2013 年 6 月 7日
http://www.sw.it.aoyama.ac.jp/2013/Compiler/lecture8.html
© 2005-13 Martin J. Dürst 青山学院大学
flex
の宿題:
コメントや実数のための正規表現読みやすさのため、コメントを /x x/
にし、スペースを使用
第一案: /x .* x/
問題: /xx/ /xx/
をまとめて認識
第二案: /x [^x]* x/
問題: /xxx/
を認識しない
第三案: /x ([^x]|x[^/])* x/
問題: /x xx/ /x
x/
をもとめて認識
第四案: /x ([^x]|x+[^/])* x/
問題: 以前と同様
第五案: /x ([^x]|x+[^/x])* x/
問題: /x xx/
を認識しない
第六案: /x ([^x]|x+[^/x])* x+/
完成!
参考: Mastering Regular Expressions, Jeffrey E.F. Friedl, pp. 168,...
バックトラックの遅さへの対策:
次のトークンしか見なくてよい文法に限定した方が望ましい
|
) がある場合、枝分かれ
(if
など) で対応while
など) で対応A → variable '=' A | integer
(代入式/assignment
operation)プログラム: scanner.h, scanner.c, parser1.c
コンパイルと実行: gcc scanner.c parser.c &&
./a
(scanner.c 参照)
nextChar
に保持
(one-character lookahead)nextChar
に読み込むnextChar
がグローバル変数だが、グローバル変数なしの実装も可能initScanner
で初期化getNextToken
で次々とトーケンを読むgetNextToken
の実装:
(parser1.c 参照)
nextToken
に保持
(one-token lookahead)nextToken
に読み込むnextToken
がグローバル変数だが、グローバル変数なしの実装も可能initScanner
と getNextToken
で準備Expression()
) を呼び出すnextToken
と比較(left recursion)
左再帰の例:
E → E '-' integer | integer
間違った解消 (結合規則が違う):
E → integer '-' E | integer
解消の結果:
E → integer EE
EE → '-' integer EE | ε
これに相当する EBNF:
E → integer {'-' integer}
文法:
正規表現:
正規表現の (簡単な) 規則は文法の (複雑な) 規則一つに相当する
Factor → FunctionCall | Variable | ArrayElement(
FunctionCall → Identifier '(' Parameters ')'
Variable → Identifier
ArrayElement → Identifier '[' Expression ']'
Factor
でどこの規則を選べば良いのか不明) 解析方法によって、文法への条件が増える:
⇒ 文法は言語を定義するだけでは不十分
→上向き構文解析 (bottom-up parsing)
bison
の演習のためノートパソコンを持参