我用Flex和野牛做了一个Visual Basic解析器,用于uni赋值。除了多行表达式的解析外,大多数似乎都能正常工作。下面是一个不起作用的代码示例:
A = A +
1
有趣的是,删除A =
可以使它正确解析。如果我将=
替换为优先级高于或等于+
的运算符,同样适用。
解析器似乎优先考虑单行表达式而不是多行表达式。我知道这是一个优先级问题,但我不知道如何解决这个问题。
截断Flex代码:
%option nounistd
%option noyywrap
%option case-insensitive
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parcer-mini.tab.h"
#pragma warning(disable : 4996)
#define YY_DECL int yylex()
int result = 0;
%}
%x STRING_LITERAL
%%
%{
char buf[100000];
memset(buf, '\0', 100000);
%}
"+" { return '+'; }
"-" { return '-'; }
"*" { return '*'; }
"/" { return '/'; }
"=" { return '='; }
"<" { return '<'; }
">" { return '>'; }
"^" { return '^'; }
([0-9]([0-9]+)?) {yylval.int_val = atoi(yytext); return INT_VALUE;}
([a-zA-Z_])([a-zA-Z_0-9])* {yylval.id_var_name = (char *) malloc(strlen(yytext)+1); strcpy(yylval.id_var_name, yytext); return IDENTIFIER;}
\n+ {return END_OF_LINE;}
<<EOF>> { static int once = 0; return once++ ? 0 : END_OF_LINE;}
%%
截断野牛代码:
%define parse.error verbose
%{
#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
extern int yylineno;
extern FILE* yyin;
extern int yyparse();
extern int yylex();
void yyerror(const char* s);
%}
%union {
int int_val;
char* id_var_name;
}
%type <expression> expr_singleline expr_multiline basic_literal_value;
%type <statement> stmt root;
%type stmt_ends;
%token<int_val> INT_VALUE
%token<id_var_name> IDENTIFIER
%token END_OF_LINE
%left '='
%left '>' '<'
%left '+' '-'
%left '*' '/'
%right UNARY_MINUS UNARY_PLUS
%left '^'
%precedence IDENTIFIER
%start root
%%
root: stmt {printf("root 1\n");}
;
stmt: expr_multiline stmt_ends {printf("stmt 1\n");}
| expr_singleline stmt_ends {printf("stmt 2\n");}
;
stmt_ends: END_OF_LINE {printf("stmt_ends 1\n");}
| stmt_ends END_OF_LINE {printf("stmt_ends 2\n");}
;
expr_singleline: basic_literal_value {printf("expr_single 0\n");}
| '-' expr_singleline %prec UNARY_MINUS {printf("expr_single 1\n");}
| '+' expr_singleline %prec UNARY_PLUS {printf("expr_single 2\n");}
| expr_singleline '+' expr_singleline {printf("expr_single 3\n");}
| expr_singleline '-' expr_singleline {printf("expr_single 4\n");}
| expr_singleline '*' expr_singleline {printf("expr_single 5\n");}
| expr_singleline '/' expr_singleline {printf("expr_single 6\n");}
| expr_singleline '=' expr_singleline {printf("expr_single 8\n");}
| expr_singleline '<' expr_singleline {printf("expr_single 9\n");}
| expr_singleline '>' expr_singleline {printf("expr_single 10\n");}
| expr_singleline '^' expr_singleline {printf("expr_single 11\n");}
| IDENTIFIER {printf("expr_single 17\n");}
;
expr_multiline: expr_singleline '+' END_OF_LINE expr_singleline {printf("expr_multi 1\n");}
| expr_singleline '-' END_OF_LINE expr_singleline {printf("expr_multi 2\n");}
| expr_singleline '*' END_OF_LINE expr_singleline {printf("expr_multi 3\n");}
| expr_singleline '/' END_OF_LINE expr_singleline {printf("expr_multi 4\n");}
| expr_singleline '=' END_OF_LINE expr_singleline {printf("expr_multi 6\n");}
| expr_singleline '<' END_OF_LINE expr_singleline {printf("expr_multi 7\n");}
| expr_singleline '>' END_OF_LINE expr_singleline {printf("expr_multi 8\n");}
| expr_singleline '^' END_OF_LINE expr_singleline {printf("expr_multi 9\n");}
;
basic_literal_value: INT_VALUE {printf("basic_literal_value int\n");}
;
%%
int main(int argc, char** argv) {
if (argc > 1) {
yyin = fopen(argv[1], "r");
yyparse();
}
else {
yyerror("not found file");
}
}
void yyerror(const char* s) {
fprintf(stderr, "Parse error: %s\n", s);
exit(1);
}
1条答案
按热度按时间bihw5rsg1#
我不知道如何解决上述问题,但我找到了一个解决方案。通过创建一个可选的End of Line标记,我合并了expr_singleline和expr_multiline。这个方法非常有效。
修改的截断野牛代码: