我已经构建了一个基于语法的递归式解析器。目前我的解析器仅告知语法是否接受令牌的输入序列。如果语法接受输入和抽象语法树,我想返回。我不知道该怎么做。
到目前为止,我所拥有的是与语法中的每个生产规则相对应的函数。我已经转换了语法,因此终端始终是每个生产规则的第一个元素。下面是我试图为其构建语法树的语法的子集。
program -> VAR = exp
exp -> NUM term
exp -> LEFTPAR exp RIGHTPAR
term -> MUL NUM term
term -> DIV NUM term
term -> . (empty)
规则的功能示例如下:
public Pair<bool, Token> exp(Token tok)
{
if (tok.type == NUM)
{
return term(tok.next);
}
if (tok.type = LEFTPAR)
{
Pair<bool, Token> temp = exp(tok.next);
if (temp.left && temp.right.type == RIGHTPAR)
return new Pair<bool, Token>(true,temp.right.next);
return new Pair<bool, Token>(false,null);
}
}
将这样的函数转换为语法树构建器的策略是什么?我试图将树节点作为输入传递给所有函数,但是当存在具有多个非终端的规则时,它会变得更加混乱。似乎更容易构建一个解析树,然后将其转换为AST后缀。任何帮助表示赞赏!
答案 0 :(得分:1)
这是解析函数参数的示例。这是在C中,但是这个想法转移即你在解析令牌流时构建AST。
此函数解析foo : double
static void parse_arg(parser_obj *obj, AstFunc *func) {
Token * tok;
TokenId tid = peek(obj);
if(tid == T_PAREN_R) {
return;
}
EXPECT(T_ID);
tok = t(obj);
char *arg_name = tok_value(tok);
EXPECT_EAT(T_COLON);
tok = t(obj);
ctype arg_type = tokid_to_type(tok_id(tok));
func->ops->new_arg(func, arg_name, arg_type);
}
func
对象实际上是AST中的一个节点,在这种情况下,当我们添加一个新参数时它会被添加到一个列表或一个树或你想要使用的任何数据结构中的多个参数一旦你完成了解析。
在以下行中,我们将一个arg添加到对象func
。
func->ops->new_arg(func, arg_name, arg_type);
func
的实际内部结构,即正在构建的树的形状或其实现方式对于解析器是不可见的。