簡體   English   中英

將BNF語法規則轉換為實際的C ++函數/代碼

[英]Converting BNF grammar rules into actual C++ functions/code

我正在嘗試創建遞歸下降解析器。 到目前為止,我已經掌握了所有基礎知識,我只需要適當地實現一些函數即可執行語法。 我以為一切都正確,看起來Aop ,但是我猜我的AopExprTerm函數做錯了什么。 有時輸入流被切斷,無法識別事物。 我不知道如何。

是否有站點或源代碼示例更深入地解釋了這一點? 我所看到的所有內容都是非常通用的,這很好,但是我堅持執行。

注意:編輯於2016年4月17日:對於我的程序,我的功能還算不錯,結構也很合理。 我曾經遇到過但沒有意識到的問題是,在某些情況下,當我調用getToken時,我“吞噬”了輸入流中的字符。 有時候,這很好,而其他時候則不是,並且需要重置輸入流。 因此,在需要逐個字符地放回字符串的情況下,我僅添加一個小循環。 例如:

if(t.getType() !=Token::EQOP)
    {
        //cout<<"You know it" << endl;
        int size = t.getLexeme().size();


        while(size>0)
        {
        br->putback(t.getLexeme().at(size-1));
        size--;
        }

        return ex;
    }

話雖這么說,我幾乎能夠相應地編輯程序,並且一旦看到吃光了字符,一切都將完成。

這是語法:

  Program::= StmtList
  StmtList::= Stmt | StmtList
  Stmt::= PRINTKW Aop SC | INTKW VAR SC | STRKW VAR SC | Aop SC
  Expr::= Expr PLUSOP Term | Expr MINUSOP Term | Term
  Term::= Term STAROP Primary | Primary
  Primary::= SCONST | ICONST | VAR | LPAREN Aop RPAREN

這是具有所有功能的主程序: http : //pastebin.com/qMB8h8vE

我似乎最困擾的功能是AssignmentOperator(Aop)Expression(Expr)Term 我會在這里列出。

ParseTree* Aop(istream *br)
{
    ParseTree * element = Expr(br);
    if(element!=0)
    {
        if(element->isVariable())
        {
            Token t= getToken(br);

            if(t==Token::EQOP)
            {                   
                cout<<"No" << endl;
                ParseTree * rhs = Aop(br);
                if(rhs==0)
                    return 0;
                else
                {
                    return new AssignOp(element, rhs);
                }
            }
            else
            {
                return element;
            }
        }
    }

    return 0;
}

ParseTree* Expr(istream *br)
{
    ParseTree * element = Term(br);
    if(element!=0)
    {
        Token t=getToken(br);
        if(t==Token::MINUSOP || t==Token::PLUSOP)
        {
            if(t==Token::PLUSOP)
            {
                ParseTree* rhs = Expr(br);
                if(rhs==0)
                    return 0;
                else
                {
                    return new AddOp(element, rhs);
                }
            }

            if(t==Token::MINUSOP)
            {
                ParseTree* rhs = Expr(br);
                if(rhs==0)
                    return 0;
                else
                {
                    return new SubtractOp(element, rhs); //or switch the inputs idk
                }
            }
        }
        else
        {
            return element;
        }
    }

    return 0;
}

ParseTree* Term(istream *br)
{
    ParseTree *element = Primary(br);

    if(element!=0)
    {
        Token t=getToken(br);
        if(t==Token::STAROP)
        {
            ParseTree* rhs =Term(br);
            if(rhs==0)
                return 0;
            else
            {
                return new MultiplyOp(element, rhs);
            }
        }
        else
        {
            return element;
        }
    }

    return 0;
}

為了編寫可恢復的下降解析器,您需要將語法轉換為LL形式,擺脫左遞歸 對於規則

Term::= Term STAROP Primary | Primary

你會得到類似的東西:

Term ::= Primary Term'
Term' ::= epsilon | STAROP Primary Term'

然后變成一個類似的功能:

ParseTree *Term(istream *br) {
    ParseTree *element = Primary(br);
    while (element && peekToken(br) == Token::STAROP) {
        Token t = getToken(br);
        ParseTree *rhs = Primary(br);
        if (!rhs) return 0;
        element = new MulOp(element, rhs); }
    return element;
}

請注意,您將需要一個peekToken函數來向前看下一個令牌而不消耗它。 它也可以使用getToken + ungetToken做同樣的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM