结合flex和bison进行文件解析

问题描述 投票:0回答:1

所以我在 flex/bison 中有这个程序。

我的两个问题是:

1)我不知道如何让它适用于文件输入,因为我的大学练习需要它使用文件。

我尝试使用来自 g++ 编译器的 iostream 库,但我有很多错误(我当然在 cout 等中更改了 printfs)

2)我不能让它像浮点数一样工作,我使用 atof declare yytext as boolean 也仍然一无所获。

提前致谢。

flex.l:

%option noyywrap

%option yylineno



%{

    #include <stdlib.h>

    #include "bison.tab.h"

    #define YYDEBUG 1

%}





%%

create_table {return CREATE;}

[ ][a-z]+ {return MONO;}

([ ][a-z]+[ ][&])+ {return CREATELIST;}



create_record_data {return RECORD;}

([ ][a-z]+)([ ]#[0-9]{1,2}) {return RECORDNUMBER;}



[0-9]+(["."][0-9]+)? {yylval = atoi(yytext); return NUMBER;}

"+" {return PLUS;}

"-" {return MINUS;}

"*" {return MULT;}

"/" {return DIV;}

"\n" {printf("Line : %d \n",yylineno);  return END;}

"\t" {return TAB;}

"(" {return PARL;}

")" {return PARR;}



%%


野牛.y :

%{

    #include <stdlib.h>

    #include <stdio.h>

%}





%token CREATE RECORD 

%token MONO CREATELIST RECORDNUMBER

%token NUMBER

%token PLUS MINUS MULT DIV PARL PARR

%token END TAB



%left PARL PARR

%left MULT DIV

%left PLUS MINUS



%start Input

%%





Input:

 | Input Line

;



Line:

 END

 | Expr END { printf("Result: %d \n", $1); }

 | Create_table END { printf("Create Table ! \n"); }

 | Create_record_data END { printf("Record Data Created ! \n"); }

;



Expr:

 NUMBER {$$ = $1;}

 | Expr PLUS Expr {$$=$1+$3;}

 | Expr MINUS Expr {$$=$1-$3;}

 | Expr MULT Expr {$$=$1*$3;}

 | Expr DIV Expr {$$=$1/$3;} 

 | PARL Expr PARR {$$=$2;}

 ; 



Create_table:

 CREATE MONO { printf("Create Table Single! \n"); } 

 | CREATE CREATELIST { printf("Create Table List ! \n"); }

 ;



Create_record_data:

 RECORD RECORDNUMBER Expr { printf("Record Created \n"); }

 ;



%%



int yyerror(char *s) {

  printf("%s \n", s);

}



int main() {

  if (yyparse()==0)

     fprintf(stderr, "Successful parsing.\n");

  else

     fprintf(stderr, "error found.\n");

}
bison flex-lexer yacc
1个回答
1
投票

在您的 main 中,您可以打开文件或使用标准输入(这使测试更容易)。

如果你想有选择地接受一个输入文件名作为你的第一个参数,改变你的主要看起来像:

extern FILE* yyin;
int main(int argc,char **argv) {
  yyin = NULL;
  if (argc==2) yyin = fopen(argv[1],"r");
  if (!yyin) yyin = stdin;
  if (!yyparse()) {
    ...

关于“使用”代币的其他问题。

您可以使用 yytext 获取扫描器发现的触发令牌的文本,但您不能将其分配给令牌。你必须使用类型。

如果你想从扫描器中获取值(而不用担心语法中的 yytext,那么在你的 %token 部分上面,添加这个:

%union
{
  int intval;
  float floatval;
}
...
%token <intval> NUMBER

然后,在您的 flex.l 中,您可以根据令牌的类型分配给联合:

[0-9]+(["."][0-9]+)? {yylval.intval = atoi(yytext); return NUMBER;}

然后,在您的语法中,您可以使用 $1 或 $3 / 等位置变量访问(在本例中为 int 值)并获取该 atoi 值。

最后一件事,你是否为 Expr 声明了语法,但它没有类型。

在顶部,在你的标记下面,你必须给非终端一个类型:

%type <intval> Expr // if an Expr is just a number

如果你想在非终端中存储更多信息,那么你应该制作/使用结构,在联合中声明它的类型,然后你可以将 NT 的类型设置为你的结构。

分配 $$(产生式规则的左侧)的唯一方法是让 $$ 具有类型。通过以上,给 Expr 一个 int 和数字 ints ...

Expr : Expr PLUS Expr { $$ = $1 + $3; }

应该工作

© www.soinside.com 2019 - 2024. All rights reserved.