編譯原理PA1實(shí)驗(yàn)報(bào)告

余岳 2015011367

環(huán)境搭建

  • 我IDE用的intellij,作業(yè)所給的框架非常方便,可以直接運(yùn)行。

實(shí)驗(yàn)內(nèi)容

  • 添加三元操作符 a?b:c
    首先在Lexer.l中定義問號和冒號
"?"  { return operator(Parser.QMARK); }
":"  { return operator(Parser.COLON); }

然后在Parser.yStmt的部分加入一個(gè)新的選項(xiàng)

Expr QMARK Expr COLON Expr                    
{
      $$.expr = new Tree.Conditional($1.expr, $3.expr, $5.expr, $2.loc);
}

由于樣例中強(qiáng)制要求右結(jié)合,故添加token和右結(jié)合標(biāo)記,以及由于優(yōu)先級的較低,應(yīng)當(dāng)寫在and和or的上面

%token QMARK COLON
%right QMARK COLON
%left OR
%left AND

之后在tree.java里實(shí)現(xiàn)Conditional這個(gè)類

    public static class Conditional extends Expr {

        public Expr det;
        public Expr trueval;
        public Expr falseval;

        public Conditional(Expr det, Expr trueval, Expr falseval, Location loc) {
            super(CONDEXPR, loc);
            this.det = det;
            this.trueval = trueval;
            this.falseval = falseval;
        }

        private void ConditionalOperatorPrintTo(IndentPrintWriter pw, String op) {
            pw.println(op);
            pw.incIndent();
            det.printTo(pw);
            trueval.printTo(pw);
            falseval.printTo(pw);
            pw.decIndent();
        }

        @Override
        public void accept(Visitor visitor) {
            visitor.visitConditional(this);
        }

        @Override
        public void printTo(IndentPrintWriter pw) {
            ConditionalOperatorPrintTo(pw, "conditional-expression");
        }
    }

其中要實(shí)現(xiàn)它的構(gòu)造函數(shù)和輸出格式printTo()。
另外需要修改幾個(gè)小地方:
定義CONDEXPR常量
(注:由于在tree.java里有幾個(gè)常量的注釋中寫了原先用的類名,故就用一樣的了)

/**
 * Conditional expressions, of type Conditional.
 */
public static final int CONDEXPR = CATCH + 1;

補(bǔ)全visitor的接口

public void visitConditional(Conditional that) {
      visitTree(that);
}
  • switch-case語句
    常量定義等內(nèi)容和三元表達(dá)式一樣,下面著重看Parser.y中的寫法:
    首先考慮每個(gè)case,寫出它的格式
Case         : CASE Constant COLON StmtList
DefaultCase  : DEFAULT COLON StmtList

由于有普通case和default case的區(qū)別,故在Case構(gòu)造函數(shù)中增加kind以區(qū)分,在輸出時(shí)根據(jù)kind不同來區(qū)分格式

// Conditioned Case
public Case(int kind, Expr constant, List<Tree> exprlist, Location loc) {
    super(kind, loc);
    this.constant = constant;
    this.exprlist = exprlist;
}
// Default Case
public Case(int kind, List<Tree> exprlist, Location loc) {
    super(kind, loc);
    this.exprlist = exprlist;
}

然后若干個(gè)case組成的列表,由于優(yōu)先寫左遞歸,故為了方便將有無default case的情況分開來寫成如下形式,其CaseList的具體實(shí)現(xiàn)可直接參照StmtList類似地寫出。

CaseListWithEnd : CaseList
                  | CaseList DefaultCase
CaseList        : CaseList Case
                  |

于是每個(gè)switch語句就可以寫成

SwitchStmt      : SWITCH '(' Expr ')' '{' CaseListWithEnd '}'
  • <<運(yùn)算符、repeat-until循環(huán)、continue語句由于比較簡單,類似地實(shí)現(xiàn)即可

調(diào)試遇到的碰到的坑

  • 在寫switch-case語句的時(shí)候,由于在三元運(yùn)算符時(shí)將冒號:轉(zhuǎn)為COLON,故不能將Case寫成
Case            : CASE Constant ':' StmtList
  • parser.y中的常量全部需要用單引號
  • 目前還不知道如何開啟byacc的yydebug模式,這給調(diào)試帶來了不少麻煩,只能手動(dòng)輸出調(diào)試,感覺需要進(jìn)一步研究一下它的架構(gòu)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容