解析器出现问题,我无法解决这个问题。我不断收到错误:parser.y:79.33-41:使用了符号字符,但未将其定义为令牌并且没有规则。我已将行放在** **。
下面是我的解析器代码:
%token PLUS TIMES DIVIDE SUBTRACT BRA KET EQUALS NOT_EQUAL LESS_THAN GREATER_THAN GREATER_THAN_OR_EQUAL
%token COMA SEMICOLON ARROW DECIMAL ENDDO ENDFOR ENDIF ENDP ENDWHILE ELSE CODE OF TYPE DECLARATIONS CHARACTER
%token INTEGER REAL IF THEN DO WHILE FOR IS BY TO WRITE NEWLINE READ NOT AND OR ID LESS_THAN_OR_EQUAL APOSTROPHE
%%
Program : block
| ENDP
| ID
;
block : DECLARATIONS declaration_block CODE statement_list
| CODE statement_list
;
declaration_block : ID OF TYPE SEMICOLON
| ID_list OF TYPE SEMICOLON
| ID_list OF TYPE SEMICOLON declaration_block
;
ID_list : ID
| ID COMA ID_list
;
type : CHARACTER
| INTEGER
| REAL
;
statement_list : statement
| statement_list SEMICOLON statement
;
statement : assignment_statement
| if_statement
| do_statement
| while_statement
| for_statement
| write_statement
| read_statement
;
assignment_statement : expression ARROW ID
;
if_statement : IF conditional THEN statement_list ELSE statement_list ENDIF
;
do_statement : DO statement_list WHILE conditional ENDDO
;
while_statement : WHILE conditional DO statement_list ENDWHILE
;
for_statement : FOR ID IS expression BY expression TO expression DO statement_list ENDFOR
;
write_statement : WRITE BRA output_list KET write_statement NEWLINE
;
read_statement : READ BRA ID KET
;
output_list : value
| output_list COMA value
;
conditional : expression comparator expression
| NOT conditional
| expression comparator expression AND conditional
| expression comparator expression OR conditional
;
comparator : EQUALS
| NOT_EQUAL
| LESS_THAN
| GREATER_THAN
| LESS_THAN_OR_EQUAL
| GREATER_THAN_OR_EQUAL
;
expression : term
| expression PLUS term
| expression SUBTRACT term
;
term : value
| term TIMES value
| term DIVIDE value
;
value : ID
| constant
| BRA expression KET
;
constant : number_constant
| character_constant
;
**character_constant : APOSTROPHE character APOSTROPHE**
;
number_constant : INTEGER
| SUBTRACT INTEGER
| SUBTRACT INTEGER DECIMAL INTEGER
| INTEGER DECIMAL INTEGER
;
%%
下面是我的词法分析器:
%{
#ifdef PRINT
#define TOKEN(i) printf("Token: " #i "\n");
#else
#define TOKEN(i) return (i);
#endif
%}
delim [ \r\n\t]
ws {delim}+
digit [0-9]
character [a-zA-Z]
INTEGER {digit}+
id {character}({character}|{digit})*
character_constant ('{character}')
%%
{ws} ; /* Do Nothing */
"+" TOKEN(PLUS)
"*" TOKEN(TIMES)
"/" TOKEN(DIVIDE)
"-" TOKEN(SUBTRACT)
"(" TOKEN(BRA)
")" TOKEN(KET)
...
"'" TOKEN(APOSTROPHE)
ENDP TOKEN(ENDP)
CODE TOKEN(CODE)
OF TOKEN(OF)
TYPE TOKEN(TYPE)
DECLARATIONS TOKEN(DECLARATIONS)
character TOKEN(CHARACTER)
{INTEGER} TOKEN(INTEGER)
...
{id} TOKEN(ID)
{character_constant} TOKEN(character_constant)
%%
从BNF到解析器的整个文件中的拼写都是正确的,没有人知道这里的问题是什么。我尝试将其更改为字母而不是字符,但这给了我另一个错误。
答案 0 :(得分:1)
该消息的含义与所讲的完全相同。您使用了符号character
,但是您既没有声明它是一个令牌,也没有提供它的生产版本。因此它既不是终端也不是非终端,并且解析器生成器在使用时会抱怨。
语法分析器生成器看不到词法分析器中发生的事情。因此,您(毫无意义,恕我直言)创建了{character}
的词法分析器定义这一事实仅在词法分析器文件内部引起关注。 (这毫无意义,因为您可以等效地使用Posix字符类[[:alpha:]]
,它具有明确的含义,并且与{character}
一样可读。)而且,解析器实际上不需要了解词法分析器的方式。附带令牌代码值。因此,当您在解析器定义中声明令牌时,解析器生成器会在头文件中放置该符号的定义。词法分析器#include
是该头文件,并允许它使用该符号作为解析器的返回值。不需要其他通讯。
答案 1 :(得分:1)
错误是无法将单个字符与词法分析器中的标识符区分开。您已经正确添加了一个词法分析器规则来匹配它,该规则返回了名为character_constant
的令牌,但是,您还为字符常量添加了一个解析器规则,该规则不需要,因为它已经在词法分析器中匹配了。该词法分析器不应返回APOSTROPHE
作为令牌,因为它会在character_constant
令牌中被匹配。
您应该从character_constant
的野牛中删除规则,并将character_constant
添加到%token
声明中与词法分析器匹配的标记列表中。
我通常建议对令牌名称使用大写字母,以免产生歧义,即哪个是终端,哪个是非终端。