Функция yylex()
является лексическим сканером, а не грамматическим парсером;парсер yyparse()
.Поэтому обновите вашу программу так, чтобы она вызывала yyparse()
вместо yylex()
, оставляя yyparse()
для вызова yylex()
, когда ей нужен новый токен:
while (yyparse() != 0)
;
Вы можете выполнить печать дерева разбора вместо пустого тела цикла, или вы можете печатать в функции, вызываемой из правила запуска в самой грамматике.
Что касается сопутствующей заметки, я не могу придумать вескую причину для использования объявления K & Rmain()
.Всегда используйте int main(int argc, char **argv)
.И если вы используете нотацию K & R, то вы должны вернуть значение из main()
, обычно ноль в случае успеха и ненулевое значение в случае сбоя.Хотя C99 позволяет вам опустить окончательный возврат с main()
(что эквивалентно return 0;
в единственном исключительном случае main()
), я рекомендую включить его.
Более поздние примечания
Хорошая идея - сделать так, чтобы людям было легко проверить, с чем вы обращаетесь за помощью.Предоставьте достаточно источника, чтобы сделать его компилируемым.Удалите достаточно источника, чтобы минимизировать усилия по компиляции.
Было не очень сложно нейтрализовать различные функции действия в грамматике.Файл parser.h
должен содержать что-то вроде typedef struct tree tree;
.И грамматика должна была быть idf.y
, чтобы bison -d idf.y
генерировал idf.tab.h
и idf.tab.c
.
Одна из первых вещей, которые я делаю с лексическим анализатором, - убедитесь, что он печатает то, что делает,Итак, я изменил правила, чтобы сделать что-то вроде:
{ID} |
-?{DIGIT}+"."{DIGIT}* |
-?{DIGIT}+ { printf("ID or number: %s\n", yytext); /*yylval.a_variable = findname(yytext);*/ return TOKID; }
";" { printf("Semi-colon\n"); return TOKSEMICOLON;}
":" { printf("Colon\n"); return TOKCOLON;}
Это довольно быстро показало мне, что вы не очень аккуратно обрабатываете пробелы или переводы строки.Вероятно, вам нужны правила для этого (и эти правила, вероятно, не возвращаются к грамматике).
[ \t] { printf("White space\n"); }
Это должно появиться перед правилом «сожирающая точка», конечно.
Имея это в виду, я смог запустить программу и получить лексический вывод:
$ ./idf
abc ;
ID or number: abc
White space
Semi-colon
$
Я набрал abc ;
, и он идентифицировал все в порядке.Поскольку в действиях грамматики не осталось кода, не было выходных данных самой грамматики.Вероятно, стоило бы скомпилировать с -DYYDEBUG
и установить yydebug = 1;
в функции main()
- вам может понадобиться добавить extern int yydebug;
в исходный файл лексического анализатора, так как main()
есть.
$ flex scanner.l
$ bison -d idf.y
$ gcc -DYYDEBUG -o idf idf.tab.c lex.yy.c
$ ./idf
Starting parse
Entering state 0
Reading a token: abc ;
ID or number: abc
Next token is token TOKID ()
Shifting token TOKID ()
Entering state 1
Reducing stack by rule 7 (line 32):
$1 = token TOKID ()
-> $$ = nterm ID ()
Stack now 0
Entering state 5
Reading a token: White space
Semi-colon
Next token is token TOKSEMICOLON ()
Shifting token TOKSEMICOLON ()
Entering state 8
Reducing stack by rule 6 (line 29):
$1 = nterm ID ()
$2 = token TOKSEMICOLON ()
-> $$ = nterm obj ()
Stack now 0
Entering state 4
Reducing stack by rule 5 (line 26):
$1 = nterm obj ()
-> $$ = nterm field ()
Stack now 0
Entering state 3
Reading a token:
Now at end of input.
Reducing stack by rule 1 (line 20):
$
Теперь ваши проблемы в функциях, которые вы не показывали.Это твое решение.