我正在为一种非常简单的编程语言编写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班/减少
我假设我的语法中的某些内容是错误的,但我不确定究竟是什么。
答案 0 :(得分:4)
你说:
所以我创建了一些规则来分隔每种变量和常量:
id_variable_string: identifier; id_variable_integer: identifier; id_variable_real: identifier;
这是你的问题。在语法上没有区分id_variable_string
和id_variable_integer
,所以你有(至少两个)浪费的规则。这就是它的抱怨。如果获得identifier
它是否应该将其视为id_variable_string
或id_variable_integer
,它就不知道了。
您必须以不同方式处理类型冲突 - 语义检查(不是语法检查),与标识符关联的类型与表达式中其他标识符的类型一致。