言語理論とコンパイラ

第十回: 上向き構文解析の実装

2013 年 6 月 21 日

http://www.sw.it.aoyama.ac.jp/2013/Compiler/lecture10.html

Martin J. Dürst

AGU

© 2005-13 Martin J. Dürst 青山学院大学

今日の予定

make の活用

bison の入力形式の一例

%{
#include <stdio.h>
#define YYSTYPE double
int yylex (void);
void yyerror (char const *);
%}
%token NUM PLUS

%%
statement: exp { printf ("Result is %g\n", $1); }
;

exp:      exp PLUS exp { $$ = $1 + $3; }
        | NUM { $$ = $1; }
;

%%
int main (void)
{    return yyparse ();  }
     
void yyerror (char const *s)
{    fprintf (stderr, "%s\n", s);  }

 

bison の入力形式の骨格

宣言など
%{ C 言語の宣言など %}
%%
書換規則    { 実行文 (C 言語) }
書換規則    { 実行文 (C 言語) }
書換規則    { 実行文 (C 言語) }
%%
関数など (C 言語)
関数など (C 言語)

 

bison の入力形式の構造

bison 専用の指示と C プログラムの一部分が混在

主に、二つの %% で区切られている三つの部分からなる:

  1. 準備・設定部分:
    C の #include、グローバル変数の定義と初期化、良く使う字句の定義など
    C 言語の部分は %{ ... %} に囲む
  2. 書換規則とその場合に実行するプログラムの断片
  3. 残りの C のプログラム (関数など)

C 言語そのものと違って、改行、字下げが解釈を左右

 

bison の書換規則の書式

実例:

exp: exp PLUS exp { $$ = $1 + $3; }
   | NUM { $$ = $1; }
;

文法:

書換規則 → 非終端記号 ":" 右辺列 ";" 右辺列 → 右辺 | 右辺 "|" 右辺列 右辺 → 記号列 "{" C言語 "}" 記号列 → 記号 | 記号 記号列 記号 → 非終端記号 | 終端記号

属性文法

(attribute(d) grammar(s))

 

flexbison の使い方の概要

bison の開発のコツ

calc 用テストファイル: test.in, test.check

bison の仕組みとデバッグ

曖昧な文法

 

文法の曖昧性の除去

問題の例:

E → E '-' E | integer

入力 4 - 5 - 7 に対して複数の解析木が作成可能

解析木によって計算結果が違う

解決方法: 文法の書き換え (左結合の場合)

E → E '-' integer | integer

優先度の取扱い

 

結合方向の取扱い

宿題

提出: 来週の木曜日 (6 月 27日) 19 時 00 分、O 棟 529 号室の前

calc.y を、test.in から test.check になるように完成

calc.y を A4 (両面印刷、表紙なし、左上ホチキス止め、名前と学生番号をコメントに記述) で提出

問題点: 出力の改行の差

対応: 改行記号の統一 (notepad2 で File → Line Endings → Unix (LF)); .lex[ \t\n][ \t\n\r] に拡張