Ich versuche, einen Parser für meine eigene Mini-Sprache zu bauen, die dann in C++ von YACC selbst übersetzt wird.LEX + YACC nimmt Token in der nächsten Zeile für eine Regel
Das Problem ist, YACC liest die erste Zeile der Eingabe sowie das erste Token aus der zweiten Zeile der Eingabe und vergleicht es mit der entsprechenden Regel, während es nur die Token in der ersten Zeile der Eingabe und gelesen hätte angepasst es
mit der entsprechenden RegelMeine Eingabedatei:
print "hello"
a = 10
print a
Lex-Datei:
%{
#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;
%%
YACC Datei ist:
%{
#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;
}
Erwartete Ausgabe lautet:
cout<<"hello"<<endl;
int a = 10;
cout<<a<<endl;
Aber die Analyse fehlschlägt, mit Teilausgabe als:
cout<<"hello"<<a<<endl;
Und Fehlermeldung:
Line: 2, Message: syntax error, Cause: =
Die Regeln verwendet reduzieren sollen (in gleicher ord er):
PRINT STRING
ID ASSIGN INTEGER
PRINT ID
aber die erste Regel verwendet wird, zu reduzieren, ist:
PRINT STRING ID
und das Parsen nicht
ID
in der nächsten Zeile ist, nach PRINT STRING
, aber immer noch die Regel verwendet wird PRINT STRING ID
.
ich eine geringere Priorität zu STRING
über ID
gegeben habe (ich denke, das ist das, was die folgenden Codemittel)
%nonassoc STRING
%nonassoc ID
Ist das das Problem?
Ich kann nicht verstehen, was passiert. Fehle ich etwas?
Sie meinen, ein Token zurückgeben, NEWLINE für jeden \ n sagen und Regeln wie PRINT STRING NEWLINE und ID ASSIGN INTEGER NEWLINE verwenden? –
@Abhilashk - ja, genau – antlersoft