私の言語で私は書くことができます
a = 1
b = 2
if true { } else { }
if true { } **Here is the problem**
else {}
私のグラマーは、ステートメント間の改行をサポートしていません。else は if でのみ使用できます。ルールにoptionalNLを追加すると
IfExpr:
IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock
else の前の optionalNL は、3 つの reduce/reduce を引き起こします。理由は、IfExpr の 2 番目のルールを使用して削減できるか、式の間に多くの改行を許可する exprLoop に削減できるためです。
私が何をしても (optionalNL と ELSE の前に %prec を書いてみました)、常に exprLoop に縮小されます。削減する代わりに、この時点で (optionalNL else に) シフトするように bison に指示するにはどうすればよいですか? (exprLoop に、else をエラーにします)。
テストするサンプルファイル
%%
program:
exprLoop;
exprLoop:
exprLoop2 expr
| exprLoop2
exprLoop2:
| exprLoop2 expr EOS
| exprLoop2 EOS
;
expr:
'i' Var optEOS '{' '}'
| 'i' Var optEOS '{' '}' optEOS 'e' '{' '}'
EOS: '\n' ;
Var: 'v';
optEOS: | optEOS EOS
%%
//this can be added to the lex file
[iev] { return *yytext; }
y.output http://www.pastie.org/707448
代替 .y および出力。\n を見て先を見越しており、ルールを縮小するか続行するかはわかりません。ルールの順序を変更して、異なる結果を取得します。しかし、常に \n を期待するか、常に else を期待するため、1 つのルールは常に無視されます。状態 15
9 expr: 'i' Var optEOS '{' '}' . [$end, '\n']
10 | 'i' Var optEOS '{' '}' . 'e' '{' '}'
11 | 'i' Var optEOS '{' '}' . '\n' 'e' '{' '}'
'e' shift, and go to state 16
'\n' shift, and go to state 17
'\n' [reduce using rule 9 (expr)]
$default reduce using rule 9 (expr)
Kinopiko さん、ご回答ありがとうございます。
私は彼のコードを競合がないように変更し、より柔軟にすることに取り組みました。ここに私のファイルがあります
test.y
%{
#include <stdio.h>
%}
%%
program: expr { printf ("First expr\n"); }
| program expr { printf ("Another expr\n"); }
expr:
if optEOS { printf ("IF only\n"); }
| if optEOS else optEOS { printf ("IF/ELSE\n"); }
if: 'i' Var optEOS '{' optEOS '}'
else: 'e' optEOS '{' optEOS '}'
EOS: '\n'
Var: 'v'
optEOS:
| EOS optEOS { ;}//printf ("many EOS\n"); }
%%
int main(int argc, char **argv)
{
int i;
printf("starting\n");
if(argc < 2) {
printf("Reading from stdin\n");
yyparse();
return 0;
}
for(i = 1; i < argc; i++) {
FILE *f;
char fn[260];
sprintf(fn, "./%s", argv[i]);
f = fopen(fn, "r");
if(!f) {
perror(argv[i]);
return (1);
}
printf("Running '%s'\n", argv[i]);
yyrestart(f);
yyparse();
fclose(f);
printf("done\n");
}
return 0;
}
test.y
%{
#include <stdio.h>
#include "y.tab.h"
%}
%option noyywrap
%%
[ \t] { }
\n { return *yytext; }
. { return *yytext; }
%%
int yyerror ()
{
printf ("syntax error\n");
exit (1);
}
コンパイル後に自動実行されるテスト ファイル
i v { }
i v { }
e { }
i v { }
e { }
i v {
} e {
}
i v { }
i v { } i v { } e { }
i v
{ } i v { } e { } i v { } e {
} i v {
} e
{ }