FLEX/YACC多行输入的第一行结束

huangapple go评论46阅读模式
英文:

FLEX/YACC End of the first line in multiline input

问题

再次我来这里寻求建议,提前感谢。
我有一个简单的解析器来解析字符并将数字相加。
当我只有一行时,可以,但它应该从文件中读取,其中有多行。
它到了推导的末尾,当它应该取STMTS + '\n'时,它说'无效字符'。它看不到\n。

不翻译

//词法分析器

//语法分析器

现在一切都看起来不错,除了它不会将STMTS与'\n'结合起来。
在这种情况下我做错了什么呢?

  • EOL是';' - 它应该是"等式"的结尾
  • 行示例:(+5+-5)*8--10;

堆栈现在为0 8 17
通过规则2 (第28行) 减少堆栈:
$1 = nterm STMT ()
$2 = token EOL ()
** -> $$ = nterm STMTS ()
进入状态7
堆栈现在为0 7
读取一个标记
下一个标记是标记"无效标记" ()
错误:弹出 nterm STMTS ()
堆栈现在为0
清理:丢弃前瞻标记"无效标记" ()
堆栈现在为0
ENDdddd1111: 5.000000
ENDddd333: 10.000000
语法错误:语法错误,行号:1

编辑:好的,我有点进展了:
在parser.y中添加'\n'作为结束符。词法分析器保持不变。现在它在bash中手动插入的字符串中工作 - 第一个字符串 - 在第二个STMTS中调用动作,第二个字符串 - 调用第一个STMTS...看起来不错。但是当我尝试解析来自文件的输入时,当应该是EOF时,我再次收到无效字符:


//从文件中
END of deriv :ONE statement - now EOF and next line
-> $$ = nterm STMTS ()
进入状态7
堆栈现在为0 7
读取一个标记
下一个标记是标记"无效标记" ()   //应该是 '\n'
语法错误
错误:弹出 nterm STMTS ()
堆栈现在为0
清理:丢弃前瞻标记"无效标记" ()
堆栈现在为0

//手动插入 - 相同的字符串
END of deriv :ONE statement - now EOF and next line
-> $$ = nterm STMTS ()
进入状态7
堆栈现在为0 7
读取一个标记
下一个标记是标记'\n' ()
移动标记'\n' ()
进入状态16
堆栈现在为0 7 16
通过规则3 (第26行) 减少堆栈:
   $1 = nterm STMTS ()
   $2 = token'\n' ()
-> $$ = nterm STMTS ()
进入状态7
堆栈现在为0 7
读取一个标记


//输入文件的内容:
(+12-9);
sqrt(16);

如果我尝试手动输入这些,它运行正常。

英文:

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?

  • EOL is ';' - it should be the end of "equation"
  • Line example: (+5+-5)*8--10;
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.

答案1

得分: 0

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] ;

英文:

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

huangapple
  • 本文由 发表于 2023年5月30日 04:24:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360151.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定