美文网首页
编译原理PA1实验报告

编译原理PA1实验报告

作者: fishpear | 来源:发表于2016-10-19 08:18 被阅读0次

    余岳 2015011367

    环境搭建

    • 我IDE用的intellij,作业所给的框架非常方便,可以直接运行。

    实验内容

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

    然后在Parser.yStmt的部分加入一个新的选项

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

    由于样例中强制要求右结合,故添加token和右结合标记,以及由于优先级的较低,应当写在and和or的上面

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

    之后在tree.java里实现Conditional这个类

        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");
            }
        }
    

    其中要实现它的构造函数和输出格式printTo()
    另外需要修改几个小地方:
    定义CONDEXPR常量
    (注:由于在tree.java里有几个常量的注释中写了原先用的类名,故就用一样的了)

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

    补全visitor的接口

    public void visitConditional(Conditional that) {
          visitTree(that);
    }
    
    • switch-case语句
      常量定义等内容和三元表达式一样,下面着重看Parser.y中的写法:
      首先考虑每个case,写出它的格式
    Case         : CASE Constant COLON StmtList
    DefaultCase  : DEFAULT COLON StmtList
    

    由于有普通case和default case的区别,故在Case构造函数中增加kind以区分,在输出时根据kind不同来区分格式

    // 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;
    }
    

    然后若干个case组成的列表,由于优先写左递归,故为了方便将有无default case的情况分开来写成如下形式,其CaseList的具体实现可直接参照StmtList类似地写出。

    CaseListWithEnd : CaseList
                      | CaseList DefaultCase
    CaseList        : CaseList Case
                      |
    

    于是每个switch语句就可以写成

    SwitchStmt      : SWITCH '(' Expr ')' '{' CaseListWithEnd '}'
    
    • <<运算符、repeat-until循环、continue语句由于比较简单,类似地实现即可

    调试遇到的碰到的坑

    • 在写switch-case语句的时候,由于在三元运算符时将冒号:转为COLON,故不能将Case写成
    Case            : CASE Constant ':' StmtList
    
    • parser.y中的常量全部需要用单引号
    • 目前还不知道如何开启byacc的yydebug模式,这给调试带来了不少麻烦,只能手动输出调试,感觉需要进一步研究一下它的架构。

    相关文章

      网友评论

          本文标题:编译原理PA1实验报告

          本文链接:https://www.haomeiwen.com/subject/nttxuttx.html