Dans ma langue, je peux écrire
a = 1
b = 2
if true { } else { }
if true { } **Here is the problem**
else {}
Ma grammaire ne prend pas en charge les retours à la ligne entre les déclarations. Un else ne peut être utilisé qu'avec un if. Lorsque j'ajoute optionalNL dans ma règle
IfExpr:
IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock
L'optionNL avant le else provoque 3 réductions/réductions. La raison en est qu'il peut réduire en utilisant la deuxième règle de IfExpr ou réduire en exprLoop où il permet de nombreuses nouvelles lignes entre les expressions.
Peu importe ce que je fais (j'ai essayé d'écrire %prec avant optionalNL et ELSE), il se réduit toujours à exprLoop ce qui fait que bison me donne une erreur synaxe sur else. Comment puis-je dire à Bison de décaler à ce point (vers optionalNL else) au lieu de réduire ? (vers exprLoop causant else comme une erreur).
fichier d'exemple à tester avec
%%
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
Alternative .y et sortie. Vous pouvez le voir regarder devant vous en voyant un \n et ne sait pas s'il faut réduire la règle ou continuer. Je change l'ordre des règles pour obtenir des résultats différents. Mais soit il s'attend toujours à un \n ou s'attend toujours à ce qu'il y ait une autre règle qui finit toujours par être ignorée. état 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)
Merci à Kinopiko pour sa réponse
J'ai modifié son code pour qu'il n'y ait pas de conflits, puis j'ai travaillé à le rendre plus flexible. Voici mes fichiers
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);
}
un fichier de test qui s'exécute automatiquement après la compilation
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
{ }