C++ 如何构建递归下降解析器
我一直在为一个简单的计算器开发递归下降解析器。当某个东西被声明时,它要么被声明为int,要么被声明为float。目前,我正在将字符串保存到两个不同的向量中,一个用于int,另一个用于float。此时,我不关心关联的数字是什么,我只关心在使用字符串之前声明它 我的问题是,如果在诸如float+int这样的操作中使用int和float,我必须能够输出警告消息 所以如果表达式是term+表达式或者term表达式或者term。在递归下降中,我怎么可能检查int是否正在浮点操作中使用。对不起,如果解释不清楚的话。我觉得有点难以解释。我已经添加了一些代码,如果必要的话,我只是不想用代码淹没这个问题 编辑: 还有一堆代码丢失,我想我只是抓住了重要的部分,但如果需要,我可以上传整个东西。我看到有些人不明白主要问题是什么。其中一个要求是“当整数和浮点值在+、-、*和/中混合时,整数将转换为浮点。打印一条消息,指示行号以及需要进行转换。”此时程序从文件中读取。如果你说“int x;”,程序当前将把x保存在int向量中,那么当你说x=5;它将确认x已声明,分配将通过。我的问题是如果你说int x;浮动y;intz;x=5;y=7.5;z=x+y;我怎样才能检查它,因为目前我的程序只保存变量的类型,而不保存值。本质上,我想知道是否有可能像扫描一个字符串一样扫描完成的解析,或者使用int和float从一个操作中找出其他方法 lex扫描器是用flex创建的C++ 如何构建递归下降解析器,c++,parsing,type-inference,C++,Parsing,Type Inference,我一直在为一个简单的计算器开发递归下降解析器。当某个东西被声明时,它要么被声明为int,要么被声明为float。目前,我正在将字符串保存到两个不同的向量中,一个用于int,另一个用于float。此时,我不关心关联的数字是什么,我只关心在使用字符串之前声明它 我的问题是,如果在诸如float+int这样的操作中使用int和float,我必须能够输出警告消息 所以如果表达式是term+表达式或者term表达式或者term。在递归下降中,我怎么可能检查int是否正在浮点操作中使用。对不起,如果解释不清
class Token {
Tokentype type;
string value;
int linenum;
public:
Token(Tokentype t, string v="") {
type = t;
value = v;
}
Tokentype getType() { return type; }
string getValue() { return value; }
int getLinenum() { return linenum; }
};
vector<string> int_list;
vector<string> float_list;
class PTree {
PTreeNodetype type;
PTree *left;
PTree *right;
public:
PTree(PTreeNodetype t, PTree *l=0, PTree *r=0) {
type = t;
left = l;
right = r;
}
PTreeNodetype getType(){ return type;}
};
// expr ::= term PLUS expr | term MINUS expr | term
PTree *
Expr() {
PTree *term = Term();
Token *t;
if (!term)
return 0;
t = getToken();
if (t == NULL){
delete t;
return 0;
}
if(t->getType() != T_SC)
{
if (t->getType() == T_RPAREN){
pushbacktoken(t);
return new PTree(EXPR, term);
}
if (t->getType() != T_PLUS && t->getType() != T_MINUS)
{
cout << t->getLinenum() << ":" << "Error: expected + or -" << endl;
pushbacktoken(t);
delete t;
return 0;
}
delete t;
PTree *expr = Expr();
if (!expr)
return 0;
return new PTree(EXPR, term, expr);
}
pushbacktoken(t);
return new PTree(EXPR, term);
}
类令牌{
标记类型;
字符串值;
int-linenum;
公众:
令牌(令牌类型t,字符串v=“”){
类型=t;
值=v;
}
Tokentype getType(){return type;}
字符串getValue(){返回值;}
int getLinenum(){return linenum;}
};
向量整数表;
向量浮点数表;
类树{
PTreeNodetype型;
p树*左;
PTree*对;
公众:
PTree(PTreeNodetype t,PTree*l=0,PTree*r=0){
类型=t;
左=l;
右=r;
}
PTreeNodetype getType(){return type;}
};
//expr::=术语加上expr |术语减去expr |术语
树*
Expr(){
PTree*term=term();
令牌*t;
如果(!术语)
返回0;
t=getToken();
如果(t==NULL){
删除t;
返回0;
}
如果(t->getType()!=t_SC)
{
如果(t->getType()==t_rpare){
pushbacktoken(t);
返回新的PTree(EXPR,term);
}
如果(t->getType()!=t\u加号和&t->getType()!=t\u减号)
{
cout getLinenum()我看到的两个选项,取决于您正在做什么
首先。在构建解析树时,不要担心它。稍后,在遍历树时,您可以轻松地检查它并抛出错误
第二个。对int
和float
使用不同的规则。因此,您将有一个添加两个int的规则和一个添加两个float的规则。这也意味着您将不会有一个混合int和float的数字
规则,我猜您是这样做的
我绝对推荐第一种方法。我看到两种选择,这取决于你在做什么
首先。在构建解析树时,不要担心它。稍后,在遍历树时,您可以轻松地检查它并抛出错误
第二个。对int
和float
使用不同的规则。因此,您将有一个添加两个int的规则和一个添加两个float的规则。这也意味着您将不会有一个混合int和float的数字
规则,我猜您是这样做的
我绝对推荐第一种方法。传统上,计算器不会“声明”事物,因此不清楚您的计算器在解析表达式时知道什么
如果我假设您在解析表达式“I*r”之前“声明I int,r real”,您似乎有几个问题:
a) 解析时如何知道i和r是否已声明?技术上的答案是,在解析过程中,您不必知道;您可以解析、建立树,然后再进行此类检查。在实际层面上,人们通常在解析过程中编织符号查找(随着您的语言变得越来越大,这会变得越来越混乱,因此不建议将其用于计算器以外的其他用途[您会发现,大多数C编译器都会这样做,这会增加它们的混乱程度])。答案很简单:保留一个已定义符号字符串的列表,当您遇到标识符时,查看其是否在列表中
b) 如何知道“i”或“r”的类型?很简单。与符号字符串关联,声明的类型,例如,关联的声明集通常称为符号表
c) 如何知道操作是否在相同(“右侧”)类型的值上运行?这里需要与每个操作数及其“类型”关联。常量具有明显的类型;1.0为实数,1为整数。“i”为整数,您的解析器知道它,因为它查找了类型(如上);与“r”类似。然后,每个表达式项必须检查其操作数的兼容性。可能不明显的是,每个表达式必须计算其结果类型,例如,3*4.0是实数,而不是整数。因此,与解析机制并行,您需要传播一个类型。计算器传统上不会“声明”因此,不清楚您的计算器在解析表达式时知道什么
如果我假设您在解析表达式“I*r”之前“声明I int,r real”,您似乎有几个问题:
a) 在解析时,您如何知道我和