Ваш лексический анализатор возвращает пробелы и табуляции как токены, но грамматика не распознает их.
Добавьте правило синтаксического анализа:
[ \t\r] { }
Это приведет вас к строке 6 вместострока 0, прежде чем вы столкнетесь с ошибкой.Вы получаете эту ошибку, потому что не допускаете точки с запятой между объявлениями:
dec_block:
dec_list semiColon;
dec_list:
dec_list dec
|
dec
;
dec:
int_dec_list
;
Вероятно, это должно быть:
dec_block:
dec_block dec
|
dec
;
dec:
int_dec_list semiColon
;
В результате вы попадете на строку 14 во входных данных.
Кстати, одна из первых вещей, которые я сделал, - убедиться, что лексический анализатор сообщает мне, что он делает, изменив правила следующим образом:
if { printf("IF\n"); return IF; }
В долгосрочном коде яd сделать этот диагностический вывод выбираемым во время выполнения.
У вас есть общая проблема с точкой с запятой.Также не ясно, что вы должны разрешить expression_list
в правиле для statement
(или, может быть, «еще нет» - это может быть уместно, когда у вас есть вызовы функций, но допускается 3 + 2 / 4
в качестве «оператора»не очень полезно).
Эта грамматика доходит до конца ввода:
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
extern FILE *yyin;
extern int linenum;
%}
%token PROGRAM_SYM VAR_SYM BEGIN_SYM END_SYM INTEGER_SYM NUMBER
%token identifier INTEGER ASSIGNOP semiColon comma THEN
%token IF ELSE FOR WHILE
%token CON_EQ CON_LE CON_GE GE LE
%left '*' '/'
%left '+' '-'
%start program
%%
program: PROGRAM_SYM identifier semiColon VAR_SYM dec_block BEGIN_SYM statement_list END_SYM '.'
;
dec_block:
dec_block dec
|
dec
;
dec:
int_dec_list semiColon
;
int_dec_list:
int_dec_list int_dec ':' type
|
int_dec ':' type
;
int_dec:
int_dec comma identifier
|
identifier
;
type:
INTEGER_SYM
;
statement_list:
statement_list statement
|
statement
;
statement:
assignment
|
selection
;
assignment:
identifier ASSIGNOP expression semiColon
;
expression:
'(' expression ')'
|
expression '*' expression
|
expression '/' expression
|
expression '+' expression
|
expression '-' expression
|
factor
;
factor:
identifier
|
NUMBER
;
selection:
IF '(' logical_expression ')' THEN statement_list ELSE statement_list
;
logical_expression:
expression '=' expression
|
expression '>' expression
|
expression '<' expression
;
%%
void yyerror(char *s){
fprintf(stderr,"Error at line: %d\n",linenum);
}
int yywrap(){
return 1;
}
int main(int argc, char *argv[])
{
/* Call the lexer, then quit. */
yyin=fopen(argv[1],"r");
yyparse();
fclose(yyin);
return 0;
}
Основные изменения включают в себя удаление assignment_list
и expression_list
и изменение logical_expression
так что две стороны расширения - expression
, а не LHS, являющийся logical_expression
(который тогда никогда не имел примитивного определения, что приводило к проблемам с предупреждениями).
Есть еще проблемы сразрешить;expression_list
в selection
должно быть более ограничительным для точного отражения грамматики Паскаля.(Вам нужен блок, где это может быть один оператор или BEGIN, список операторов, END.)