J'essaye de construire un analyseur pour mon propre mini-langage, qui est ensuite traduit en C++ par YACC lui-même. Le problème est que YACC lit la première ligne d'entrée ainsi que le premier jeton de la deuxième ligne de l'entrée et l'associe à la règle correspondante, alors qu'il aurait dû lire uniquement les jetons dans la première ligne d'entrée et identifié avec la règle correspondanteLEX + YACC prenant un jeton dans la ligne suivante pour une règle
Mon fichier d'entrée est:
print "hello"
a = 10
print a
fichier Lex:
%{
#include <stdio.h>
#include "y.tab.h"
%}
alpha [a-zA-Z]
digit [0-9]
%%
[ \t] ;
[ \n] { yylineno = yylineno + 1;}
print {yylval = strdup(yytext); return PRINT;}
{alpha}({alpha}|{digit})* {yylval = strdup(yytext); return ID;}
{digit}+ {yylval = strdup(yytext); return INTEGER;}
\".*\" {yylval = strdup(yytext); return STRING;}
"=" return ASSIGN;
%%
fichier YACC est:
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern int yylineno;
extern FILE *yyin;
extern FILE *yyout;
extern char *yytext;
%}
%token PRINT INPUT INTO ASSIGN INTEGER DECIMAL BOOLVAL CHARACTER
%nonassoc STRING
%nonassoc ID
%%
entry: entry action {fprintf(yyout, "\t%s", $2); }
| action {fprintf(yyout, "\t%s", $1); }
;
action : print {$$ = $1;}
| assign {$$ = $1;}
;
print : PRINT ID {
printf("rule: PRINT ID");
char* id = strdup($2);
strcpy($$, "");
strcat($$,"cout<<");
strcat($$,id);
strcat($$,"<<endl;\n");
}
| PRINT STRING {
printf("rule: PRINT STRING\n");
char* str = strdup($2);
strcpy($$, "");
strcat($$,"cout<<");
strcat($$,str);
strcat($$,"<<endl;\n");
}
| PRINT STRING ID {
printf("rule: PRINT STRING ID\n");
char* str = strdup($2);
char* id = strdup($3);
strcpy($$, "");
strcat($$,"cout<<");
strcat($$,str);
strcat($$,"<<");
strcat($$,id);
strcat($$,"<<endl;\n");
}
;
assign: ID ASSIGN INTEGER {
char* id = strdup($1);
char* val = strdup($3);
strcpy($$,"");
strcat($$,"int ");
strcat($$,id);
strcat($$," = ");
strcat($$,val);
strcat($$,";\n");
}
;
%%
int main(int argc, char *argv[])
{
yyin = fopen(argv[1], "r");
yyout = fopen("out.txt","w");
if(!yyparse())
printf("\nParsing complete\n");
else
printf("\nParsing failed\n");
//fclose(yyin);
fclose(yyout);
return 0;
}
yyerror(char *s) {
printf("\n \nLine: %d, Message: %s, Cause: %s\n", yylineno, s, yytext);
}
yywrap()
{
return 1;
}
sortie prévue est:
cout<<"hello"<<endl;
int a = 10;
cout<<a<<endl;
Mais ne analyse syntaxique, avec une sortie partielle:
cout<<"hello"<<a<<endl;
Et message d'erreur:
Line: 2, Message: syntax error, Cause: =
Les règles utilisées pour réduire sont censés être (dans le même er):
PRINT STRING
ID ASSIGN INTEGER
PRINT ID
mais, la première règle étant utilisée pour réduire est:
PRINT STRING ID
et l'analyse syntaxique échoue
ID
est dans la ligne suivante, après PRINT STRING
, mais toujours la règle utilisé est PRINT STRING ID
.
J'ai donné une priorité moindre à STRING
sur ID
(je suppose que c'est ce que le code ci-dessous signifie)
%nonassoc STRING
%nonassoc ID
Est-ce le problème?
Je n'arrive pas à comprendre ce qui se passe. Est-ce que je manque quelque chose?
Vous voulez dire, renvoyez un jeton, dites NEWLINE pour chaque \ n et utilisez les règles telles que PRINT STRING NEWLINE et ID ASSIGN INTEGER NEWLINE? –
@Abhilashk - oui, exactement – antlersoft