【问题标题】:Translating a grammar file in a hand written parser在手写解析器中翻译语法文件
【发布时间】:2016-05-29 13:25:56
【问题描述】:

出于教育目的,我一直在尝试编写自己的编译器,但遇到了一个问题。我已经采用了递归下降方法,并具有一些关于 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 函数。

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

谁能指出我正确的方向?

【问题讨论】:

标签: c++ parsing bison yacc


【解决方案1】:

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

A → α |一个β

然后你的递归下降程序就变成了

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

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

这与在 LL 语法中消除左递归的过程相同——您实际上是用

替换了上面的规则

A → α A'
A'→ ε | βA'

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

使用您的语法并使用您上面的代码使用的接受/预期技术,您会得到类似的结果:

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

               ⋮

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

【讨论】:

    【解决方案2】:

    注意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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 2013-04-23
      • 2016-05-24
      • 1970-01-01
      相关资源
      最近更新 更多