余岳 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.y中Stmt的部分加入一個(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)。