我正在尝试使用bison和flex为自定义pascal语言创建一个编译器,并且我最终会根据我的自定义语法获得应该是正确的程序的语法错误。
我的自定义语法:
<program> ::= program id
<block>
<block> ::= {
<sequence>
}
<sequence> ::= <statement> ( ; <statement> )*
<brackets-seq> ::= { <sequence> }
<brack-or-stat> ::= <brackets-seq> |
<statement>
<statement> ::= ε |
<assignment-stat> |
<if-stat> |
<while-stat>
<assignment-stat> ::= id := <expression>
<if-stat> ::= if (<condition>)
<brack-or-stat>
<elsepart>
<elsepart> ::= ε |
else <brack-or-stat>
<while-stat> ::= while (<condition>)
<brack-or-stat>
<expression> ::= <optional-sign> <term> ( <add-oper> <term>)*
<term> ::= <factor> (<mul-oper> <factor>)*
<factor> ::= constant |
(<expression>) |
id
<condition> ::= <boolterm> (and <boolterm>)*
<boolterm> ::= <boolfactor> (or <boolfactor>)*
<boolfactor> ::= not [<condition>] |
[<condition>] |
<expression> <relational-oper> <expression>
<relational-oper> ::= == | < | > | <> | <= | >=
<add-oper> ::= + | -
<mul-oper> ::= * | /
<optional-sign> ::= ε | <add-oper>
我对野牛的语法实施:
%{
#include <stdio.h>
#include <string.h>
int yylex(void);
void yyerror(char *s);
%}
%union {
int i;
char *s;
};
%token <i> INTEGERNUM
%token PROGRAM;
%token OR;
%token AND;
%token NOT;
%token IF;
%token ELSE;
%token WHILE;
%token PLUS;
%token MINUS;
%token MUL;
%token DIV;
%token LSB;
%token RSB;
%token LCB;
%token RCB;
%token LEFTPAR;
%token RIGHTPAR;
%token ID;
%token INT;
%token ASSIGN;
%token ISEQUAL;
%token LTHAN;
%token GTHAN;
%token NOTEQUAL;
%token LESSEQUAL;
%token GREATEREQUAL;
%left '+' '-'
%left '*' '/'
%%
program:
PROGRAM ID block
;
block:
LCB RCB
|LCB sequence RCB
;
sequence:
statement ';'sequence
|statement ';'
;
bracketsSeq:
LCB sequence RCB
;
brackOrStat:
bracketsSeq
|statement
;
statement:
assignmentStat
|ifStat
|whileStat
|
;
assignmentStat:
ID ':=' expression
ifStat:
IF LEFTPAR condition RIGHTPAR brackOrStat elsepart
;
elsepart:
ELSE brackOrStat
|
;
whileStat:
WHILE LEFTPAR condition RIGHTPAR brackOrStat
;
expression:
addOper expression
|expression addOper expression
|term
;
term:
term mulOper term
|factor
;
factor:
INT
|LEFTPAR expression RIGHTPAR
|ID
;
condition:
condition AND condition
|boolterm
;
boolterm:
boolterm OR boolterm
|boolfactor
;
boolfactor:
NOT LSB condition RSB
|LSB condition RSB
|expression relationalOper expression
;
relationalOper:
ISEQUAL
|LTHAN
|GTHAN
|NOTEQUAL
|LESSEQUAL
|GREATEREQUAL
;
addOper:
PLUS
|MINUS
;
mulOper:
MUL
|DIV
;
optionalSign
|addOper
;
%%
int main( int argc, char **argv )
{
extern FILE *yyin;
++argv, --argc; /* skip over program name */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
else
yyin = stdin;
do
yyparse();
while(!feof(yyin));
}
我的flex实现非常简单,只需返回所需的每个符号或标识符的标记。
在以下简单程序中使用我的实现:
program circuit
{
a:=b;
}
我最终收到语法错误。特别是当解析到达:=
之后的点时,根据我的调试打印,我使用:
$ ./a.exe verilog.txt
text = program
text = circuit val = circuit
text = {
text = a val = a
text = :=
syntax error
这是我第一次使用flex和bison,因此我猜测自从我获得./bison.exe -dy comp.y
命令后,我对原始语法的执行错误了:
野牛冲突64转/减少
任何想法都会有所帮助。谢谢!
答案 0 :(得分:1)
这条规则:
assignmentStat: ID ':=' expression
使用一个令牌':=',哪个bison提供的代码与任何其他令牌不同,而你的词法分析器无法知道,因此你几乎肯定不会返回它。您可能会为字符序列':='返回ASSIGN
,因此您需要:
assignmentStat: ID ASSIGN expression
对于shift-reduce冲突,它们意味着解析器与您指定的语言不完全匹配,而是与某个子集匹配(由默认shift而不是reduce确定)。您可以使用bison的-v
选项在.output
文件中完整打印出解析器状态机(包括所有冲突)。然后,您可以检查冲突并确定如何更改语法以匹配您想要的内容。
当我在你的例子中运行bison时,我看到只有9个移位/减少冲突,所有这些都来自expr: expr OP expr
- 样式规则,这些规则是模糊的(可能是向右或向左递归)。默认的分辨率(shift)使它们都是正确的递归,这可能不是你想要的。您可以将语法更改为不明确,或使用bison的内置优先级解析工具来解决它们。