parser.y:79.33-41:使用了符号字符,但未定义为令牌并且没有规则

时间:2018-11-07 06:10:49

标签: c bison flex-lexer yacc lexical-analysis

解析器出现问题,我无法解决这个问题。我不断收到错误: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到解析器的整个文件中的拼写都是正确的,没有人知道这里的问题是什么。我尝试将其更改为字母而不是字符,但这给了我另一个错误。

2 个答案:

答案 0 :(得分:1)

该消息的含义与所讲的完全相同。您使用了符号character,但是您既没有声明它是一个令牌,也没有提供它的生产版本。因此它既不是终端也不是非终端,并且解析器生成器在使用时会抱怨。

语法分析器生成器看不到词法分析器中发生的事情。因此,您(毫无意义,恕我直言)创建了{character}的词法分析器定义这一事实仅在词法分析器文件内部引起关注。 (这毫无意义,因为您可以等效地使用Posix字符类[[:alpha:]],它具有明确的含义,并且与{character}一样可读。)而且,解析器实际上不需要了解词法分析器的方式。附带令牌代码值。因此,当您在解析器定义中声明令牌时,解析器生成器会在头文件中放置该符号的定义。词法分析器#include是该头文件,并允许它使用该符号作为解析器的返回值。不需要其他通讯。

答案 1 :(得分:1)

错误是无法将单个字符与词法分析器中的标识符区分开。您已经正确添加了一个词法分析器规则来匹配它,该规则返回了名为character_constant的令牌,但是,您还为字符常量添加了一个解析器规则,该规则不需要,因为它已经在词法分析器中匹配了。该词法分析器不应返回APOSTROPHE作为令牌,因为它会在character_constant令牌中被匹配。

您应该从character_constant的野牛中删除规则,并将character_constant添加到%token声明中与词法分析器匹配的标记列表中。

我通常建议对令牌名称使用大写字母,以免产生歧义,即哪个是终端,哪个是非终端。