Flex/Bison程序适配文件输入与浮点数解析问题求助
解决Flex/Bison程序的两个问题:文件输入与浮点数解析
一、实现文件输入功能
不用替换printf为cout,Flex/Bison默认生成C代码,直接用C标准库的文件操作即可实现从指定文件读取输入。修改bison.y的main函数,通过命令行参数接收输入文件名,并用Flex提供的全局文件指针yyin打开文件:
修改后的main函数代码:
int main(int argc, char *argv[]) { if (argc > 1) { yyin = fopen(argv[1], "r"); if (!yyin) { perror("Failed to open input file"); return 1; } } if (yyparse() == 0) fprintf(stderr, "Successful parsing.\n"); else fprintf(stderr, "error found.\n"); if (yyin != stdin) fclose(yyin); return 0; }
编译运行时,直接把输入文件名作为参数传入即可:
./your_program input.txt
二、实现浮点数解析
当前代码无法解析浮点数的原因有两个:一是用atoi只转换整数,二是yylval默认是int类型,无法存储浮点数。需要修改Bison的类型定义和Flex的转换逻辑:
步骤1:修改bison.y的类型定义
添加%union定义指定支持的数值类型,同时标记NUMBER和Expr的类型为浮点型:
%{ #include <stdlib.h> #include <stdio.h> %} // 添加类型联合体 %union { double num; } %token CREATE RECORD %token MONO CREATELIST RECORDNUMBER %token <num> NUMBER // 标记NUMBER携带double类型值 %token PLUS MINUS MULT DIV PARL PARR %token END TAB %left PARL PARR %left MULT DIV %left PLUS MINUS %type <num> Expr // 标记Expr返回double类型值 %start Input
步骤2:修改表达式计算和输出的格式
把所有整数相关的输出和计算改为浮点型:
Line: END | Expr END { printf("Result: %.2f \n", $1); } // 用%f输出浮点数 | 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;} ;
步骤3:修改flex.l的NUMBER转换逻辑
用atof替换atoi,并赋值给yylval.num:
[0-9]+(\.[0-9]+)? {yylval.num = atof(yytext); return NUMBER;}
注意:原正则里的[\".\"]是错误写法,直接写\.即可匹配小数点。
修改后的完整代码
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.num = atof(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;} %%
bison.y
%{ #include <stdlib.h> #include <stdio.h> %} %union { double num; } %token CREATE RECORD %token MONO CREATELIST RECORDNUMBER %token <num> NUMBER %token PLUS MINUS MULT DIV PARL PARR %token END TAB %left PARL PARR %left MULT DIV %left PLUS MINUS %type <num> Expr %start Input %% Input: | Input Line ; Line: END | Expr END { printf("Result: %.2f \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(int argc, char *argv[]) { if (argc > 1) { yyin = fopen(argv[1], "r"); if (!yyin) { perror("Failed to open input file"); return 1; } } if (yyparse() == 0) fprintf(stderr, "Successful parsing.\n"); else fprintf(stderr, "error found.\n"); if (yyin != stdin) fclose(yyin); return 0; }
内容的提问来源于stack exchange,提问作者Thanos Rom
相关产品推荐
相关产品推荐

