【发布时间】:2020-06-11 05:07:01
【问题描述】:
暑假我在学校学习了 flex 和 bison,现在我想更深入地了解一下。我无法理解 Bison 3.0.2 的文档。也许你们中的一些人可以帮助我。我想解析一个表示方程的字符串,同时填写一个数据结构,其中包含有关已解析内容的信息。例如,假设我有 (ax+b)^2。我希望解析器生成一个包含字符串和整数常量的结构,如下所示。
( BEGINGROUP
a VARIABLE
x VARIABLE
+ ADDITION
b VARIABLE
) ENDGROUP
我已经使用 flex 创建了一个语言规范,并且我已经使用 bison 创建了一个语法。所需要的只是让两者将信息放入结构中。我有一些代码以我想要的方式工作,但我不禁认为我错过了一些东西。在 Bison 文档示例中,我看到他们使用 $$ 或 $1 来检查语义值?当我打印语义值时,我总是得到零。不管怎样,我的代码贴在下面。
数学.l
%{
#include "equation.h"
Equation* equ;
void setEquation(Equation* equation) {
equ = equation;
}
%}
/* Definitions */
space [ \t]
digit [0-9]
letter [a-zA-Z]
number ({digit}+|{digit}+"."{digit}+|"."{digit}+|{digit}+".")
variable {letter}
/* actions */
%%
{space} ;
{number} equ->addElement(yytext, Equation::number); return(1);
{variable} equ->addElement(yytext, Equation::variable); return(2);
"+" equ->addElement(yytext, Equation::addition); return(10); /* Basic operators */
"-" return(11);
"*" return(12);
"/" return(13);
"^" return(14);
"log" return(15);
"sin" return(20); /* Trigonometric Functions */
"cos" return(21);
"tan" return(22);
"csc" return(23);
"sec" return(24);
"cot" return(25);
"arcsin" return(26);
"arccos" return(27);
"arctan" return(28);
"(" equ->addElement(yytext, Equation::begGroup); return(30); /* Grouping Operators */
")" equ->addElement(yytext, Equation::endGroup); return(31);
"[" return(32);
"]" return(33);
"," return(34);
. fprintf(stderr, "Error on character %s\n", yytext);
数学.y
/*
* Implement grammer for equations
*/
%{
#include "lex.yy.c"
#include "equation.h"
#include <iostream>
int yylex(void);
int yyerror(const char *msg);
void output(const char* where) {
std::cout << where << ": " << yytext << std::endl;
}
%}
%token e_num 1
%token e_var 2
%token e_plus 10
%token e_minus 11
%token e_mult 12
%token e_div 13
%token e_pow 14
%token e_log 15
%token e_sin 20
%token e_cos 21
%token e_tan 22
%token e_csc 23
%token e_sec 24
%token e_cot 25
%token e_asin 26
%token e_acos 27
%token e_atan 28
%token lparen 30
%token rparen 31
%token slparen 32
%token srparen 33
%token comma 34
%start Expression
%%
Expression : Term MoreTerms
| e_minus Term MoreTerms
;
MoreTerms : /* add a term */
e_plus Term MoreTerms
| /* subtract a term */
e_minus Term MoreTerms
| /* add a negetive term */
e_plus e_minus Term MoreTerms /* Add a negetive term */
| /* minus a negetive term */
e_minus e_minus Term MoreTerms /* Subtract a negetive term */
| /* no extra terms */
;
Term : Factor MoreFactors {equ->addElement("*", Equation::multiplication)};
;
MoreFactors: e_mult Factor MoreFactors
| e_div Factor MoreFactors
| Factor MoreFactors
|
;
Factor : e_num { std::cout << $1 << std::endl; } //returns zero no matter where I put this
| e_var
| Group
| Function
;
BeginGroup : lparen | slparen;
EndGroup : rparen | srparen;
Group : BeginGroup Expression EndGroup
;
Function : TrigFuncs
| PowerFunc
;
TrigFuncs : e_sin lparen Expression rparen
| e_cos lparen Expression rparen
| e_tan lparen Expression rparen
| e_csc lparen Expression rparen
| e_sec lparen Expression rparen
| e_cot lparen Expression rparen
| e_asin lparen Expression rparen
| e_acos lparen Expression rparen
| e_atan lparen Expression rparen
;
PowerFunc : e_num e_pow Factor
| e_var e_pow Factor
| Group e_pow Factor
| TrigFuncs e_pow Factor
;
我认为我在做什么很清楚。如您所见,扫描器将 yytext 与其代码一起存储到方程类中,但有时解析器必须将信息添加到方程类中,这就是事情变得忙碌的地方。一方面,试图在语句之前或中间添加代码会导致大量的移位/减少冲突。其次,将代码放在语句末尾的效果是乱序记录。查看术语的规则。如果我输入“ax”,这隐含的意思是“a”乘以“x”或“a*x”。我希望解析器将乘法添加到我的结构中,但是解析器不按顺序执行此操作。那么有没有更好的方法来实现我的目标?
【问题讨论】: