c - Flex/Bison 解析器识别“(”与“(”不同)
问题描述
我正在尝试使用 flex 和 bison 编写一个简单的玩具语言解析器,它基本上只支持变量和算术函数。
目前我面临一个奇怪的问题,其中带有左括号和下一个标记之间的空格的语句与带有左括号且下一个标记之间没有空格的语句的工作方式不同,特别是我试图识别以下程序。
var b: int
begin
b <- (4)
end
尝试这样做会在第 3 行出现语法错误,但是如果我在 4 和 ( 之间添加一个空格,则程序会被正确识别。
我的 parser.lex 文件如下。
%{
#include<stdlib.h>
#include<math.h>
#include "parser.tab.h"
%}
LETTR [a-zA-Z]
DIGIT [0-9]
BIN [0-1]
SIMB [$|_]
WHITESPACE [ \t\r]+
%%
WHITESPACE { }
"\n" {yylineno++;}
"begin" {return BEGN;}
"if" {return IF;}
"ifelse" {return IFELSE;}
"while" {return WHILE;}
"end" {return END;}
"var" {return VAR;}
"read" {return READ;}
"print" {return PRINT;}
"int" {return INT;}
"float" {return FLOAT;}
"<-" {return ASSIGN;}
({SIMB}|{LETTR})({LETTR}|{DIGIT}|{SIMB})* {yylval.id=(char*)malloc(strlen(yytext)+1); strcpy(yylval.id, yytext); return ID;} /* Identificador */
({DIGIT})({DIGIT})* {return NUMINT;} /*Entero*/
({DIGIT})*.({DIGIT})({DIGIT})* {return NUMFLOAT;} /*Punto Flotante*/
";" {return SEMICOLON;}
":" {return COLON;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULT;}
"/" {return DIVIDE;}
"<" {return LESSTHAN;}
">" {return GREATTHAN;}
"=" {return EQUALS;}
"<=" {return LESSEQUALS;}
">=" {return GREATEQUALS;}
"~" {return NEGSIGN;}
"(" {return LEFTP;}
")" {return RIGHTP;}
. { }
%%
而我的 parser.y 文件如下:
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
FILE extern *yyin;
char extern *yytext;
int yylineno;
int yylex();
int yyerror(char const * s);
void addToTable(char * var);
void initTable();
void checkVar();
void printTable();
%}
%union{
char *id;
}
%token <id > ID
%token BEGN IF IFELSE WHILE END VAR ASSIGN LEFTP RIGHTP INT FLOAT SEMICOLON COLON PLUS MINUS
MULT DIVIDE LESSTHAN GREATTHAN EQUALS LESSEQUALS GREATEQUALS NUMINT NUMFLOAT READ PRINT NEGSIGN
%start prog
%%
prog: opt_decls BEGN opt_stmts END {printf("Valid program!\n"); printTable(); return 0;}
opt_decls: decls
| /* empty */
;
decls : dec SEMICOLON decls
| dec
;
dec : VAR ID COLON tipo { addToTable($2);}
;
tipo : INT
| FLOAT
;
stmt : ID ASSIGN expr {checkVar($1);}
| IF LEFTP expression RIGHTP stmt
| IFELSE LEFTP expression RIGHTP stmt stmt
| WHILE LEFTP expression RIGHTP stmt
| READ ID {checkVar($2);}
| PRINT expr
| BEGN opt_stmts END
;
opt_stmts : stmt_lst
| /*empty*/
;
stmt_lst : stmt SEMICOLON stmt_lst
| stmt
;
expression : expr
| expr relop expr
;
expr : expr PLUS term
| expr MINUS term
| sign term
| term
term : term MULT factor
| term DIVIDE factor
| factor
;
factor : LEFTP expr RIGHTP
| ID {checkVar($1);}
| NUMINT
| NUMFLOAT
;
relop : LESSTHAN
| GREATTHAN
| EQUALS
| LESSEQUALS
| GREATEQUALS
;
sign : NEGSIGN
;
%%
char symbolTable [100][50];
int yyerror(char const * s) {
fprintf(stderr, "%s at line: %d while reading %s\n", s, yylineno, yytext);
}
void printTable(){
printf("Symbol table:\n");
int i;
for (i = 0; i < 100; i++){
if (strcmp(symbolTable[i], "") != 0){
printf("%s\n", symbolTable[i]);
}
}
}
void addToTable(char *var){
int i = 0;
for (i = 0; i < 100; i++){
if (strcmp(symbolTable[i], "") == 0){
strcpy(symbolTable[i], var);
break;
}
}
}
void initTable(){
int i;
for (i = 0; i < 100; i++){
strcpy(symbolTable[i], "");
}
}
void checkVar(char * var){
int i;
for (i = 0; i < 100; i++){
if (strcmp(symbolTable[i], var) == 0){
return;
}
}
char errorMsg [255];
sprintf(errorMsg, "Variable %s was not initialized", var);
yyerror(errorMsg);
exit(-1);
}
void main(int argc, char *argv[]) {
initTable();
if (argc == 1)
printf("Input file not found.\n");
else{
yyin = fopen(argv[1], "r");
yyparse();
}
fclose(yyin);
}
老实说,我对可能导致这种情况的原因感到困惑。
我正在使用以下命令运行程序(使用 Ubuntu 16.04)
flex parser.lex
bison -d parser.y
gcc lex.yy.c parser.tab.c -lfl
./a.out p3.txt
其中 p3.txt 是一个文本文件,其中包含要解析的程序。
解决方案
推荐阅读
- ios - 应该在哪个队列上调用 completionHandler 来报告即时错误?
- c# - 即使游戏对象在层次结构中处于活动状态,Gameobject.find 也仅返回 null
- docker - 为什么这个 docker 镜像会返回这个错误:无法访问 jarfile /home/server.jar
- r - ggplot - 如何用多个 DATE 列绘制多行年份?
- asp.net-mvc - 从 Viewbag Dropdown 访问数据
- dart - 分隔线和行之间的填充很大
- node.js - 当测试用例需要更多时间时,伊斯坦布尔与 mocha 不生成覆盖率报告
- java - 使用 java 类执行类似 mongoDB shell 的查询
- gradle - JDeveloper 和 gradle 集成
- keras - 使用 Keras 进行元素乘法