所以我在 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");
}
在您的 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; }
应该工作