parser.y: 79.33-41: символьный символ используется, но не определен как токен и не имеет правил - PullRequest
0 голосов
/ 07 ноября 2018

У меня проблема с парсером, и я просто не могу обернуть голову вокруг него. Я продолжаю получать ошибку : 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 голосов
/ 07 ноября 2018

Ошибка в том, что отдельный символ нельзя отличить от идентификатора в лексере. Вы правильно добавили правило лексера, чтобы соответствовать ему, которое возвращает токен с именем character_constant, однако вы также добавили правило синтаксического анализа для символьной константы, которая не нужна, так как она уже сопоставлена ​​в лексере. Лексер не должен возвращать APOSTROPHE в качестве токена, поскольку он соответствовал бы в character_constant токене.

Вы должны просто удалить правило из bison для character_constant и добавить character_constant в список токенов, соответствующих лексеру в объявлении %token.

Я бы обычно рекомендовал использовать заглавные буквы для имен токенов, чтобы избежать двусмысленности в том, что является терминалом, а что нетерминалом.

0 голосов
/ 07 ноября 2018

Сообщение означает именно то, что оно говорит. Вы используете символ character, но вы не объявили его токеном и не предоставили для него продукцию. Поэтому он не является ни терминальным, ни нетерминальным, и генератор синтаксического анализатора жалуется, когда он используется.

То, что происходит в вашем лексере, не видно генератору парсера. Поэтому тот факт, что вы (бессмысленно, ИМХО) создали определение лексера {character}, представляет интерес только внутри файла лексера. (Это бессмысленно, потому что вы могли бы эквивалентно использовать класс символов Posix [[:alpha:]], который имеет ясное значение и столь же читабелен, как и {character}.) И действительно, парсеру не нужно ничего знать о том, как лексер предлагает кодовое значение токена Поэтому, когда вы объявляете токен в определении парсера, генератор парсера помещает определение для этого символа в заголовочный файл; этот заголовочный файл получает лексер #include, что позволяет ему использовать этот символ в качестве возвращаемого значения для синтаксического анализатора. Никакого другого общения не требуется.

...