5

我正在为一种非常简单的编程语言编写 BNF 语法,并使用 Flex 和 Bison 进行编译。
我只有 3 种变量和常量类型:实数、整数、字符串
我的 .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;
整数 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 移位/减少


我假设我的语法有问题,但我不确定到底是什么。

4

1 回答 1

5

你说:

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

id_variable_string:
identifier;

id_variable_integer:
identifier;

id_variable_real:
identifier;

这是你的问题。在语法上没有什么可以区分 anid_variable_string和 an 的id_variable_integer,所以你有(至少两个)浪费的规则。这就是它所抱怨的。它不知道什么时候得到 anidentifier是否应该将其视为 anid_variable_string或 an id_variable_integer

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

于 2013-11-12T04:37:04.197 回答