1 / 59

字句解析

字句解析. 字句解析( LexicalAnalysis ) 文字列を単語に区切る 字句解析プログラム. 字句解析. プログラミング言語   区切り記号を使って簡単に行える. 自然言語  ◎ 英語のように分かち書きされているものはかなり簡単  ◎ 日本語などは非常に困難    例:きんきだいがく → 近畿+大学                   近畿だ+医学. 字句解析. 入力文字列 write(ab,12)      ↓ Symbol [日本語] WRITE  左括弧 変数名 コンマ 整数 右括弧 Symbol [ English]

piera
Download Presentation

字句解析

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 字句解析 字句解析(LexicalAnalysis) 文字列を単語に区切る 字句解析プログラム

  2. 字句解析 • プログラミング言語   区切り記号を使って簡単に行える. • 自然言語  ◎英語のように分かち書きされているものはかなり簡単  ◎日本語などは非常に困難    例:きんきだいがく → 近畿+大学                   近畿だ+医学

  3. 字句解析 • 入力文字列 write(ab,12)      ↓ • Symbol[日本語] WRITE 左括弧 変数名 コンマ 整数 右括弧 • Symbol[English] WRITELPARENNAMECOMMAINTEGERRPAREN • トークンの文字列(name,value) write ( ab , 12 )

  4. トークンの種類 • 区切り記号: セミコロン,コンマ,,(,),{,},[,] • 演算子:==,!=,<,>,<=,>=,&&,||,!,+,-,*,/,%,= • 名前: ID[変数名,手続き名] • 定数: 整数,文字 • キーワード:if,int,main,readint, readchar,while,writeint,writechar

  5. ADD + SUB - MUL * DIV / MOD % ASSIGN = SEMICOLON ; LPAREN ( RPAREN ) LBRACE{ RBRACE} LBRACKET [ RBRACKET] COMMA , 英語

  6. ①SUB - ②MUL * ③LPAREN ( ④RBRACE    { ⑤LBRACKET[ ★Symbol[English] 誤りはどれ?

  7. ①EQUAL == ②INC ++ ③DEC       ーー ④ASSIGN== ⑤ADD  + ★Symbol[English] 誤りはどれ?

  8. 空白文字を読み飛ばす • 空白文字=' ' '\t' '\n' • write ( ab , 12 )   ↓  空白文字を読み飛ばす • write(ab,12)

  9. プログラム→トークンタイプ proceduremain; var ei,su,go; procedure gokeiKeisan; begin go := ei+ su end; begin ei := 70; su := 50; call gokeiKeisan end . 変数名 procedure名 整数値

  10. 最長一致 • 字句解析の基本=最長一致   =一番長い字句候補を選ぶ • 自然言語の例    きょうとふ → 京都府?           → 今日+戸+負? • 最長の 京都府 が正解みたい

  11. 最長一致で解決できない場合 • (東京特許許可局) • とうきょうとっきょ • 最長一致=東京都+っきょ • 2文節最長一致方式 • 東京+特許 → 正解みたい

  12. 最長一致(コンパイラの場合) 1.a<=b は a<=b でなく, a<=b   と字句解析される. 2.+++ は  +++ と字句解析される 3.+++  (空白をいれる)は +++ と字句解析される.  4.-++ は -++ と字句解析される.(-+というトークンがないため) 5.== は == でなく == と字句解析される. 6.mainab=c は mainab=c でなく, mainab=c と 字句解析される. mainabという変数名

  13. ①+++ INCADD ②ーー= DECASSIGN ③+ーー ADDDEC ④+ ++    INCADD ⑤===  EQUALASSIGN ★ 最長一致 誤りはどれ?

  14. a+++b (=a+++ b) の構文木 <exp> <term>          “+” <term> <factor> <factor> <unsigned> <unsigned> NAME “++” NAME     “a”         “b”

  15. a+++b の構文木 空白あり <exp> <term>  “+” <term> <factor> <factor> <unsigned> <unsigned> NAME      “++” NAME     “a”         “b”

  16. 字句解析オートマトン +1 + セミコロン 足し算 等しい = 代入 + ; = 0-9 INT 0-9 英字,数字,_ a-z,A-Z,_ NAME

  17. 1文字=1トークン ; セミコロン

  18. 最長一致=先読みして,決定1文字? 2文字?最長一致=先読みして,決定1文字? 2文字? =以外で確定 何でも 代入 等しい = = 1文字先読み

  19. 文字 'a'    ← '\n'   ← やらなくてよい? 'a' の値 文字コード=>整数 value=(int)'a'

  20. 文字   '?' 何でも n,t,.. ¥ ' 文字 ' ¥以外 シングルクォート シングルクォート

  21. 最長一致(名前) 英字,数字,_ NAME a-z,A-Z,_ 先読み:英字,数字,_以外      で確定

  22. 数(ゼロと非ゼロ) ゼロ 0 0-9 1-9 INTEGER 数字以外  で確定

  23. 区切り方 空白は飛ばす 先頭が数字,数字の続き, 次が改行(数字でない) • ab=c12++32 先頭が+,次も+ 先頭が=, 次の文字が英字(=でない) 先頭が英字, 英数字の続き, 次の文字が空白(英字でない) 先頭が英字, 英数字の続き, 次の文字が=(英数字でない)

  24. プログラム:記号部分 • 現在位置の文字:currentChar • 次の位置の文字:nextChar • ++ と + の区別 • if(currentChar==‘+‘) { if(nextChar==‘+‘) { token=new Token(INC); nextChar(); } else token=new Token(ADD); }

  25. プログラム:変更例 • 現在位置の文字:currentChar • 次の位置の文字:nextChar • -= と - の区別 • if(currentChar==‘-‘) { if(nextChar==‘=‘) { token=new Token(SUBASSIGN); nextChar(); } else token=new Token(SUB); }

  26. 文字  '?''\?' if(currentChar == '\'') { char ch = nextChar(); if(ch=='\\') {ch=nextChar(); if(nextChar=='\'') { if(ch=='n') value=13; else if (ch=='t') value=11; .... } } else if ( nextChar == '\'') value = (int) ch; nextChar(); ttype = CHARACTER; } '\n'など 訂正

  27. 最長一致プログラム:変数名と予約語,大文字のみ最長一致プログラム:変数名と予約語,大文字のみ • 現在位置の文字:currentChar • 変数名トークンの文字列:name • if(Character.isUpperCase(currentChar) ) { name=“”; while(Character.isUpperCase(currentChar)) { name+=currentChar; nextChar(); } } 変数名の終わりまで取り込む

  28. 変更例,大文字か小文字 • 現在位置の文字:currentChar • 変数名トークンの文字列:name • if(Character.isLowerCase(currentChar)|| Character.isUpperCase(currentChar)) { name=“”; while(Character.isLowerCase(currentChar)|| Character.isUpperCase(currentChar)) { name+=currentChar; nextChar(); } }

  29. 字句解析(2) 字句解析プログラム

  30. トークンクラス class Token { Symbol symbol; int value; String name; } トークンの種類 MAIN IF WHILE ADD SUB MUL LPAREN RBRACE 整数トークン 整数値 変数トークン 変数名

  31. プログラムの構造 ソースファイル nextChar()

  32. 方法(1)currentChar のみを用いて • 現在位置の文字:currentChar • <= と < を区別するプログラム • if(currentChar==‘<‘) { nextChar(); if(currentChar==‘=‘) { token=new Token(Symbol.GE); nextChar(); } else token=new Token(Symbol.GT); }

  33. ★ 記号 • 現在位置の文字:currentChar • += と + を区別するプログラム • if(currentChar==‘+‘) { nextChar(); if(currentChar==‘=‘) { token=new Token(Symbol.ADDASSIGN); nextChar(); } else token=new Token(Symbol.ADD); }

  34. 整数 • 現在位置の文字:currentChar • 整数トークンの文字列(数字列):name • 整数値 value • if(currentChar == '0' ) {name="0";value=0; token=new Token(Symbol.INTEGER,value)} • if(Character.isDigit(currentChar)) { name=“”; while(Character.isDigit(currentChar)) { name+=currentChar; nextChar(); } value=Integer.parseInt(name); token=new Token(Symbol.INTEGER,value); } 終わりの数字 まで取り込む

  35. 計算により整数値を求める • 現在位置の文字:currentChar • 整数トークンの文字列(数字列):name • 整数値 value • if(currentChar == '0' ) {name="0";value=0; token=new Token(Symbol.INTEGER,value)} • if(Character.isDigit(currentChar)) { value=0; while(Character.isDigit(currentChar)) { value = value * 10 + Character.digit(currentChar, 10); nextChar(); } token=new Token(Symbol.INTEGER,value); }

  36. 変数名と予約語 • 予約語は変数名として使えない main=1+2;  と書いてはいけない • 文字列を取り出したとき,予約語と一致していれば予約語,そうでなければ変数名 • whileは予約語 • while1,whilea,whilは変数名

  37. 変数名 と 予約語 • 整数とおなじように文字列を最長一致で取り出す. • 文字列:name • main などと一致すれば mainトークンなど •     そうでない時は 変数名 • if(Character.isLetter(currentChar)) { • name=“”; while(Character.isLetterOrDigit(currentChar)) { name+=currentChar; } token=new Token(Symbol.NAME,name); if(name.equals(“main”)) token=new Token(Symbol.MAIN); else if(name.equals(“read”)) token=new Token(Symbol.READ); ……..

  38. ★変数名 と 予約語 • 整数とおなじように文字列を最長一致で取り出す. • 文字列:name • main などと一致すれば mainトークンなど •     そうでない時は 変数名 • if(Character.isLetter(currentChar)) { • name=“”; while(Character.isLetterOrDigit(currentChar)) { name+=currentChar; } token=new Token(Symbol.NAME,name); if(name.equals(“main”)) token=new Token(Symbol.MAIN); else if(name.equals(“read”)) token=new Token(Symbol.READ); ……..

  39. プログラミング方法(2) • 次の文字によって,状態推移する?しない?              ↓ • nextChar の導入(currentCharの次の文字) • char lookAhead(){ return nextChar; }

  40. lookAhead()を用いて • 現在位置の文字:currentChar • 次の文字:lookAhead() • <= と < を区別するプログラム • if(currentChar==‘<‘) { if(lookAhead()==‘=‘) { token=new Token(Symbol.LE); nextChar(); } else token=new Token(Symbol.LT); }

  41. プログラミング方法(2-2) • ++と+の区別 • if(currentChar=='+'){ if(nextChar=='+'){ token=new Token(Symbol.INC); nextChar(); } else token=new Token(Symbol.ADD); }

  42. プログラミング方法(2-3) • 整数 • String str; if(Character.isDigit(currentChar)){ str=""+currentChar; while(Character.isDigit(nextChar)){ nextChar(); str += currentChar; } }

  43. プログラミング方法(3ー1) • 字句解析:有限オートマトン風       ↓ • 正規表現を利用する       ↓ • 文字単位でなく,行単位で解析する.      行の残り = line

  44. プログラミング方法(3ー2) • ++ と + の区別 • if(line.charAt(0)=='+' || line.cahrAt(1)=='+'){ token=new Token(Symbol.INC); line=line.substring(2); } else if(line.charAt(0)=='+'){ token=new Token(Symbol.ADD); line=line.substring(1); }

  45. プログラミング方法(3ー3) • 変数名 • String str; elseif(Character.isLetterOrDigit(ch0)||ch0=='_'){ substr=line.split("\\W"); str=substr[0]; line=line.substring(str.length()); if(str.equals("main")) token=new Token(Symbol.MAIN); else token=new Token(Symbol.NAME,str); } 非単語文字 \w=単語文字 a-zA-Z0-9_

  46. FileScannerクラス コンストラクタ:ファイル名を与える. ファイル終了:closeFile() ソースの一行lineをget:currentLine() 一文字切り出し:nextChar() 次の文字を返す:lookAhead() 行番号を返す:currentLineNumber()

  47. NULL MAIN IF INT EQUAL GREAT ADD SUB ASSIGN LPAREN RPAREN ・ ・ ・ ・ enumSymbol(トークンのタイプ)

  48. Tokenクラス • コンストラクタ: • LPARENなど:Symbolのみを与える • 整数など:Symbolと整数値 • 変数名:Symbolと名前の文字列 • Symbolのチェック:checkSymbol(symbol)

  49. LexicalAnalyzer • コンストラクタ: 1.ソースファイル開く sourceFileScanner=newFileScanner(fileName); 2.一文字読み込む nextChar(); • currentChar:現在位置の文字とする • token:nextToken()が返すトークン

  50. 字句切り出し:nextToken()の全体像 Token nextToken(){ // 空白文字を読み飛ばす while(currentChar==' ' || currentChar=='\n' || currentChar=='\t') nextChar(); //EOF if(currentChar=='\0') return new Token(Symbol.EOF);  ・ ・ ・ ・ ・ ・  トークンの決定 ・ ・ ・ ・ ・ // 決まらないときはNULLとする.(エラーとする?) elsetoken= new Token(Symbol.NULL); // 次の文字を読み込む nextChar(); // 決定したトークンを返す returntoken;   }

More Related