lex 和 yacc 文件中的语法错误
Syntax error in lex & yacc file
我对 lex 和 yacc 还很陌生。我正在尝试一种语法来识别输入文本:ESCREVER 1;
或 ESCREVER 1+2;
但每次我尝试它都会显示语法错误,我认为问题出在解析数字或单词 ESCREVER
上。
这是我的 flex/lex 代码
%{
#include "gram.h"
int yyerror(const char *s);
%}
/* letras [A-Za-z]+ */
/* id ({letras})({letras}|{digito})* */
%%
"ESCREVER" {return ESCREVER; }
"TERMINAR" {return TERMINAR; }
[0-9]+ { yylval.num =atoi(yytext);
return NUM; }
[A-Za-z0-9]* { yylval.str=strdup(yytext);
return TEXTO;}
"/" |
"-" |
"+" |
"*" |
"=" |
. {return yytext[0];}
[ \n\t] { }
%%
int yywrap(){ return 1; }
YACC代码:
%{
#include <stdio.h>
int yylex(void);
int yyerror(const char *s);
%}
%union{
char *str; /* para strings*/
int num; /* para inteiros */
}
%token TERMINAR ESCREVER
%token SUBTRACAO
%token MULTIPLICACAO
%token DIVISAO
%token SOMA
%token<num> NUM /*para inteiros*/
%token<str> TEXTO /*MUDAR PARA VAR*/
%type<num> elemento
%type<num> expr
%type<num> lista
%start s
%%
s:linha s
|TERMINAR ';' {return 0;}
;
linha: ESCREVER lista';' {printf("%d",);}
| VARS
;
lista: lista ',' elemento
| elemento
;
elemento:NUM
|expr
;
VARS :
| NUM
| TEXTO
| expr
| TEXTO '=' VARS ';' /* para delcaracoes */
;
expr : NUM SOMA expr {$$=+;}
| NUM SUBTRACAO expr {$$=-;}
| NUM MULTIPLICACAO expr {$$=*;}
| NUM DIVISAO expr {$$=/;}
| NUM '+' expr {$$=+;}
| NUM '=' expr {$$==;}
| NUM '-' expr {$$=-;}
| NUM '*' expr {$$=*;}
| NUM '/' expr {$$=/;}
| NUM {$$=; }
;
%%
int yyerror(char const *s) {
fprintf(stderr,"Erro: %s\n",s);
return 0;
}
int main(int argc, char *argv[]) {
extern FILE *yyin;
if (argc > 1) {
if((yyin=fopen(argv[1],"r"))==NULL){
fprintf(stderr,"erro ao abrir o ficheiro \"%s\".\n",argv[1]);
return 1;
}
} else
printf("introduza comandos: \n");
yyparse();
return 0;
}
您的扫描仪规格中的这两行都匹配 space:
. {return yytext[0];}
[ \n\t] { }
当您键入 ESCREVER 1;
时,space 由第一条规则解释。由于 Flex 按照规则的写入顺序使用规则,您只需将 blank-ignoring 规则向上移动,以便首先检查它。
我对 lex 和 yacc 还很陌生。我正在尝试一种语法来识别输入文本:ESCREVER 1;
或 ESCREVER 1+2;
但每次我尝试它都会显示语法错误,我认为问题出在解析数字或单词 ESCREVER
上。
这是我的 flex/lex 代码
%{
#include "gram.h"
int yyerror(const char *s);
%}
/* letras [A-Za-z]+ */
/* id ({letras})({letras}|{digito})* */
%%
"ESCREVER" {return ESCREVER; }
"TERMINAR" {return TERMINAR; }
[0-9]+ { yylval.num =atoi(yytext);
return NUM; }
[A-Za-z0-9]* { yylval.str=strdup(yytext);
return TEXTO;}
"/" |
"-" |
"+" |
"*" |
"=" |
. {return yytext[0];}
[ \n\t] { }
%%
int yywrap(){ return 1; }
YACC代码:
%{
#include <stdio.h>
int yylex(void);
int yyerror(const char *s);
%}
%union{
char *str; /* para strings*/
int num; /* para inteiros */
}
%token TERMINAR ESCREVER
%token SUBTRACAO
%token MULTIPLICACAO
%token DIVISAO
%token SOMA
%token<num> NUM /*para inteiros*/
%token<str> TEXTO /*MUDAR PARA VAR*/
%type<num> elemento
%type<num> expr
%type<num> lista
%start s
%%
s:linha s
|TERMINAR ';' {return 0;}
;
linha: ESCREVER lista';' {printf("%d",);}
| VARS
;
lista: lista ',' elemento
| elemento
;
elemento:NUM
|expr
;
VARS :
| NUM
| TEXTO
| expr
| TEXTO '=' VARS ';' /* para delcaracoes */
;
expr : NUM SOMA expr {$$=+;}
| NUM SUBTRACAO expr {$$=-;}
| NUM MULTIPLICACAO expr {$$=*;}
| NUM DIVISAO expr {$$=/;}
| NUM '+' expr {$$=+;}
| NUM '=' expr {$$==;}
| NUM '-' expr {$$=-;}
| NUM '*' expr {$$=*;}
| NUM '/' expr {$$=/;}
| NUM {$$=; }
;
%%
int yyerror(char const *s) {
fprintf(stderr,"Erro: %s\n",s);
return 0;
}
int main(int argc, char *argv[]) {
extern FILE *yyin;
if (argc > 1) {
if((yyin=fopen(argv[1],"r"))==NULL){
fprintf(stderr,"erro ao abrir o ficheiro \"%s\".\n",argv[1]);
return 1;
}
} else
printf("introduza comandos: \n");
yyparse();
return 0;
}
您的扫描仪规格中的这两行都匹配 space:
. {return yytext[0];}
[ \n\t] { }
当您键入 ESCREVER 1;
时,space 由第一条规则解释。由于 Flex 按照规则的写入顺序使用规则,您只需将 blank-ignoring 规则向上移动,以便首先检查它。