•
何をトークンとして扱うか–
終端記号はすべてトークン–
基本言語仕様のうち正規表現で書けるものは トークンとしてlex
で切り出す基本言語仕様
<プログラム> ::= <変数宣言部> <文集合>
<変数宣言部> ::= <宣言文> <変数宣言部> | <宣言文>
<宣言文> ::= define <識別子>; | array <識別子> [<数>];
<文集合> ::= <文> <文集合>| <文>
<文> ::= <代入文> | <ループ文> | <条件分岐文>
<代入文> ::= <識別子> = <算術式>; <識別子> [ <数> ] = <算術式>;
<算術式> ::= <算術式> <加減演算子> <項> | <項>
<項> ::= <項> <乗除演算子> <因子> | <因子>
<因子> ::= <変数> | (<算術式>)
<加減演算子> ::= + | -
<乗除演算子> ::= * | /
<変数> ::= <識別子> | <数> | <識別子>[<数>]
<ループ文> ::= while (<条件式>) { <文集合> }
<条件分岐文> ::= if (<条件式>) { <文集合> } | if (<条件式>) { <文集合> } else { <文集合> }
<条件式> ::= <算術式> <比較演算子> <算術式>
<比較演算子> ::= == | '<' | '>'
<識別子> ::= <英字> <英数字列> | <英字>
<英数字列> ::= <英数字> <英数字列>| <英数字>
<英数字> ::= <英字> | <数字>
<数> ::= <数字> <数> | <数字>
<英字> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|
T|U|V|W|X|Y|Z
<数字> ::= 0|1|2|3|4|5|6|7|8|9
この線から下は
lex
で基本言語仕様
<プログラム> ::= <変数宣言部> <文集合>
<変数宣言部> ::= <宣言文> <変数宣言部> | <宣言文>
<宣言文> ::= define <識別子>; | array <識別子> [<数>];
<文集合> ::= <文> <文集合>| <文>
<文> ::= <代入文> | <ループ文> | <条件分岐文>
<代入文> ::= <識別子> = <算術式>; <識別子> [ <数> ] = <算術式>;
<算術式> ::= <算術式> <加減演算子> <項> | <項>
<項> ::= <項> <乗除演算子> <因子> | <因子>
<因子> ::= <変数> | (<算術式>)
<加減演算子> ::= + | -
<乗除演算子> ::= * | /
<変数> ::= <識別子> | <数> | <識別子>[<数>]
<ループ文> ::= while (<条件式>) { <文集合> }
<条件分岐文> ::= if (<条件式>) { <文集合> } | if (<条件式>) { <文集合> } else { <文集合> }
<条件式> ::= <算術式> <比較演算子> <算術式>
<比較演算子> ::= == | '<' | '>'
<識別子> ::= <英字> <英数字列> | <英字>
<英数字列> ::= <英数字> <英数字列>| <英数字>
<英数字> ::= <英字> | <数字>
<数> ::= <数字> <数> | <数字>
<英字> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|
T|U|V|W|X|Y|Z
<数字> ::= 0|1|2|3|4|5|6|7|8|9
具体的には赤字がトークン
あとはこの線より上の終端記号がトークン
トークン
•
それぞれのトークンごとに種類を分ける例:識別子,数,プラス記号,マイナス記号,
define, array ….
•
今はまだyacc
のアクションを書かないので型 について考える必要はない• lex
もトークンの名前をreturn
するだけでよい非終端記号の名前
(本来なんでもいいのだが,時間がないので例を示す)
<
プログラム> program
<
変数宣言部> declarations
<
宣言文> decl_statement
<
文集合> statements
<
文> statement
<
代入文> assignment_stmt
<
算術式> expression
<
項> term
<
因子> factor
<
加減演算子> add_op
<
乗除演算子> mul_op
<
変数> var
<
ループ文> loop_stmt
<
条件分岐文> cond_stmt
<
条件式> condition
<
比較演算子> cond_op
基本言語仕様にあるそれ以外 の非終端記号は
lex
で処理して トークンになってしまうのでyacc
ファイルでの非終端記号として は扱わない言語仕様を拡張してこれ以外 の非終端記号を導入するとき はその名前は自分たちで考え ること
これらの名前を
yacc
ファイルで 使うトークン名 ( 普通は大文字を使う)
(本来なんでもいいのだが,時間がないので例を示す.)
define DEFINE
array ARRAY
while WHILE
if IF
else ELSE
; SEMIC
[ L_BRACKET
] R_BRACKET
( L_PARAN
) R_PARAN
{ L_BRACE
} R_BRACE
= ASSIGN
+ ADD
- SUB
* MUL
/ DIV
== EQ
< LT
> GT
<識別子> IDENT
<数> NUMBER
言語仕様を拡張してこれ以外 のトークンを導入するときはそ の名前は自分たちで考えるこ と
これらが
lex
からのreturn
値になる
lex ファイル(ひながた)
(
定義部省略)%%
"define" return DEFINE;
"array" return ARRAY;
…(
中略)…
整数の正規表現
return NUMBER;
識別子の正規表現
return IDENT;
空白タブ改行