在手写语法分析器中翻译语法文件

Translating a grammar file in a hand written parser

本文关键字:语法 翻译 文件 分析器 语法分析      更新时间:2023-10-16

我一直在尝试为教育目的编写自己的编译器,但遇到了一个问题。我采用了递归下降的方法,之前我对lex和yacc/bison有一些了解。

到目前为止,我只是尝试处理解析方面,而不考虑AST的生成或代码生成。

我正在尝试为这个特定的语法文件部分编写表达式解析

primary_expression
: IDENTIFIER
| CONSTANT
| STRING_LITERAL
| '(' expression ')'
;
postfix_expression
: primary_expression
| postfix_expression '[' expression ']'
| postfix_expression '(' ')'
| postfix_expression '(' argument_expression_list ')'
| postfix_expression '.' IDENTIFIER
| postfix_expression PTR_OP IDENTIFIER
| postfix_expression INC_OP
| postfix_expression DEC_OP
;

到目前为止,我有这个代码

void Parser::primaryExpression()
{
if (accept(Token::eIdentifier))
{
}
else if (accept(Token::eIntNumber))
{
}
else if (accept('('))
{
expression();
expect(')');
}
}
void Parser::postfixExpression()
{
}

我在处理postfix_expression的递归性时遇到了一些问题,我不知道如何继续使用postfixExpression函数。

我的印象是,对于递归下降语法分析器,我可能应该以不同的方式排列语法。

有人能给我指正确的方向吗?

左递归在LL(递归下降)解析器中很难处理——您需要识别at并将其更改为循环,而不是递归调用。一般来说,您希望将左递归重构为

A→α|Aβ

然后你的回避下降程序变成

parseA() {
parseAlpha();
while (lookaheadMatchesBeta())
parseBeta();
}

请注意,这需要足够的前瞻性来区分FIRST(β)和FOLLOW(A),以便找到所有可以匹配β

这与LL语法中消除左递归的过程相同——您正在用有效地替换上面的规则

A→&阿尔法A'
A'→&ε;|&β;

然后用循环替换CCD_ 3中的尾部递归调用并将其内联到CCD_。

使用语法并使用上面代码使用的接受/期望技术,你会得到这样的东西:

void Parser::postfixExpression() {
primaryExpression();
while (true) {
if (accept('[')) {
expression();
expect(']');
} else if (accept('(')) {
if (accept(')')) {
} else {
argumentExpressionList();
expect(')'); }
} else if (accept('.')) {

 nbsp nbsp nbsp nbsp nbsp nbsp nbsp #8942;

} else if (accept(Token::DEC_OP)) {
} else {
break;
}
}
}

请注意,postfix_expression总是首先解析primary_expression,因此业务的第一个顺序是primaryExpression()

然后,如果下一个字符是其余七个规则中遵循递归postfix_expression的任何字符,则您正在解析postfix_expression。这会给你带来另一个posfix_expression,所以你再重复一遍。

我不会为您编写C++代码,但使用伪代码:

postfixExpression()
{
primaryExpression();
while (next character is any of the characters that follow
postfix_expression in the remaining seven rules)
{
parse_the_appropriate_rule();
}
}