yylineno in error recovery


How can i print the number of line where there is a syntax error using yylineno ?

I did the following thing but i constantly get "Number 1 : syntax error"

void yyerror( const char *msg )
  printf("Number %d: %s\n", yylineno, msg);

Thanks in advance for any help !
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

In my grammars I declare a variable called line and I increment it in token rules

Below is an example, my language supports // comments so I increment it in that rule as well.
If you have multiline comments (like C) you'll need to do the same in that rule.

int line = 0;
\n              line++;
\/\/.*\n        line++;    /* COMMENT */

Open in new window


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
unknown_Author Commented:
I still have the same problem

my input is :
int x ;


But i get :

rule 15
Unknown character [E]
Line 0: syntax error

#include "y.tab.h"
int line = 0;
letter          [a-zA-Z_]
letter_digit     [a-zA-Z0-9_]	
comment 	"/*"."*/"
digit 		[0-9]
variable	[a-z_]({letter_digit})*
integer		{digit}+
float		{digit}+(\.{digit}+)?(e[+ -]?{digit}+)?
string           \"[^"\n]*["\n]
whitespace	[ \t\n]
ws              {whitespace}+
"+"			{ return('+'); }
"-"			{ return('-'); }
"("			{ return('('); }
")"			{ return(')'); }
","			{ return(','); }
";"			{ return(SEMICOLON); }
"="			{ return('='); } 
"*"			{ return('*'); }
"/"			{ return('/'); }
"%"			{ return('%'); }
"||"		        { return(OR2); }
"&&"		        { return(AND2); }
"|"			{ return(OR); }
"&"			{ return(AND); }
"if"                    { return(IF);       }
"else"                  { return(ELSE);     }
"do"                    { return(DO);       }
"int"                   { return(INT);      }
"return"                { return(RETURN);   }
"void"                  { return(VOID);     }
"float"                 { return(FLOAT);    }
"while"                 { return(WHILE);   }
{string} { 
{variable}* { 
{digit}+ {  
  yylval.ival = atoi(yytext);
{float}+ {
  yylval.ival = atoi(yytext);
   return (FLOAT);
{ws} {};
[ ] {} ;
\n              line++;
\/\/.*\n        line++;    /* COMMENT */
[ \t\n\r]            /* skip whitespace */
.                    { printf("Unknown character [%c]\n",yytext[0]);
		       return UNKNOWN;    }
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define YYDEBUG 1
extern int  yyparse();
 extern int yylex();
 extern int line  ;
extern FILE *yyin;	
int yywrap()
    return 1;
void yyerror(const char *s)
    printf("\n%*s\n%*s\n", s);
// void yyerror (char *s) {fprintf (stderr, "%s\n", s);}
/*void yyerror(char *s) 
  fprintf(stderr,"%s\n",s,"%d", yylineno); 
void yyerror( const char *msg )
  printf("Line %d: %s\n",line, msg); 
%start goal
%union {
	int ival;
	char * sval;
%token <sval> IDENTIFIER
%token <sval> VARIABLE
%token <ival> INTEGER
 /*%token <ival> FLOAT*/
%token <sval> STRING
%token <sval> LITERAL
%token <sval> UNKNOWN 
%token <sval> PLUS
%token <sval> MINUS
%token <sval> TIMES
%token <sval> SLASH
%token <sval> LPAREN
%token <sval> RPAREN
%token <sval> SEMICOLON
%token <sval> COMMA
%token <sval> EQL
%token <sval> OR 
%token <sval> OR2
%token <sval> AND
%token <sval> AND2
/* keywords */
%token <sval> IF
%token <sval> ELSE
%token <sval> DO
%token <sval> INT
%token <sval> RETURN
%token <sval> VOID
%token <sval> FLOAT
%token <sval> WHILE
%type <sval> goal
%type <ival> expression
%type <ival> term 
%type <ival> factor 
%type <sval> ifstatement
%type <sval> whilestatement
%type <sval> dostatement
%type <sval> variable_list
%type <sval> variable 
goal			: statement_list;
statement_list: { /*empty*/ }
                | statement_list statement
statement : declaration_statement
          | ifstatement 
          | whilestatement
          | variable '=' expression SEMICOLON 
          | dostatement 
declaration_statement : INT variable_list SEMICOLON {printf("INT_VARIABLE\n");}
                      | FLOAT variable_list SEMICOLON {printf("FLOAT_VARIABLE\n");}
expression		:	term '+' term {printf("RULE 1\n");} {$$ = $1 + $3;}
|	term '-' term {printf("rule 2\n");} {$$ = $1 - $3;}
|	term {printf("rule 3\n");}  {$$ = $1;}   ;
term			:	factor '*' factor  {printf("rule 4\n");} {$$ = $1 * $3;}
|	factor '/' factor  {printf("rule 5\n");} {$$ = $1 / $3;} 
|	factor {printf("rule 6\n");}  {$$ = $1;}  ;
factor			:	variable {printf("rule 7\n");} 
|	INTEGER {printf("rule 8\n");} 
|	FLOAT {printf("rule 9\n");} 
|	STRING {printf("rule 10\n");}
|	'(' expression ')' {printf("rule 11\n");};
ifstatement		:	IF '(' expression ')' goal ELSE goal SEMICOLON {printf("rule: IF_ELSE_STATEMENT\n");}
|	IF '(' expression ')' goal {printf("rule: IF_STATEMENT\n");};
whilestatement	:	WHILE '(' expression ')' goal {printf("rule: WHILE_STATEMENT\n");};	
dostatement : DO expression WHILE '(' expression ')'   {printf("rule DO_STATEMENT\n");} ;
variable : VARIABLE {printf("rule var2\n");} {$$= $1; };
variable_list : VARIABLE {printf("rule 15\n");}  {$$= $1; }
|  	variable ',' variable_list {printf("rule 16\n");}  ;
#include "lex.yy.c"
main(int argc,char *argv[])
    printf("Please specify the input file\n");
 FILE *fp=fopen(argv[1],"r");
     printf("couldn't open file for reading\n");
 do {
 }while (!feof(yyin));

Open in new window

You now have multiple lexer rules for the same thing, whitespace and newlines.

ws -> whitespace
as well as the ones I just gave you both map to the same thing.


[ \t\n\r]            /* skip whitespace */

Review your lexer rules, you don't want a lot of the same thing, for one it is confusing, plus it will ignore the redundant rules. Combine down to unique rules.

You said your input  is:

my input is :
int x ;


How in your lexer grammar are you handling "Error". It looks like your lexer rule for "variable" does not allow a variable to start with an uppercase letter. So when it sees "Error", which is in your sample, it handles it with the default rule, which prints "Unknown character"
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

unknown_Author Commented:
How can i do the same rule for single line comment ?
I mean about the // comment is \/\/.*\n        line++;  

I tried something similar for /* comment */  but is not valid

\/* .* */\

@unknown_: You have 5 open C questions all on different areas of your compiler, but some are overlapping a bit. Can I suggest you wrap several of them up so we can narrow down. Too much overlap becomes confusing for us to track, and can also be suspect to moderator's getting involved.

Lets keep the questions to specific topics, and accomplish 1 or 2 things at a time? I am less willing to work with you on 5 threads at once.
unknown_Author Commented:
Thanks !

Can you please have a look to that question :

Thanks !

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.