Microsoft PowerPoint - Compiler06note.pptx

Similar documents
Microsoft PowerPoint - Compiler06.pptx

Microsoft PowerPoint - Compiler05.pptx

Microsoft PowerPoint - Compiler05note.pptx

Microsoft Word - Javacc.docx

Microsoft PowerPoint - Compiler10note.pptx

Microsoft PowerPoint - Compiler04note.ppt [互換モード]

Microsoft PowerPoint - Compiler04note.ppt [互換モード]

Microsoft PowerPoint - Compiler04note.ppt [互換モード]

Java講座

Microsoft PowerPoint - Compiler03note.pptx

Microsoft PowerPoint - 04SyntaxAnalysis.ppt [互換モード]

Microsoft PowerPoint - Compiler15note.ppt [互換モード]

PowerPoint プレゼンテーション

Java プログラミング Ⅰ 7 回目 switch 文と論理演算子 今日の講義講義で学ぶ内容 switch 文 論理演算子 条件演算子 条件判断文 3 switch 文 switch 文 式が case のラベルと一致する場所から直後の break; まで処理しますどれにも一致致しない場合 def

Microsoft PowerPoint - Compiler03.pptx

Java プログラミング Ⅰ 7 回目 switch 文と論理演算子 条件判断文 3 switch 文 switch 文式が case の値と一致した場合 そこから直後の break; までを処理し どれにも一致しない場合 default; から直後の break; までを処理する 但し 式や値 1

Microsoft PowerPoint - Compiler01note.pptx

Microsoft Word - problem3.doc

Microsoft PowerPoint - 3.ppt [互換モード]

文法と言語 ー文脈自由文法とLR構文解析2ー

Microsoft PowerPoint - 03BNFScanner.ppt [互換モード]

Microsoft PowerPoint ppt

言語プロセッサ2005 -No.6-

break 文 switch ブロック内の実行中の処理を強制的に終了し ブロックから抜けます switch(i) 強制終了 ソースコード例ソースファイル名 :Sample7_1.java // 入力値の判定 import java.io.*; class Sample7_1 public stati

JavaプログラミングⅠ

第12回 モナドパーサ

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

プログラミングA

問 次の Fortran プログラムの説明及びプログラムを読んで、設問に答えよ。

Microsoft Word - problem5.doc

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤

1 (2 * 3) 1 2 * 3 Preorder In order Post order 1 * 1 * Breadth-first Depth-first * * 3 Preorder: 1 * 2 3 In order: 1 2 * 3 Post orde

JavaプログラミングⅠ

Prog1_6th

Java プログラミング Ⅰ 3 回目変 数 今日の講義講義で学ぶ内容 変数とは 変数の使い方 キーボード入力の仕方 変 数 変 数 一時的に値を記憶させておく機能 変数は 型 ( データ型 ) と識別子をもちます 2 型 ( データ型 ) 変数に記憶する値の種類変数の型は 記憶できる値の種類と範囲

Microsoft PowerPoint - 03BNFScanner-print.ppt

解きながら学ぶJava入門編

オブジェクト指向プログラミング・同演習 5月21日演習課題

デジタル表現論・第4回

Microsoft Word - NonGenTree.doc

Microsoft Word - CompA-Ex doc

Microsoft PowerPoint - prog03.ppt

Microsoft PowerPoint - OOP.pptx

Microsoft PowerPoint - C_Programming(3).pptx

Microsoft Word - NonGenList.doc

K227 Java 2

プログラミングA

r02.dvi

ohp02.dvi

Microsoft PowerPoint ppt

プログラミングA

Javaによるアルゴリズムとデータ構造

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

メソッドのまとめ

nlp1-04a.key

8 if switch for while do while 2

基礎計算機演習 実習課題No6

プログラミング入門1

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

Javaプログラムの実行手順

情報実習Ⅱ

JavaプログラミングⅠ

2

Prog1_3rd

Exam : 1z1-809-JPN Title : Java SE 8 Programmer II Vendor : Oracle Version : DEMO Get Latest & Valid 1z1-809-JPN Exam's Question and Answers 1 from Ac

Prog1_10th

文字列操作と正規表現

slide5.pptx

人工知能入門

Prog1_15th

18/12/06 情報工学実験 C コンパイラ (2018 年度 ) 担当 : 笹倉 佐藤 その 3 yacc の構造 定義部 %% 定義部の終了 規則部 %% 規則部の終了 ユーザ定義サブルーチン部 :C のプログラムを書く 形は lex と同じ 1

2

プログラミング入門1

JavaプログラミングⅠ

問 次の Fortran プログラムの説明及びプログラムを読んで、設問に答えよ。

Prog2_9th

Java演習(4) -- 変数と型 --

2

新・明解Java入門

Microsoft PowerPoint - 05LLprint.ppt [互換モード]

Microsoft PowerPoint - ruby_instruction.ppt

プログラミング基礎I(再)

Microsoft PowerPoint - 08LR-conflicts.ppt [互換モード]

Prog2_12th

問題1 以下に示すプログラムは、次の処理をするプログラムである

(Microsoft PowerPoint - \223\306\217KJAVA\221\346\202R\224\ ppt)

untitled

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

Javaセキュアコーディングセミナー東京 第3回 入出力(File, Stream)と例外時の動作 演習解説

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

プログラミング入門1

構文解析表の作成講義でも少し触れましたが 各選言で先頭に出現する可能性がある終端記号の集合 のことを DIRECTOR 集合とよびます DIRECTOR は direction( 方向 ) を決定するという意味を持っており LL(k) 構文解析器が非終端記号を解析する際に そのうちどの選言を利用する

: gettoken(1) module P = Printf exception End_of_system (* *) let _ISTREAM = ref stdin let ch = ref ( ) let read () = (let c =!ch in ch := inp

プログラミング入門1

Microsoft PowerPoint - 計算機言語 第7回.ppt

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

ガイダンス

スライド 1

PowerPoint プレゼンテーション

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

Transcription:

コンパイラ 第 6 回構文解析 構文解析プログラムの作成 http://www.info.kindai.ac.jp/compiler 38 号館 4 階 N-411 内線 5459 takasi-i@info.kindai.ac.jp コンパイラの構造 字句解析系 構文解析系 制約検査系 中間コード生成系 最適化系 目的コード生成系 処理の流れ情報システムプロジェクト I の場合 output (ab); 字句解析系 output ( 変数名 ) ; 構文解析系 マイクロ構文の文法に従い解析 マクロ構文の文法に従い解析 <output_statement> ::= output ( <exp> ) ; コード生成系 VSM アセンブラの文法に従い生成 1. PUSH &ab 2. OUTPUT 構文解析系 (syntax analizer, parser) 構文解析系 if 文 構文解析木を作成 if ( 式 ) 文 if (ans > 123 ) output ( 1 ) ; 式 > 式出力文 変数 整数 output ( 式 ) ; ans 123 文字 1 構文解析 下降型解析 (top-down parsing) 上昇型解析 (bottom-up parsing) 情報システムプロジェクト I の構文解析 再帰下降解析 (recursive descent parsing) LL 解析 (Left to right scan & Left most derivation) 演算子順位構文解析 (operator precedence parsing) LR 解析 (Left to right scan & Right most derivation) プログラムの構造 ( 構文解析系 ) FileScanner.java ファイル探査部 LexicalAnalyzer.java 字句解析部 Kc.java 構文解析部 char Token char nextchar(); Token nexttoken(); void parse<a>(); //1 文字読み込む // トークンを切り出す // 非終端記号 <A> を // 解析をする k19 言語原始プログラム Token.java トークン定義部 boolean checksymbol (Symbol); // トークンを識別する 1

Kc クラス Kc # 構文解析部 - lexer : LexicalAnalyzer # 字句解析器 - token : Token # 読み取りトークン Kc (sourcefilename : String) # コンストラクタ parseprogram() : void # <Program> の解析 parsemainfunction() : void # <MainFuntion> の解析 parseblock() : void # <Block> の解析 parsevar_decl() : void # <Var_decl> の解析 : : closefile () : void # 入力ファイルを閉じる - syntaxerror (message : String) : void # エラー検出時の処理 + main (args : String[]) : void # メイン 構文解析プログラム 非終端記号ごとに解析用メソッドを作成 例 : 非終端記号 <A> の解析 void parse<a> () { if ( トークン列が <A> のマクロ構文と合致 ) { <A> のコード生成 ; /* マクロ構文と一致しなかった場合はエラー */ 構文解析部 構文解析部のプログラム Token token; Token nexttoken(); // 現在読み込み中のトークン // 次のトークンを読み込む 例 <decl> ::= int NAME ; の解析 void parsedecl () { マクロ構文と合致しているか? if (token == int ) 合致すれば次のトークンを読み込む if (token == NAME ) if (token == ; ) 合致しなければ構文エラー Token クラス Token # トークン定義部 - symbol : Symbol # トークンの種類 - intvalue : int # トークンの値 - strvalue : String # トークンの名前 Token (symbol : Symbol) # コンストラクタ Token (symbol : Symbol, intvalue : int) # コンストラクタ Token (symbol : Symbol, strvalue : String) # コンストラクタ checksymbol (symbol : Symbol) : boolean # トークンの種類を比較 getsymbol () : Symbol # トークンの種類を返す getintvalue () : int # トークンの値を返す getstrvalue () : String # トークンの名前を返す Token クラス class Token { Symbol symbol; /* トークンの種類 */ int intvalue; /* 整数値または文字コード */ String strvalue; /* 変数名 */ トークン symbol intvalue strvalue main MAIN == EQUAL 123 PINTEGER 123 a CHARACTER 97 ( a の文字コード ) time NAME time トークンの判定 トークンの一致判定は Token.checkSymbol (Symbol) を利用 boolean checksymbol (Symbol symbol) 例 : トークンが + か? token.checksymbol (Symbol.ADD) 2

値を持つトークン 値を持つトークン 整数 ( 整数値 ) 文字 ( 文字コード ) 変数名 ( 文字列 ) intvalue フィールドの値を得る int getintvalue() strvalue フィールドの値を得る String getstrvalue() int val = token.getintvalue(); トークンの値は制約検査部 コード生成部で必要 構文解析部 例 <decl> ::= int NAME ; の解析 void parsedecl () { if (token.checksymbol (Symbol.INT)) if (token.checksymbol (Symbol.NAME)) if (token.checksymbol (Symbol.SEMICOLON)) 非終端記号 <A> の解析 1. <A> ::= ε のとき何もしない 2. <A> ::= a ( T) のとき if (token == a ) 非終端記号 <A> の解析 3. <A> ::= <B> ( N) のとき 1. ε First (<B>) のとき 2. ε First (<B>) のとき この判定には <B> の First 集合が必要 if (token First (<B>)) parse<b>(); <B> 解析メソッドへ if (token (First (<B>)-ε)) parse<b>(); else 節無し 非終端記号 <A> ( 分岐 ) の解析 4. <A> ::= β 1 β 2 β 3 ε のとき if (token First (β 1 )) { β 1 の解析 ; else if (token First (β 2 )) { β 2 の解析 ; else if (token First (β 3 )) { β 3 の解析 ; else ; εに対応 ε あり 非終端記号 <A> ( 分岐 ) の解析 4. <A> ::= β 1 β 2 β 3 のとき ε 無し if (token First (β 1 )) { β 1 の解析 ; else if (token First (β 2 )) { β 2 の解析 ; else if (token First (β 3 )) { β 3 の解析 ; 合致しなければ構文エラー 3

非終端記号 <A> ( 分岐 ) の解析 4. <A> ::= β 1 β 2 β 3 ε のとき switch (token) { case First (β 1 ) : β 1 の解析 ; break; case First (β 2 ) : β 2 の解析 ; break; case First (β 3 ) : β 3 の解析 ; break; default : break; εに対応 εが無い場合は default : syntaxerror(); 非終端記号 <A> ( 連接 ) の解析 5. <A> ::= β 1 β 2 β 3 のとき β 1 の解析 ; β 2 の解析 ; β 3 の解析 ; 非終端記号 <A> ( 閉包 ) の解析 6. <A> ::= {β のとき while (token First (β)) { βの解析 ; 非終端記号 <A> ( 省略 ) の解析 7. <A> ::= [β] のとき if (token First (β)) { βの解析 ; は付けない 非終端記号 <A> ( 括弧 ) の解析 6. <A> ::= (β) のとき β の解析 ; 非終端記号解析の例 例 : <MainFunction> ::= main ( ) <Block> parsemainfunction() { if (token == main ) else syntaxerror (); 終端記号なら次のト if (token == ( ) else syntaxerror (); if (token == ) ) else syntaxerror (); if (token First (<Block>)) parseblock(); else syntaxerror (); この判定には <Block> のFirst 集合が必要 終端記号なら次のトークンを読む 非終端記号なら対応するメソッドへ 4

非終端記号解析の例 ( 分岐 ) 例 : <Factor> ::= NAME INTEGER CHARACTER input parsefactor() { switch (token) { case NAME : break; case INTEGER : break; case CHARACTER : break; case input : break; default : syntaxerror (); εに対応 非終端記号解析の例 ( 閉包 ) 例 : <Block> ::= { { <Decl> { <St> parseblock() { if (token == { ) while (token First (<Decl>)) parsedecl(); // { <Decl> while (token First (<St>)) parsest(); // { <St> if (token == ) この判定には <Decl>, <St> のFirst 集合が必要 非終端記号解析の例 ( 閉包 ) 例 : <Block> ::= { { <Decl> { <St> First (<Decl>) = { int First (<St>) = { if, while, NAME, INTEGER, output, parseblock() { if (token == { ) while (token == int ) parsedecl(); while (token == if token == while token == NAME token == INTEGER token == output ) parsest(); if (token == ) First 集合の判定要素数が多い First (<St>) = { if, while, break, output, First (<Exp>) = {INTEGER, NAME, output, ++, 要素数が多い場合は判定用メソッドを作っておくと便利 /* token が <St> の First 集合なら true を返す */ boolean isstfirst (Token token) { return (token == if token == while token == break token == output ); 非終端記号解析の例 ( 省略 ) 例 : <Decl> ::= int NAME [ = <Const> ] ; parsedecl() { if (token == int ) else syntaxerror (); if (token == NAME) else syntaxerror (); if (token == = ) { if (token First (<Const>)) parseconst(); else syntaxerror (); else syntaxerror() は付けない [] 内の解析 if (token == ; ) 左再帰性のある場合の解析 左再帰 例 : <Term> ::= <Tetm> + <Factor > <Factor> このままプログラムすると parseterm() { if (token First (<Term>)) { 左再帰性があると parseterm(); 無限ループに陥る if (token == + ) if (token First (<Factor>)) parsefactor(); else if (token First (<Factor>)) parsefactor(); 5

左再帰性のある場合の解析 例 : <Term> ::= <Tetm> + <Factor > <Factor> 左再帰性の除去を行う 右再帰に <Term> ::= <Factor> <T > <T > ::= + <Factor > <T > ε <Term> ::= <Factor> { + <Factor > EBNF 記法に 左再帰性のある場合の解析右再帰に : <Term> ::= <Factor> <T > <T > ::= + <Factor > <T > ε parseterm() { if (token First (<Factor>)) parsefactor(); if (token == + ) parset (); parset () { if (token == + ) { if (token First (<Factor>)) parsefactor(); if (token == + ) parset (); 左再帰性のある場合の解析 EBNF 記法に : <Term> ::= <Factor > { + <Factor> parseterm() { if (token First (<Factor>)) parsefactor(); while (token == + ) { if (token First (<Factor>)) { 内の解析 parsefactor(); 同一の接頭部を持つ場合の解析 例 : <Term> ::= <Factor > + <Term> <Factor> このままプログラムすると 同一の接頭部 parseterm() { if (token First (<Factor>)) { 同一の条件式 parsefactor(); if (token == + ) if (token First (<Term>)) parseterm(); else if (token First (<Factor>)) parsefactor(); 絶対にこの分岐には入らない 同一の接頭部を持つ場合の解析 例 : <Term> ::= <Factor> + <Term> <Factor> 左括り出しを行う 左括り出し <Term> ::= <Factor> [ + <Term> ] 同一の接頭部を持つ場合の解析 左括り出し : <Term> ::= <Factor > [ + <Term> ] parseterm() { if (token First (<Factor>)) parsefactor(); if (token == + ) { if (token First (<Term>)) [] 内の解析 parseterm(); 6

同一の接頭部を持つ場合の解析 例 : <Term> ::= <Factor> + <Term> <Factor> - <Term> <Factor> 左括り出し <Term> ::= <Factor> [ + <Term> - <Term>] ここもまとめる <Term> ::= <Factor> [ ( + - ) <Term>] 同一の接頭部を持つ場合の解析 <Term> ::= <Factor > [ ( + - ) <Term> ] parseterm() { if (token First (<Factor>)) parsefactor(); if (token == + token == - ) { if (token First (<Term>)) parseterm(); [] 内の解析 構文解析時のエラー処理 入力がマクロ構文と一致しなかった 構文解析エラー parsemainfunction() { if (token == main ) else syntaxerror ( main がありません ); if (token == ( ) else syntaxerror ( ( がありません ); if (token == ) ) else syntaxerror ( ) がありません ); if (token First (<Block>)) parseblock(); else syntaxerror (First (<Block>) + がありません ); エラー検出時はエラーメッセージを表示して停止 構文解析時のエラー処理 エラー検出時はエラーメッセージを表示して停止 private void syntaxerror (String err_mes) { System.out.println (analyzeat() + でエラー検出 ); /* LexicalAnalyzer の analyzeat() を用いてエラー位置表示 */ System.out.println (err_mes); /* エラーメッセージ表示 */ closefile (); /* 入力ファイルを閉じる */ System.exit (0); /* プロクラム停止 */ エラー箇所およびエラー原因がユーザに分かり易いエラーメッセージを作成する プログラム末到達時の処理 プログラム末到達時にファイル末ならばコンパイル完了 void parseprogram () { if (token First (<MainFunction>)) parsemainfunction(); else syntaxerror (); ファイル末を示すトークン if (token == EOF) { コンパイル完了処理 else syntaxerror ( ファイル末ではありません ); デバグ用に static final boolean DEBUG = false; void parse<a> () { : if (DEBUG) System.out.println ( /* デバグ情報を出力 */ ); : DEBUG = true; として実行するとデバグ情報出力 ( デバガがあるなら不要 ) 7

トレース機能 static final boolean TRACE = false; int level = 0; void parse<a> () { ++level; if (TRACE) { for (int i=0; i<level; ++i) System.out.print ( ); System.out.println ( <A> (<A> 開始 ); // <A> 解析 if (TRACE) { for (int i=0; i<level; ++i) System.out.print ( ); System.out.println ( <A> 終了 ); --level; トレース機能 % java kc.kc foo.k program 開始 main 開始 ver_decl 開始 ver_decl 終了 statement 開始 if_statement 開始 exp 開始 トレース機能があると ( ユーザにとって ) 便利 : LL(1) 文法 LL(1) 文法 1 個のトークン ( 直後に来るトークン ) の先読みで構文解析可能な文法 左辺が同じ生成規則が複数あるとき トークンを 1 個先読みすればどの右辺を選択するかわかる 同一の左辺に対して 右辺の先頭トークン ( 終端記号 ) が全て異なる 次に来るトークンを先読みするメソッドがあれば解析可能 構文解析不能な文法 例 : First (α) = { x, a First (β) = { x, b Firsr (γ) = { x, c <A> ::= α β γ <B> ::= {αβ <C> ::= [α] β <A> <B> <C> 共に先頭の終端記号が x だとどの分岐か判定できない 左括り出しも難しい LL(1) 文法でないとバックトラック無しでは構文解析不能 バックトラックありの構文解析 構文解析メソッドを boolean 型に 解析完了 true 解析失敗 false 返り値が false ならば次の導出パターンへ /* <A> の構文解析を行う構文解析を完了できれば true を返す */ boolean parse<a> () { if ( トークン列が <A> のマクロ構文と合致 ) { return true; // 構文解析完了 else { return false; // 構文解析失敗 バックトラックありの構文解析 字句解析器から1 度に全てのトークンを読み込む tokenlist int loc 0 main 現在のマーク位置 1 ( loc LexicalAnalyzer 2 do { tokenlist [i] = token; ++i; while (token!= $ ); 2 3 4 5 6 7 ) { int a, b ファイル末を示すトークン 8

バックトラックありの構文解析部 int loc; // 現在のマーク位置 /* マーク位置を 1 つ進める */ void proceed() { ++loc; token = tokenlist [loc]; /* マーク位置を指定の位置に戻し 生成したコードを削除する */ void backtrack (int backpoint) { tokenlist [backpoint +1 ] ~ tokenlist [loc] のコードを削除 loc = backpoint; token = tokenlist [loc]; バックトラックありの構文解析部 構文解析部のプログラム int loc; // 現在のマーク位置 void proceed(); // マーク位置を1つ進める void backtrack(); // マークを指定の位置に戻し コードを削除する /* <A> の構文解析を行う構文解析を完了できれば true を返す */ boolean parse<a> () { : proceed(); return true; // 構文解析完了 : backtrack (backpoint); return false; // 構文解析失敗 開始位置まで戻る バックトラックありの構文解析の例 文末を示すトークン 生成規則 <E> ::= <T> $ <F> $ <T> ::= <F> + <F> <F> ::= a b c First (<T>) = { a, b, c First (<F>) = { a, b, c First 集合で判定できない バックトラック無しには構文解析不能 バックトラックありの構文解析の例 生成規則 <E> ::= <T> $ <F> $ <T> ::= <F> + <F> <F> ::= a b c boolean parsef(){ if (token == a token == b token == c ) { proceed(); // マーク位置を1つ先へ return true; // 解析完了 <F> ::= a b else return false; // 解析失敗 バックトラックありの構文解析 <T> ::= <F> + <F> boolean parset(){ if (token == + ) { proceed(); return true; // 解析完了 <T> ::= <F> + <F> else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; マークを初期位置に戻す バックトラックありの構文解析 // <E> ::= <T> $ の解析 <E> ::= <T> $ else backtrack (backpoint); // 解析失敗, バックトラック マークを初期位置に戻す // <E> ::= <F> $ の解析 <E> ::= <F> $ else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; 9

else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; 10

else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; 構文解析完了 else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; 開始位置に戻る proceed(); return if (token true; == + ) // 解析完了 { else backtrack (backpoint); proceed(); // 解析失敗 return true; // 解析完了 else { backtrack (backpoint); return proceed(); false; return true; // 解析完了 else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else { backtrack else (backpoint); { backtrack return (backpoint); false; return false; else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; 11

else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; else backtrack (backpoint); // 解析失敗 else { backtrack (backpoint); return false; else { backtrack (backpoint); return false; 構文解析完了 12