文法定義でコンフリクトだらけ
システム関数を50個ほど定義してみて、テストしていると、まだ、ぜんぜん「なでしこ」に文法が追いついてないことに気づき、ちょこちょこと、文法定義を追加しています。
ただ、コンフリクトしまくりで、これが非常に大変です。む〜。
今まで、なでしこでは以下のように書けました。
今日&「*」&今を表示。 #→引数(命令+演算子+命令+演算子+命令)+命令
しかし、これができるようにすると、conflictの嵐で、正しく解析ができません。
(今日)&「*」&(今)を表示
とカッコで括れば動きます。
・・・まぁ、この例(引数に演算が混ざる)では、どうせ日本語として不自然だし、これでもいいかな?
ただし、以下のように、これを文字列に埋め込んだ場合は、正しく動きます。
「{今日} {今}」を表示。
なぜなら、埋め込みを外すときに、()で括るようにしているから。
ただ、命令の引数に命令を書くときは、よほど曖昧でない限りカッコは不要です。
今日の「-」を「/」に置換して表示。 #(引数(命令)+引数+引数+命令)して+命令
日本語らしく書くには、後置記法っぽく「引数+引数+...命令」として、
関数っぽく書くには、「命令(引数,引数,...)」という感じで書きます。
構文定義は以下のようにしています。(FUNCが普通(言い切り)の命令、FUNCARGが助詞(の、から、まで...)付の命令です。)
callfunc : expr_list FUNC { $$ = nc.callFunc($2, $1); } | FUNC { $$ = nc.callFunc($1, null); } | FUNC '(' expr_list ')' { $$ = nc.callFunc($1, $3); } expr_list : expr { $$ = nc.expr_list_top($1); } | FUNCARG { $$ = nc.callFunc($1,null); } | expr_list expr { $$ = nc.expr_list_next($1, $2); } | expr_list FUNCARG { $$ = nc.callFunc($2, $1); } expr : value | expr '*' expr { $$ = nc.expr(ANodeTypes.MUL, $1, $3); } | expr '/' expr { $$ = nc.expr(ANodeTypes.DIV, $1, $3); } ... value : variable | NUM { $$ = nc.constNum($1); } | INT { $$ = nc.constInt($1); } | STR { $$ = nc.constStr($1); } | '(' expr ')' { $$ = nc.setJosi($2,$3); } | '(' callfunc ')' { $$ = $2; }
本当は、valueの定義の中で、(callfunc)のカッコをはずしたいのです。
そうすれば、現行のなでしこと同じように書くことができます。しかし、これをやると
「4 shift/reduce conflicts, 189 reduce/reduce conflicts.」とエラーが返ってきて大変なことになります。
他には、なぜか、代入の「=」と、値比較の「=」がコンフリクトしています。