无法弄清楚为什么Bison会抛出“由于冲突而导致解析器无效的规则”

时间:2013-11-12 00:15:14

标签: grammar bison flex-lexer bnf

我正在为一种非常简单的编程语言编写BNF语法,并使用Flex和Bison进行编译。 我只有3个变量和常量类型: real,integer,string
我的.l文件具有“ID”的标记定义,如下所示:

DIGIT [0-9]
LETTER [a-zA-Z]
ID {LETTER}({LETTER}|{DIGIT})*


我的.y文件有标识符的定义,如下所示:

identifier:
ID;

现在,我想使用标识符定义来构建变量和常量名称。但我也想限制对相同类型数据的赋值(例如,我不希望将字符串赋值给整数变量)。所以我创建了一些规​​则来分隔每种变量和常量:

id_variable_string:
identifier;

id_variable_integer:
identifier;

id_variable_real:
identifier;

我对常数做了同样的事情。 现在,在我的语言中,我有一个用于常量声明/定义的部分,然后是一个用于变量声明的部分。也就是说,常量是在它们被赋值的同时声明(类似于“myConstant = 123”),但必须先声明变量,然后在专门为语句设计的部分中赋值。
例如,如果我想要一个整数和一个字符串变量,我必须先声明它们:
STRING myStrVariable;
INTEGER myIntVariable;
然后,在为陈述保留的区域中,我可以选择进行分配(陈述可以是分配,决定,选择,输出等):

assignment: 
        id_variable_string ASSIGN_OPERATOR literal_string
        | id_variable_string ASSIGN_OPERATOR id_const_string 
        | id_variable_string ASSIGN_OPERATOR id_variable_string 
        | id_variable_string ASSIGN_OPERATOR concatenacion  
        | id_variable_integer ASSIGN_OPERATOR id_const_integer 
        | id_variable_integer ASSIGN_OPERATOR id_variable_integer  
        | id_variable_integer ASSIGN_OPERATOR expression 
        | id_variable_integer ASSIGN_OPERATOR literal_integer
        | id_variable_real ASSIGN_OPERATOR id_variable_real
        | id_variable_real ASSIGN_OPERATOR id_const_real
        | id_variable_real ASSIGN_OPERATOR expression
        | id_variable_real ASSIGN_OPERATOR literal_real
        ;

我打算明确地说,字符串变量只能分配字符串文字,字符串连接(使用+),字符串常量或其他字符串变量。整数变量和实变量相同,只是它们不能被分配连接而是表达式(数学运算)。
连接定义如下:

concatenation:
        id_variable_string ADD_OPERATOR id_variable_string 
        | id_variable_string ADD_OPERADOR literal_string 
        | literal_string ADD_OPERADOR id_variable_string 
        | literal_string ADD_OPERADOR literal_string
        | id_const_string ADD_OPERADOR id_const_string  
        | id_const_string ADD_OPERADOR id_variable_string 
        | id_const_string ADD_OPERADOR literal_string 
        | literal_string ADD_OPERADOR id_const_string  
        | id_variable_string ADD_OPERADOR id_const_string
        ;

表达式定义为:

expression: 
        expression ADD_OPERATOR term
        | expression SUBST_OPERADOR term
        | term
        ;

term:
        term MULTIP_OPERATOR factor
        | term DIVISION_OPERATOR factor
        | factor
        ;

factor:     
        id_variable_integer
        | id_variable_real
        | id_const_integer
        | id_const_real
        | literal_integer
        | literal_real
        | PARENTHESIS_OPEN expression PARENTHESIS_CLOSE
        ;

现在,这就是Bison所说的:


55作业:id_variable_integer ASSIGN_OPERATOR id_const_integer
56 | id_variable_integer ASSIGN_OPERATOR id_variable_integer
58 | id_variable_integer ASSIGN_OPERATOR literal_integer
59 | id_variable_real ASSIGN_OPERATOR id_variable_real
60 | id_variable_real ASSIGN_OPERATOR id_const_real
62 | id_variable_real ASSIGN_OPERATOR literal_real


国家50个冲突:1个班次/减少
国家76次冲突:14次转移/减少
国家130次冲突:2次/减少
国家131冲突:1班/减少
国家133冲突:1班/减少
国134冲突:1班/减
国家135冲突:1班/减少
国家137冲突:1班/减少
状态138冲突:1班/减少

我假设我的语法中的某些内容是错误的,但我不确定究竟是什么。

1 个答案:

答案 0 :(得分:4)

你说:

  

所以我创建了一些规​​则来分隔每种变量和常量:

id_variable_string:
identifier;

id_variable_integer:
identifier;

id_variable_real:
identifier;

这是你的问题。在语法上没有区分id_variable_stringid_variable_integer,所以你有(至少两个)浪费的规则。这就是它的抱怨。如果获得identifier它是否应该将其视为id_variable_stringid_variable_integer,它就不知道了。

您必须以不同方式处理类型冲突 - 语义检查(不是语法检查),与标识符关联的类型与表达式中其他标识符的类型一致。