Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I've been having an issue a while now while creating the front-end for a compiler with a flex/bison (right now we're at the stage where we create the lexer and syntax analyzer, with flex and bison accordingly).

Please note I'm a completely new to lexing/parsing and flex/bison, so all tips are more than welcome.

The issue I'm currently facing, is that I keep getting a newline syntax error with bison. Here are the files:

lexer.l

#include <stdio.h> #include <stdlib.h> #include "sym_hashing.h" #include "fifostrq.h" #include "parser.h" FILE *new_file; void add_bloc_number(); void reduce_bloc_number(); void singleLineComment(); void multiLineComment(); void handleError(char*); void validateNum(char*); void genericParse(char*); DEQ* errQue; %option yylineno %option noyywrap alpha [A-Za-z] digit [0-9] identifier {alpha}({alpha}|{digit})* integer (-?{digit}{1,5}) constString \"(\\.|[^"\\])*\" other [\n\r\t\v\f]+ "LET" {return(LET); } "DO" {return(DO); } "LOOP" {return(LOOP); } "UNTIL" {return(UNTIL); } "WHILE" {return(WHILE); } "WEND" {return(WEND); } "SUB" {return(SUB); } "CALL" {return(CALL); } "INPUT" {return(INPUT); } "PRINT" {return(PRINT); } "IF" {return(IF); } "THEN" {return(THEN); } "ELSE" {return(ELSE); } "AND" {return(AND); } "NOT" {return(NOT); } "OR" {return(OR); } "RETURN" {return(RETURN); } "REM" {singleLineComment();} "+" {return(PLUS);} "-" {return(MINUS);} "*" {return(STAR);} "/" {return(DIV);} "<" {return(LT);} ">" {return(GT);} "<=" {return(LTEQUAL);} ">=" {return(GTEQUAL);} "<>" {return(LTGT);} ";" {return(SEMICOLON);} "," {return(COMMA);} "(" {return(LPAREN);} ")" {return(RPAREN);} "[" {return(LBRACK);} "]" {return(RBRACK);} "{" {return(LSWIGLY);} "}" {return(RSWIGLY);} "=" {printf("Found =\n"); return(ASSIGNMENT);} "==" {return(EQUALS);} "%*" {multiLineComment();} {constString} { yylval.conststr=strdup(yytext); printf("Found %s\n", yylval.conststr); return(CONSTSTR);} {integer} { yylval.constnum=strdup(yytext); printf("Found %s\n", yylval.constnum); validateNum(yylval.constnum); return(CONSTINT);} {identifier} { yylval.name=strdup(yytext); printf("Found %s\n", yylval.name); return(IDENTIFIER);} {other} {} . { char* yycopy=strdup(yytext); genericParse(yycopy);} void genericParse(char * val) { if (val[0] != '\0' && val[0] != ' ' && val != NULL) { handleError(val); void handleError(char * token) { char * buff = malloc(sizeof(char) * (strlen(token) + 36)); sprintf(buff, "Lexer ERROR at line %d of token %s\n", line, token); insertAtHead(errQue, buff); void singleLineComment() { int c; while ((c = input()) != '\n' && c != EOF); line++; void validateNum(char * value) { int num = atoi(value); if (num < -32768 || num > 32767) { handleError(value); return; void add_bloc_number() { block_num = block_num + 1; void reduce_bloc_number() { block_num = block_num - 1; void multiLineComment() { int c, flag = 0; for (;;) { while ((c = input()) != '*' && c != EOF) { if (c == '\n') { line++; if (c == '*') { while ((c = input()) == '*') { if (c == '\n') { line++; if (c == '%') { break; if (c == EOF) { printf("ERROR: EOF in comment\n"); break;

gram.y

#include <stdio.h> #include <string.h> #include <malloc.h> #include "fifostrq.h" #include "sym_tab.h" extern int column; extern void yyrestart( FILE *input_file ); extern char *yytext; extern FILE *yyin; extern int yylineno; extern int block_num; int yyerror(const char *s); int column; %locations %define parse.error verbose %define parse.lac full %printer { fputs($$, yyo); } IDENTIFIER %union char *name; char *constnum; char *conststr; %token IDENTIFIER %token CONSTINT CONSTSTR %token LET DO LOOP UNTIL WHILE WEND SUB %token CALL INPUT PRINT IF THEN ELSE AND %token NOT OR RETURN ASSIGNMENT NEWLINE %token PLUS MINUS STAR DIV LT GT LTEQUAL GTEQUAL %token LTGT SEMICOLON COMMA LPAREN RPAREN %token LSWIGLY RSWIGLY EQUALS LBRACK RBRACK %token MISC %right ASSIGNMENT %left LT GT LTEQUAL GTEQUAL LTGT EQUALS %left AND OR %right NOT %left PLUS MINUS %left STAR DIV %type <name> IDENTIFIER %type <constnum> CONSTINT %type <conststr> CONSTSTR %start program program: statement_or_func newline_statement_or_func_op newline_statement_or_func_op: /*empty*/ | NEWLINE statement_or_func newline_statement_or_func_op statement_or_func: sequence | func_stat sequence: statement | sequence le statement NEWLINE | SEMICOLON brackets_seq: LSWIGLY sequence RSWIGLY brack_or_stat: brackets_seq | statement statement: /*empty*/ | decl_stat assignment_stat | if_stat | do_until_stat | while_stat | return_stat | print_stat | input_stat | func_stat | call_stat /*comment stat is not needed, they are removed by the lexer*/ decl_stat: LET declaration | decl_stat COMMA declaration declaration: IDENTIFIER | assignment_stat assignment_stat: IDENTIFIER ASSIGNMENT expression if_stat: IF LPAREN condition RPAREN THEN brack_or_stat elsepart elsepart: /*empty*/ | ELSE brack_or_stat do_until_stat: DO brack_or_stat LOOP UNTIL LPAREN condition RPAREN while_stat: WHILE LPAREN condition RPAREN brack_or_stat WEND return_stat: RETURN LPAREN expression RPAREN /*with the grammar rule specified in the pdf, PRINT "*"; wouldn't work*/ print_stat: PRINT CONSTSTR le | PRINT CONSTSTR COMMA expression_list expression_list: expression | expression_list COMMA expression input_stat: INPUT CONSTSTR COMMA IDENTIFIER | input_stat COMMA IDENTIFIER func_stat: SUB IDENTIFIER funcbody funcbody: formalpars brackets_seq formalpars: LPAREN /*empty*/ RPAREN | LPAREN formalparlist RPAREN formalparlist: IDENTIFIER | formalparlist COMMA IDENTIFIER call_stat: CALL IDENTIFIER actualpars actualpars: LPAREN /*empty*/ RPAREN | LPAREN actualparlist RPAREN actualparlist: actualparitem | actualparlist COMMA actualparitem actualparitem: expression | IDENTIFIER /*comment stat is not needed, it is removed by the parser regardless...*/ condition: boolterm | condition OR boolterm boolterm: boolfactor | boolterm AND boolterm boolfactor : NOT LBRACK condition RBRACK | LBRACK condition RBRACK | expression relational_oper expression expression: optional_sign term | expression add_oper optional_sign term term: factor | term mul_oper factor factor: constant | LPAREN expression RPAREN | IDENTIFIER | call_stat constant: CONSTINT | CONSTSTR relational_oper: EQUALS | LT | LTEQUAL | LTGT | GTEQUAL | GT add_oper: PLUS | MINUS mul_oper: STAR | DIV optional_sign: /*empty*/ | add_oper int yydebug; int main(int argc, char *argv[]){ #ifdef YYDEBUG yydebug = 1; #endif createDEQ(&errQue); if (argc != 2) printf("\nUsage: lexyy <input file name> \n"); if ((yyin = fopen(argv[1], "r")) == NULL) printf("\n<%s> not found.\n", argv[1]); else { yyrestart(yyin); yyparse(); fclose(yyin); printQueue(errQue); freeDEQ( & errQue); return 0; int yyerror(const char *token) { fflush(stdout); char *buff = malloc(sizeof(char) * 1000); sprintf(buff, "\n-----------------------\n%s\n%*s\n%*s\tLine: %d\tColumn: %d\tBlock: %d\n-----------------------\n", yytext, column, "^", column, token, yylineno, column, block_num); insertAtHead(errQue, buff); return 0; static int yyprint(FILE *file, int type, YYSTYPE value) { if (type == IDENTIFIER) fprintf (stderr," = %s", value.name); return 1;
<PROGRAM> ::= < STATEMENT-OR-FUNC >
(‘\n’ < STATEMENT-OR-FUNC >)*
<STATEMENT-OR-FUNC> ::= < SEQUENCE > |
<FUNC-STAT>
<SEQUENCE> ::= <STATEMENT> ( <LE> <STATEMENT> )*
<LE> ::= ‘\n’ | ‘;’
<BRACKETS-SEQ> ::= { <SEQUENCE> }
<BRACK-OR-STAT> ::= <BRACKETS-SEQ> | <STATEMENT>
<STATEMENT> ::= ε |
<DECL-STAT>
<ASSIGNMENT-STAT> |
<IF-STAT> |
<DO-UNTIL-STAT> |
<WHILE-STAT> |
<RETURN-STAT> |
<PRINT-STAT> |
<INPUT-STAT> |
<FUNC-STAT> |
<CALL-STAT> |
<COMMENT-STAT>
< DECL-STAT > ::= LET ASSIGNMENT-STAT ( , DECLARATION)*
< DECLARATION > ::= ID | ASSIGNMENT-STAT
<ASSIGNMENT-STAT> ::= ID = <EXPRESSION>
...and others (irrelevant, read on)

input file

LET a, a1=2, n, i, max1=-1
a = 5;
b = 4;

With the fix provided in the response in the comments below, I still get this error:

Starting parse
Entering state 0
Reading a token: --(end of buffer or a NUL)
--accepting rule at line 29 ("LET")
Next token is token LET ()
Shifting token LET ()
Entering state 1
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 98 ("a")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 1
Entering state 24
Reading a token: --accepting rule at line 78 (",")
Next token is token COMMA ()
Reducing stack by rule 28 (line 107):
   $1 = nterm identifier ()
-> $$ = nterm declaration ()
Stack now 0 1
Entering state 25
Next token is token COMMA ()
Shifting token COMMA ()
Entering state 49
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 98 ("a1")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 1 25 49
Entering state 24
Reading a token: --accepting rule at line 87 ("=")
Next token is token ASSIGNMENT ()
Shifting token ASSIGNMENT ()
Entering state 48
Reading a token: --accepting rule at line 95 ("2")
Next token is token CONSTINT ()
Reducing stack by rule 88 (line 264):
-> $$ = nterm optional_sign ()
Stack now 0 1 25 49 24 48
Entering state 62
Next token is token CONSTINT ()
Shifting token CONSTINT ()
Entering state 97
Reducing stack by rule 76 (line 249):
   $1 = token CONSTINT ()
-> $$ = nterm constant ()
Stack now 0 1 25 49 24 48 62
Entering state 104
Reducing stack by rule 72 (line 245):
   $1 = nterm constant ()
-> $$ = nterm factor ()
Stack now 0 1 25 49 24 48 62
Entering state 103
Reading a token: --accepting rule at line 78 (",")
Next token is token COMMA ()
Reducing stack by rule 69 (line 235):
-> $$ = nterm mul_oper_op ()
Stack now 0 1 25 49 24 48 62 103
Entering state 130
Reducing stack by rule 71 (line 241):
   $1 = nterm factor ()
   $2 = nterm mul_oper_op ()
-> $$ = nterm term ()
Stack now 0 1 25 49 24 48 62
Entering state 102
Next token is token COMMA ()
Reducing stack by rule 66 (line 226):
-> $$ = nterm add_oper_op ()
Stack now 0 1 25 49 24 48 62 102
Entering state 126
Reducing stack by rule 68 (line 232):
   $1 = nterm optional_sign ()
   $2 = nterm term ()
   $3 = nterm add_oper_op ()
-> $$ = nterm expression ()
Stack now 0 1 25 49 24 48
Entering state 78
Reducing stack by rule 30 (line 112):
   $1 = nterm identifier ()
   $2 = token ASSIGNMENT ()
   $3 = nterm expression ()
-> $$ = nterm assignment_stat ()
Stack now 0 1 25 49
Entering state 26
Reducing stack by rule 29 (line 108):
   $1 = nterm assignment_stat ()
-> $$ = nterm declaration ()
Stack now 0 1 25 49
Entering state 79
Next token is token COMMA ()
Shifting token COMMA ()
Entering state 49
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 98 ("n")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 1 25 49 79 49
Entering state 24
Reading a token: --accepting rule at line 78 (",")
Next token is token COMMA ()
Reducing stack by rule 28 (line 107):
   $1 = nterm identifier ()
-> $$ = nterm declaration ()
Stack now 0 1 25 49 79 49
Entering state 79
Next token is token COMMA ()
Shifting token COMMA ()
Entering state 49
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 98 ("i")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 1 25 49 79 49 79 49
Entering state 24
Reading a token: --accepting rule at line 78 (",")
Next token is token COMMA ()
Reducing stack by rule 28 (line 107):
   $1 = nterm identifier ()
-> $$ = nterm declaration ()
Stack now 0 1 25 49 79 49 79 49
Entering state 79
Next token is token COMMA ()
Shifting token COMMA ()
Entering state 49
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 98 ("max1")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 1 25 49 79 49 79 49 79 49
Entering state 24
Reading a token: --accepting rule at line 87 ("=")
Next token is token ASSIGNMENT ()
Shifting token ASSIGNMENT ()
Entering state 48
Reading a token: --accepting rule at line 95 ("-1")
Next token is token CONSTINT ()
Reducing stack by rule 88 (line 264):
-> $$ = nterm optional_sign ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48
Entering state 62
Next token is token CONSTINT ()
Shifting token CONSTINT ()
Entering state 97
Reducing stack by rule 76 (line 249):
   $1 = token CONSTINT ()
-> $$ = nterm constant ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48 62
Entering state 104
Reducing stack by rule 72 (line 245):
   $1 = nterm constant ()
-> $$ = nterm factor ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48 62
Entering state 103
Reading a token: --accepting rule at line 76 ("
Next token is token NEWLINE ()
Reducing stack by rule 69 (line 235):
-> $$ = nterm mul_oper_op ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48 62 103
Entering state 130
Reducing stack by rule 71 (line 241):
   $1 = nterm factor ()
   $2 = nterm mul_oper_op ()
-> $$ = nterm term ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48 62
Entering state 102
Next token is token NEWLINE ()
Reducing stack by rule 66 (line 226):
-> $$ = nterm add_oper_op ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48 62 102
Entering state 126
Reducing stack by rule 68 (line 232):
   $1 = nterm optional_sign ()
   $2 = nterm term ()
   $3 = nterm add_oper_op ()
-> $$ = nterm expression ()
Stack now 0 1 25 49 79 49 79 49 79 49 24 48
Entering state 78
Reducing stack by rule 30 (line 112):
   $1 = nterm identifier ()
   $2 = token ASSIGNMENT ()
   $3 = nterm expression ()
-> $$ = nterm assignment_stat ()
Stack now 0 1 25 49 79 49 79 49 79 49
Entering state 26
Reducing stack by rule 29 (line 108):
   $1 = nterm assignment_stat ()
-> $$ = nterm declaration ()
Stack now 0 1 25 49 79 49 79 49 79 49
Entering state 79
Next token is token NEWLINE ()
Reducing stack by rule 25 (line 97):
-> $$ = nterm comma_declaration_op ()
Stack now 0 1 25 49 79 49 79 49 79 49 79
Entering state 117
Reducing stack by rule 26 (line 99):
   $1 = token COMMA ()
   $2 = nterm declaration ()
   $3 = nterm comma_declaration_op ()
-> $$ = nterm comma_declaration_op ()
Stack now 0 1 25 49 79 49 79 49 79
Entering state 117
Reducing stack by rule 26 (line 99):
   $1 = token COMMA ()
   $2 = nterm declaration ()
   $3 = nterm comma_declaration_op ()
-> $$ = nterm comma_declaration_op ()
Stack now 0 1 25 49 79 49 79
Entering state 117
Reducing stack by rule 26 (line 99):
   $1 = token COMMA ()
   $2 = nterm declaration ()
   $3 = nterm comma_declaration_op ()
-> $$ = nterm comma_declaration_op ()
Stack now 0 1 25 49 79
Entering state 117
Reducing stack by rule 26 (line 99):
   $1 = token COMMA ()
   $2 = nterm declaration ()
   $3 = nterm comma_declaration_op ()
-> $$ = nterm comma_declaration_op ()
Stack now 0 1 25
Entering state 50
Next token is token NEWLINE ()
Shifting token NEWLINE ()
Entering state 42
Reducing stack by rule 10 (line 70):
   $1 = token NEWLINE ()
-> $$ = nterm le ()
Stack now 0 1 25 50
Entering state 80
Reducing stack by rule 27 (line 103):
   $1 = token LET ()
   $2 = nterm declaration ()
   $3 = nterm comma_declaration_op ()
   $4 = nterm le ()
-> $$ = nterm decl_stat ()
Stack now 0
Entering state 14
Reading a token: --accepting rule at line 98 ("a")
Next token is token IDENTIFIER ( = (null))
Shifting token IDENTIFIER ( = (null))
Entering state 23
Reducing stack by rule 2 (line 43):
   $1 = token IDENTIFIER ( = (null))
-> $$ = nterm identifier ()
Stack now 0 14
Entering state 46
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 87 ("=")
Next token is token ASSIGNMENT ()
Shifting token ASSIGNMENT ()
Entering state 48
Reading a token: --accepting rule at line 100 (" ")
--accepting rule at line 95 ("5")
Next token is token CONSTINT ()
Reducing stack by rule 88 (line 264):
-> $$ = nterm optional_sign ()
Stack now 0 14 46 48
Entering state 62
Next token is token CONSTINT ()
Shifting token CONSTINT ()
Entering state 97
Reducing stack by rule 76 (line 249):
   $1 = token CONSTINT ()
-> $$ = nterm constant ()
Stack now 0 14 46 48 62
Entering state 104
Reducing stack by rule 72 (line 245):
   $1 = nterm constant ()
-> $$ = nterm factor ()
Stack now 0 14 46 48 62
Entering state 103
Reading a token: --accepting rule at line 77 (";")
Next token is token SEMICOLON ()
Reducing stack by rule 69 (line 235):
-> $$ = nterm mul_oper_op ()
Stack now 0 14 46 48 62 103
Entering state 130
Reducing stack by rule 71 (line 241):
   $1 = nterm factor ()
   $2 = nterm mul_oper_op ()
-> $$ = nterm term ()
Stack now 0 14 46 48 62
Entering state 102
Next token is token SEMICOLON ()
Reducing stack by rule 66 (line 226):
-> $$ = nterm add_oper_op ()
Stack now 0 14 46 48 62 102
Entering state 126
Reducing stack by rule 68 (line 232):
   $1 = nterm optional_sign ()
   $2 = nterm term ()
   $3 = nterm add_oper_op ()
-> $$ = nterm expression ()
Stack now 0 14 46 48
Entering state 78
Reducing stack by rule 30 (line 112):
   $1 = nterm identifier ()
   $2 = token ASSIGNMENT ()
   $3 = nterm expression ()
-> $$ = nterm assignment_stat ()
Stack now 0 14
Entering state 47
Reducing stack by rule 16 (line 85):
   $1 = nterm decl_stat ()
   $2 = nterm assignment_stat ()
-> $$ = nterm statement ()
Stack now 0
Entering state 13
Next token is token SEMICOLON ()
Shifting token SEMICOLON ()
Entering state 43
Reducing stack by rule 11 (line 71):
   $1 = token SEMICOLON ()
-> $$ = nterm le ()
Stack now 0 13
Entering state 45
Reading a token: --accepting rule at line 76 ("
Next token is token NEWLINE ()
Reducing stack by rule 15 (line 83):
-> $$ = nterm statement ()
Stack now 0 13 45
Entering state 77
Next token is token NEWLINE ()
Shifting token NEWLINE ()
Entering state 42
Reducing stack by rule 10 (line 70):
   $1 = token NEWLINE ()
-> $$ = nterm le ()
Stack now 0 13 45 77
Entering state 45
Reading a token: --accepting rule at line 98 ("b")
Next token is token IDENTIFIER ( = (null))
Reducing stack by rule 15 (line 83):
-> $$ = nterm statement ()
Stack now 0 13 45 77 45
Entering state 77
Next token is token IDENTIFIER ( = (null))
Reducing stack by rule 7 (line 60):
-> $$ = nterm le_statement_op ()
Stack now 0 13 45 77 45 77
Entering state 116
Reducing stack by rule 8 (line 62):
   $1 = nterm le ()
   $2 = nterm statement ()
   $3 = nterm le_statement_op ()
-> $$ = nterm le_statement_op ()
Stack now 0 13 45 77
Entering state 116
Reducing stack by rule 8 (line 62):
   $1 = nterm le ()
   $2 = nterm statement ()
   $3 = nterm le_statement_op ()
-> $$ = nterm le_statement_op ()
Stack now 0 13
Entering state 44
Reducing stack by rule 9 (line 66):
   $1 = nterm statement ()
   $2 = nterm le_statement_op ()
-> $$ = nterm sequence ()
Stack now 0
Entering state 12
Reducing stack by rule 5 (line 56):
   $1 = nterm sequence ()
-> $$ = nterm statement_or_func ()
Stack now 0
Entering state 11
Next token is token IDENTIFIER ( = (null))
Reducing stack by rule 3 (line 50):
-> $$ = nterm newline_statement_or_func_op ()
Stack now 0 11
Entering state 41
Reducing stack by rule 1 (line 38):
   $1 = nterm statement_or_func ()
   $2 = nterm newline_statement_or_func_op ()
-> $$ = nterm program ()
Stack now 0
Entering state 10
Next token is token IDENTIFIER ( = (null))
Error: popping nterm program ()
Stack now 0
Cleanup: discarding lookahead token IDENTIFIER ( = (null))
Stack now 0
syntax error, unexpected IDENTIFIER, expecting $end
Process finished with exit code 1

I do not understand how this makes sense, from my end. It found an identifier (I cannot figure out which token it refers to, due to the broken yyerror function), that's null (?) and it was expecting an EOF(?)

Next token is token IDENTIFIER ( = (null))

After accepting 'b' identifier, it incorrectly identifies (something ? I do not understand which character) as an identifier, rather than picking up on the EQUALS, CONSTINT and LE tokens.

Edit: I've added a few more debugging info (line, column, block)

syntax error, unexpected IDENTIFIER, expecting $end Line: 3 Column: 0 Block: 0

With input like this:

SUB fib (n, ret)
low,high;
IF ( n == 0 OR n == 1)
ret = n;
high = call fib(n-1, high);
low = call fib(n-2, low)
ret = high + low;
RETURN ret

I get this error:

syntax error, unexpected IDENTIFIER, expecting $end Line: 3 Column: 0 Block: 0

which is obviously the same as the aforementioned one. For some reason, after a semicolon, it always expects a $end. I cannot figure out where this behaviour results from. From what I've understood, it reduces the stack to state 0, which is this:

State 0
    0 $accept: . program $end

...but the issue being I cannot understand WHY it would reduce to this, or how to fix this.

Any help for these three points is more than appreciated.

Many thanks in advance.

@g_elef: For some reason, you didn't mention the fact that your grammar has five shift/reduce conflicts and two reduce/reduce conflicts. Those may lead to the parser taking an unexpected action, and should be fixed before trying to debug further. On the positive side, you included your entire grammar so it was possible to run it through bison to get the notifications. So thanks for that. – rici May 11, 2021 at 15:24 One comment about your grammar, which is likely creating some of those conflicts: You seem to be translating A (sep A)* into asequence: A asequence_op; asequence_op: %empty | sep A asequence_op;. That's ugly (imho), leads to excessive stack usage, and is often involved in parsing conflicts. Better to not rely on empty productions and use left-recursion: asequence: A | asquence sep A. To the extent possible, avoid empty productions. – rici May 11, 2021 at 15:30 Other random comments: your semantic type includes a name tag, but your lexer never sets the value. Instead, it stores a pointer to a copy of yytext in the mysterious undeclared variable yycopy, which I suppose is in some other translation unit. You should instead store that pointer in yylval.name, so that the parser can see it. (And then figure out why you think you need an additional global, which is probably either a bug or a design flaw.) – rici May 11, 2021 at 15:35 And you use %option yylineno. so it should really not be necessary to count newline characters yourself in count. I'm also highly skeptical for the need for count; in particular, it's attempt to count brace nesting is doomed to failure because the { and } in char close = '}'; and /* Here is a { */ should not be counted. You can count block nesting in your parser if you really need it for something. Or you can count the actual tokens, if you insist on doing it in the lexer. – rici May 11, 2021 at 15:38

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.