Once again I go here for advice, thanks in advance. I have simple parser to parse the chars and summ the numbers together. When I have just one line, it is ok but it should read from file, where multiple lines are. It goues to the end of derivation and when it should take STMTS + '\n' it says 'invalid character'. It does not see the \n.
//lex
%{
#include "kfloat.tab.h"
%}
%option nounput
%option noinput
%%
[ \t] ;
[0-9]+ { yylval.d=atof(yytext); return NUMBER; }
"sqrt" {return iSQRT; }
"log" {return iLOG; }
"+" { return OPLUS; }
"-" { return OMINUS; }
"*" { return OMULT; }
"/" { return ODIV; }
"(" { return LPAR; }
")" { return RPAR; }
"\n" { yylineno++; return yytext[0]; }
";" { return EOL;}
. return yytext[0];
%%
//yacc
%{
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define YYDEBUG 1
void yyerror(char *);
int yylex(void);
extern int yylineno;
%}
%union { double d;}
%token <d> NUMBER
%token EOL
%type <d> EXP STMT
%left OPLUS OMINUS
%left OMULT ODIV
%left iLOG iSQRT
%left LPAR RPAR
%%
STMTS : STMTS STMT EOL {printf("END of deriv :2 and MORE statements- now EOF and next line\n");} //edit
| STMT EOL {printf("END of deriv :ONE statement - now EOF and next line\n");} //edit
| STMTS '\n' //edit
;
STMT : EXP
|
;
EXP : EXP OPLUS EXP {$$=$1+$3; printf("ENDdddd1111: %f\n",$1);}
| EXP OMINUS EXP {$$=$1-$3;}
| EXP OMULT EXP {$$=$1*$3;}
| EXP ODIV EXP {if ($3==0) {yyerror("Zatim nelze delit nulou"); exit(0);} else {$$=$1/$3;}}
| LPAR EXP RPAR { ;}
| iSQRT EXP {$$=sqrt($2);}
| iLOG EXP {$$=log10($2);}
| OPLUS EXP {$$= $2;}
| OMINUS EXP {$$= -$2;}
| NUMBER {$$= $1;}
;
%%
/* lineno do erroru printf*/
int main(void)
{
#if YYDEBUG
yydebug = 1;
#endif
if(!yyparse ())
printf("OK\n");
return 0;
}
void yyerror (char *s)
{
printf("Syntakticka chyba: %s na radku: %i\n",s,yylineno);
}
And when executed, in the end everything looks fine, except it wont combine STMTS with '\n'. What am I doing wrong in this case please?
Stack now 0 8 17
Reducing stack by rule 2 (line 28):
$1 = nterm STMT ()
$2 = token EOL ()
**-> $$ = nterm STMTS ()
Entering state 7
Stack now 0 7
Reading a token
Next token is token "invalid token" ()**
Error: popping nterm STMTS ()
Stack now 0
Cleanup: discarding lookahead token "invalid token" ()
Stack now 0
ENDdddd1111: 5.000000
ENDddd333: 10.000000
Syntakticka chyba: syntax error na radku: 1
EDIT: OK, I am a bit further: Added '\n' as endline into a parser.y. Lex is the same. Now it works for manually inserted strings in bash - first string - the action in second STMTS is called, second string - first STMTS is called.... seems good. But when I try to parse input from file, I get invalid charcter again when it should be EOF:
//from file
END of deriv :ONE statement - now EOF and next line
-> $$ = nterm STMTS ()
Entering state 7
Stack now 0 7
Reading a token
Next token is token "invalid token" () //should be '\n'
Syntaktickâ–’ chyba
Error: popping nterm STMTS ()
Stack now 0
Cleanup: discarding lookahead token "invalid token" ()
Stack now 0
// manual insert - same string
END of deriv :ONE statement - now EOF and next line
-> $$ = nterm STMTS ()
Entering state 7
Stack now 0 7
Reading a token
Next token is token '\n' ()
Shifting token '\n' ()
Entering state 16
Stack now 0 7 16
Reducing stack by rule 3 (line 26):
$1 = nterm STMTS ()
$2 = token '\n' ()
-> $$ = nterm STMTS ()
Entering state 7
Stack now 0 7
Reading a token
// Content of input file:
(+12-9);
sqrt(16);
If I try to input those manually, it works fine.
Your lexer returns the token '\n'
for newline, but the parser is not expecting it. If you want to have a newline end a STMT, you need a rule that expects that -- something like STMTS : STMT '\n'
.
Alternately, change your lexer to ignore newlines. You probably want to ignore other whitespace as well, so something like
[ \t\r\n] ;
in the lex code