parser.y:79.33-41: symbol character is used, but is not defined as a token 并且没有规则

parser.y:79.33-41: symbol character is used, but is not defined as a token and has no rules

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

消息的意思与它所说的完全一致。您使用符号 character 但您既没有将其声明为令牌,也没有为其提供产生式。所以它既不是终端也不是非终端,解析器生成器在使用时会报错。

分析器生成器看不到词法分析器中发生的事情。因此,您已经(毫无意义,恕我直言)创建了 {character} 的词法分析器定义这一事实仅在词法分析器文件中感兴趣。 (这毫无意义,因为你可以等效地使用 Posix 字符 class [[:alpha:]],它具有明确的含义并且与 {character} 一样可读。)实际上解析器并没有需要知道关于词法分析器如何得出令牌代码值的任何信息。因此,当您在解析器定义中声明一个标记时,解析器生成器会将该符号的定义放入头文件中;词法分析器 #include 那个头文件,并且让它使用那个符号作为解析器的 return 值。无需其他通信。

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

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

我通常建议使用大写字母作为令牌名称,以避免任何歧义,即终端和非终端。