Lex & Yacc: gcc при компиляции y.tab.c выдает много ожидаемых ошибок токена

Я реализую язык программирования (катир) с помощью yacc и lex. Файлы Lex и yacc подготавливаются, а файлы lex.yy.c и y.tab.c создаются без ошибок. Но когда я вызываю gcc -o katir y.tab.c, он выдает большой список ошибок, например, и продолжается так:

y.tab.c:557:41: error: expected ‘;’ before ‘goto’
 yyloop:
                                         ^
y.tab.c:558:8: error: called object is not a function or function pointer
     if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
        ^
y.tab.c:559:5: error: expected ‘;’ before ‘{’ token
     if (yychar < 0)
     ^
y.tab.c:607:8: error: called object is not a function or function pointer
 yyinrecovery:
        ^
y.tab.c:608:5: error: expected ‘;’ before ‘{’ token
     if (yyerrflag < 3)
     ^
y.tab.c:666:8: error: called object is not a function or function pointer
     yym = yylen[yyn];
        ^
y.tab.c:667:9: error: expected ‘;’ before ‘yyval’
     if (yym)
         ^
y.tab.c:669:9: error: expected ‘;’ before ‘memset’
     else
         ^
y.tab.c:677:8: error: called object is not a function or function pointer
     yym = yylhs[yyn];
        ^
y.tab.c:678:5: error: expected ‘;’ before ‘{’ token
     if (yystate == 0 && yym == 0)
     ^
y.tab.c:708:9: error: expected ‘;’ before ‘yystate’
     else
         ^
y.tab.c:714:8: error: called object is not a function or function pointer
 #endif
        ^
y.tab.c:715:5: error: expected ‘;’ before ‘{’ token
     if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
     ^
y.tab.c:727:12: error: called object is not a function or function pointer
     yyfreestack(&yystack);
            ^
y.tab.c:731:12: error: called object is not a function or function pointer
     yyfreestack(&yystack);

Мой файл lex:

%{
#include <stdlib.h>
void yyerror(char *);
%}
begin begin
end end
assignment_op <-
endline \n
difference diff
set_type set
integer_type integer
char_type char
boolean_type boolean
string_type string
float_type float
constant const
equal ==|eq
comment {hashtag}([^\n])*\n
hashtag #
and \&\&|and
or \|\||or
cardinality_op \|
cp_op cp
set_del del
else else
not !|not
lt <|lt
gt >|gt
lte <=|lte
gte >=|gte
lp \(
rp \)
lcb \{
rcb \}
comma ,
endstmnt \;
underscore _
dot \.
digit [0-9]
letter[a-zA-Z]
if if
then then
do do
multiplier \*
divider \/
subtractor \-
adder \+
union uni
intersection inter
subset subs
superset sups 
while while
for for
fc fc
return return
input input
output output
true true
false false
space ([ ])
boolean TRUE|FALSE
integer [+-]?({digit})+
float ({integer})*(\.({digit})+|({digit})+\.)({digit})*
char \'[^\\\']\'
string \"([^\\\"]|\\\"|\\\n|\\\\)*\"
identifier {letter}({letter}|{digit}|{underscore})*
text ([^\\\"]|\\\"|\\\n|\\\\)*
whitespace [ \t]
%option yylineno
%%
{end} return end;
{begin} return begin;
{assignment_op} return assignment_op;
{equal} return equality_op;
{hashtag} return hashtag;
{set_type} return set_type;
{and} return and;
{or} return or;
{else} return else;
{lp} return lp;
{rp} return rp;
{lcb} return lb;
{rcb} return rb;
{lt} return lt;
{gt} return gt;
{lte} return lte;
{gte} return gte;
{comma} return comma;
{dot} return dot;
{then} return then;
{cardinality_op} return cardinality_op;
{cp_op} return cp_op;
{set_del} return del;
{float} return float;
{digit} return digit;
{integer} return integer;
{integer_type} return int_type;
{char_type} return char_type;
{boolean_type} return boolean_type;
{string_type} return string_type;
{float_type} return float_type;
{if} return if;
{do} return do;
{while} return while;
{for} return for;
{true} return true;
{false} return false;
{difference} return difference;
{union} return union;
{intersection} return intersection;
{subset} return subset;
{superset} return superset;
{constant} return constant;
{boolean} return boolean;
{char} return char;
{fc} return fc;
{endline} ;
{whitespace};
{return} return return;
{output} return output;
{input} return input;
{string} return string;
{identifier} return identifier;
{comment} return comment;
{endstmnt} return endstmnt;
{underscore} return underscore;
{multiplier} return multiplier;
{divider} return divider;
{subtractor} return subtractor;
{adder} return adder;
{text} return text;

%%
int yywrap(){return 1;}

И файл yacc выглядит следующим образом:

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token begin
%token end
%token assignment_op
%token equal
%token hashtag
%token constant
%token and
%token or
%token then
%token not
%token else
%token lp
%token rp
%token lcb
%token rcb
%token comment
%token lt
%token gt
%token lte
%token gte
%token comma
%token dot
%token cardinality_op
%token cp_op
%token set_del
%token float
%token digit
%token integer
%token integer_type
%token char_type
%token boolean_type
%token string_type
%token float_type
%token if
%token do
%token while
%token for
%token true
%token false
%token difference
%token union
%token set_type
%token intersection
%token subset
%token superset
%token constant
%token boolean
%token char
%token fc
%token return
%token output 
%token input
%token string
%token identifier
%token comment
%token endstmnt
%token underscore
%token multiplier
%token divider
%token subtractor
%token adder
%token text

%start program
%right assignment_op
%left adder subtractor difference intersection union
%left multiplier divider
%left cp_op
%%

//Start Rule
program:
    begin stmnt_l end; 
stmnt_l:
    stmnt endstmnt
    |stmnt endstmnt stmnt_l 
    ;
//Possible statement types
stmnt:
    if_stmnt;
nan_if:
    loop_stmnt
    |expression
    |declare
    |initialize
    |in_out_stmnt
    |function
    ;
loop_stmnt: 
    while_stmnt
    |for_stmnt
    |do_while_stmnt  
    ;
if_stmnt: matched | unmatched;
matched: if logical_expression then matched else matched| nan_if;

unmatched: if logical_expression then stmnt
       | if logical_expression then matched else unmatched;

while_stmnt: while lp logical_expression rp lcb stmnt_l rcb;

do_while_stmnt: do lcb stmnt_l rcb while logical_expression ;

for_stmnt: for lp initialize endstmnt logical_expression lp stmnt_l rp;

term: var | constant_type | function_call;

constant_type: constant var;

var: identifier;

//Types
type: boolean | string | integer | float; //|set
primitive: boolean_type | string_type | integer_type | float_type | set_type; 
set: lcb list rcb | lcb rcb;
list: type | var | type comma list | var comma list;
//----------------------------------Declerations----------------------------------------------
declare:
    primitive var;

init_types:
    type | function_call | set_exp;
initialize:
    declare assignment_op init_types | var assignment_op init_types;


//Connectives
logical_operator: subset | superset | lt | gt | and | or | not | equal;
logical_expression: term logical_operator logical_expression | term logical_operator term | not_expression;
not_expression: not lp logical_expression rp;
del_expression: set_del var;

//Arithmetic
arithmetic_expression: arithmetic_expression adder arithmetic_expression | exp2;
exp2: exp2 subtractor exp2 | exp3;
exp3: exp3 multiplier exp3 | exp4;
exp4: exp4 divider exp4 | exp5;
exp5: integer | float | function_call;

//Set Expressions
set_exp: exp_uni;
exp_uni: exp_uni union exp_uni | exp_intersection;
exp_intersection: exp_intersection intersection exp_intersection| exp_diff;
exp_diff: exp_diff difference exp_diff|exp_cartesian;
exp_cartesian: exp_cartesian cp_op exp_cartesian | set;

expression: arithmetic_expression | logical_expression | cardinality_expression | del_expression;
cardinality_expression: cardinality_op var cardinality_op | cardinality_op set cardinality_op;

//Input/Output
in_out_stmnt: input_stmnt | output_stmnt;
input_stmnt: input lp input_body rp;
input_body: type var;
output_stmnt: output lp output_body rp;
output_body: var;

//Function
function: type var lp arguments rp lcb stmnt_l return_stmnt rcb
      | type var lp rp lcb stmnt_l return_stmnt rcb;
arguments: primitive var | primitive var comma arguments;
function_call: fc lp parameters rp | fc lp rp;
parameters: var | var comma parameters |type comma parameters;
return_stmnt: return var;

%%
#include "lex.yy.c"
int yyerror(char *s) {
    fprintf(stdout, "line %d: %s\n", yylineno,s);
}
int main(){
 return yyparse();
 if(yynerrs < 1){
    printf("Parsing is successful\n");
 }
 return 0;
}

И, наконец, весь код, который я вызываю в терминале Linux, следующий:

flex katir.l
yacc katir.yacc
gcc -o katir y.tab.c

Просмотрите файл ytab.c. Перед первой сообщенной ошибкой должна быть синтаксическая ошибка. Он будет в одном из ваших исходных файлов. Ваша грамматика yacc выглядит нормально.   —  person Çağlar Ç.    schedule 05.04.2020

См. также:  Получение веб-страниц из переменной

Примечание: return yyparse(); в main означает, что остальная часть main не будет выполнена.   —  person Çağlar Ç.    schedule 05.04.2020

Разве y.tab.c не является автоматически созданным файлом? Я посмотрел и не понял, как найти синтаксическую ошибку. Если хотите, я могу добавить все полученное сообщение об ошибке. Извините за эти вопросы новичков, так как я новичок в этой платформе, а также спасибо за поддержку @PaulOgilvie   —  person Çağlar Ç.    schedule 05.04.2020

Это потому, что использование имен токенов, таких как логические миксы с зарезервированным словом C boolean, поскольку в y.tab.c есть вызов как файл #define boolean 302, или есть другая проблема?   —  person Çağlar Ç.    schedule 05.04.2020

@PaulOgilvie Конечно, они могут столкнуться. Если у вас есть #define int 258 и #define if 259, то это приведет к тому, что что-то вроде int main() станет 258 main(), что является синтаксической ошибкой, и if (cond) станет 259 (cond), что является ошибкой типа. Это похоже на проблему OP.   —  person Çağlar Ç.    schedule 05.04.2020

@ sepp2k; !!Виноват. Столкнитесь наоборот. Не думал об этом.   —  person Çağlar Ç.    schedule 05.04.2020

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Çağlar Ç.

    Как вы уже догадались в комментарии, ваша проблема в том, что имена ваших токенов конфликтуют с ключевыми словами C. Определение токена if в вашем файле yacc приведет к тому, что сгенерированный файл C будет содержать как строку типа if = 258 (где 258, конечно, может быть другое число) внутри объявления enum, так и #define if 258 впоследствии. if = 258 — это, конечно, синтаксическая ошибка, а #define if 258 вызовет ошибки везде, где if используется как часть фактического оператора if в любом месте следующего кода (потому что что-то вроде if(cond) станет 42(cond), что является ошибкой типа). То же самое и с любыми другими ключевыми словами.

    По соглашению имена токенов должны быть записаны в ALL_CAPS, чтобы избежать именно этой проблемы.

    bison генерирует #defines только в том случае, если вы вызываете его с параметром -y/--yacc (или используете файл сценария yacc, который поставляется с дистрибутивом bison, который делает именно это). Posix требует #define, но они могут сильно раздражать; без опции обратной совместимости -y bison генерирует только enum. person Çağlar Ç.; 05.04.2020

    @rici Это все еще оставляет синтаксическую ошибку из if = 258 в объявлении enum (я знаю, что вы это знаете, я просто разъясняю OP / другим читателям, что вы не говорите, что bison не сделает безопасным использование ключевых слов в качестве имена токенов). person Çağlar Ç.; 05.04.2020

    Правильно, вы никогда не можете использовать ключевые слова. Но без #defines у вас, по крайней мере, не возникнет проблем со столкновением с идентификаторами, используемыми в коде, который представляет собой гораздо больший и менее контролируемый набор имен (поскольку возможно, что файл заголовка будет включен в другие ЕП). Безусловно, вы должны использовать ALLCAPS для токенов (и я также обычно использую префикс). Но нет веских причин использовать -y. person Çağlar Ç.; 05.04.2020

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: