450 likes | 590 Views
コード生成(2). コード生成プログラム セマンティックアクション. 宣言,変数表. K言語 main(){ int a,b,sum; b=a+3; }. アセンブラ PUSHI 1 PUSH 0 PUSHI 3 ADD ASSGN REMOVE. 左辺 bのD番地. D番地. type. 右辺 aのD番地. 変数表. size. 数値3. 代入. 変数名. <Exp>::=<Term> “+” <Term>. b + 7 PUSH 1 0 PUSHI 7
E N D
コード生成(2) コード生成プログラム セマンティックアクション
宣言,変数表 K言語 main(){ int a,b,sum; b=a+3; } アセンブラ PUSHI 1 PUSH 0 PUSHI 3 ADD ASSGN REMOVE 左辺 bのD番地 D番地 type 右辺 aのD番地 変数表 size 数値3 代入 変数名
<Exp>::=<Term>“+”<Term> b+7 PUSH 10 PUSHI 7 ADD void parseExp(){ parseTerm(); if(token.checkSymbol(ADD))nextToken(); parseTerm(); appendCode(Operator.ADD); }
if(a) b=3; a=0番地,b=10番地,c=20番地 とする 100 PUSH0 101 BEQ 106 102 PUSHI 10 103 PUSHI 3 104 ASSGN 105 REMOVE 106 appendCode replaceCode
変数表に関するセマンティックアクション VarTable varTable; 変数追加,Dseg番地を返す adr=varTable.addElement(type,name,size) 番地取得 varTable.getAddress(name)
VSMのコード生成→iseg.の省略 命令だけのコード iseg.appendCode(opCode) 命令+アドレス iseg.appendcode(opCode,adr) アドレス変更 iseg.replaceCode(ptr番地,adr行先番地) 例: ptr番地 BEQadr行先番地 現在のiseg番地 iseg.getAddress()
最後にHALT void parseProgram(){ parseMain_function(); appendCode(HALT); } Operator.HALT を省略
Var_decl(1) 初期値設定なし • <Var_decl> ::= “int” <Var1> { “,” <Var1> } • <Var1> ::= NAME | NAME “[“ INTEGER “]”
Var_decl ⇒変数表に追加,配列 void parseVar_decl1(){int adr; String name=token.getString(); if(token.checkSymbol(NAME)) nextToken(); if(token.checkSymbol(LBRACKET)){ nextToken(); if(token.checkSymbol(INTEGER)){ adr=varTable.addVar(INTARRAY,name, token.getIntValue()); nextToken();} if(token.checkSymbol(RBRACKET)) nextToken();} elseadr=varTable.addVar(INTSCALAR,name, 1); ........
Var_decl(2) 初期値設定あり • <Var_decl> ::= “int” <Var1> { “,” <Var1> } • <Var1> ::= NAME [ “=“ [ “-”] INTEGER ] | NAME “[“ INTEGER “]”
Var_decl ⇒変数表に追加,初期値設定 void parseVar_decl1(){int adr; String name=token.getString(); if(token.checkSymbol(NAME)) nextToken(); if(token.checkSymbol(LBRACKET)){ ................ else { adr=varTable.addVar(name, INTSCALAR, 1); if(token.checkSymbol(ASSIGN)){int sign=1;nextToken(); appendCode(PUSHI,varTable.getAddress(name)); if(token.checkSymbol(SUB)){sign = -1;nextToken();} if(token.checkSymbol(INTEGER)){ appendCode(PUSHI,sign*token.getIntValue()); nextToken(); appendCode(ASSGN); appendCode(REMOVE);}
★<if>::=“if” ”(“ <expression> “)” <statement> void parseIf(){ if(token.checkSymbol(IF))nextToken(); if(token.checkSymbol(LPAREN))nextToken(); parseExpression(); int adr=appendCode(Operator.BEQ,-1); if(token.checkSymbol(RPAREN)))nextToken(); parseStatement(); replaceCode(adr, iseg.getAddress()); }
どの位置にセマンティックアクションをいれるか?どの位置にセマンティックアクションをいれるか? • <While_state> ::= “while” “(” <Expression> “)” <State> void parseWhile_state(){ ? int isegAdr1=getIsegPtr(); if(symbol==Symbol.WHILE) nextToken(); ? int isegAdr1=getIsegPtr(); if(symbol==Symbol.LPAREN) nextToken(); ? int isegAdr1=getIsegPtr(); parseExpression(); //意味がある場所 ? int isegAdr2=appendCode(Operators.BEQ ); if(symbol==Symbol.RPAREN)nextToken(); ? int isegAdr2=appendCode(Operators.BEQ); parseState(); //意味がある場所 appendCode(Operators.JUMP,isegAdr1); replaceCode(isegAdr2);}
式[簡単化している] <Exp_statement> ::= <expression> “;” <expression>::=<Exp> [ “=“ <expression> ] <Exp>::= <Term> { “+” <Term> } <Term>::= NAME
式の最後 <Exp_statement> ::= <expression> “;” a=b; PUSHI aの番地 PUSHbの番地 ASSGN REMOVE セミコロン→REMOVE
<Exp_statement> ::= <expression> “;” void parseExp_Statement(){ parseExpression(); if(token.checkSymbol(SEMICOLON)){ appendCode(Operator.REMOVE); nextToken(); } else syntaxError("exp_statement"); }
<expression>::=<Exp>[“=“ <expression>] void parseExpression(){ if(parseExp()){ if(token.checkSymbol(ASSIGN)){ nextToken(); parseExpression(); appendCode(Operator.ASSGN); } } }
加算 <Exp> ::= <Term> +<Term>; a=b+c; PUSHI aの番地 PUSHbの番地 PUSHcの番地 ADD ASSGN REMOVE Symbol.ADD→Operator.ADD
<Exp>::=<Term>{“+”<Term>} boolean parseExp(){ boolean sahenp=parseTerm(true); while(token.checkSymbol(ADD)){ sahenp=false; nextToken(); parseTerm(false); appendCode(Operator.ADD); } return sahenp; }
変数(左辺? 右辺?) <Term> ::= NAME a=b pushi aの番地 pushbの番地 ASSGN 左辺 → pushi 右辺 → push
<Term>::=NAME booelan parseTerm(boolean sahenp){ if(token.checkSymbol(NAME)){ String name=token.getString(); int adr=varTable.getAddress(name); nextToken(); if(sahenp && token.checkSymbol(ASSGN)) appendCode(PUSHI,adr); else { appendCode(PUSH,adr); sahenp=false; } return sahenp; }
ASSIGN? ASSIGNADD? <Term> ::= NAME a+=b PUSHI aの番地 COPY LOAD PUSHbの番地 ADD ASSGN
代入文 = と += void parseExpression(){ if(parseExp()){ Symbol symbol=token.getSymbol(); if(symbol==ASSIGNADD){ appendCode(Operator.COPY); appendCode(Operator.LOAD);} nextToken(); parseExpression(); if(symbol==ASSIGNADD)appendCode(Operator.ADD); appendCode(Operator.ASSGN); insertAssignCode(type); } }
Arithmetic_expression(1) void parseArithmetic_expression(){ parseArithmetic_term(); while(token.checkSymbol(ADD) || token.checkSymbol(SUB)){ SymbolopCode=token.getSymbol(); nextToken(); parseArithmetic_term(); if(opCode==Symbol.ADD) appendCode(Operator.ADD); elseappendCode(Operator.SUB); } }
Arithmetic_expression(2) void parseArithmetic_expression(){ parseArithmetic_term(); while(token.checkSymbol(ADD) || token.checkSymbol(SUB)){ if(token.checkSymbol(ADD)){ nextToken(); parseArithmetic_term(); appendCode(Operator.ADD); } else { nextToken(); parseArithmetic_term(); appendCode(Operator.SUB); } } }
配列 NAME[<exp>] a[3]=b[5] PUSHI aの番地 PUSHI 3 ADD PUSHI bの番地 PUSHI5 ADD LOAD ASSGN
配列 elseif(curType==LEFT_BRACKET){ appendCode(Operator.PUSHI,varTable.getAddress(name)); nextToken(); parseExpression(); if(token.checkSymbol(RBRACKET)) nextToken(); appendCode(Operator.ADD); if(! sahenp) appendCode(Operator.LOAD);} }
★<Arithmetic_factor>::=“-” <Arithmetic_factor> |... void parseArithmetic_factor(){ if(token.checkSymbol(SUB)){ nextToken(); parseArithmetic_factor(); appendCode(Operator.CSIGN); } ............. }
後置INC NAME ++ a ++ PUSH aの番地 COPY INC POP aの番地
★後置INC elseif(token.checkSymbol(Symbol.INC)){ nextToken(); appendCode(Operator.PUSH,varTable.getAddress(name)); appendCode(Operator.COPY); appendCode(Operator.INC); appendCode(Operator.POP,varTable.getAddress(name)); }
前置DEC -- NAME --a PUSH aの番地 DEC COPY POP aの番地
前置DEC elseif(token.checkSymbol(Symbol.DEC)){ nextToken(); if(token.checkSymbol(NAME)){ String name=token.getString(); appendCode(Operator.PUSH,varTable.getAddress(name)); appendCode(Operator.DEC); appendCode(Operator.COPY); appendCode(Operator.POP,varTable.getAddress(name)); nextToken(); } }
★ 論理演算 void insertLogicalCode(Symbol symbol){ appendCode(COMP); switch(symbol){ case EQUAL: appendCode(Operator.BEQ,iseg.getAddress()+3); break; case NOTEQ: appendCode(Operator.BNE,iseg.getAddress()+3); break; } appendCode(Operator.PUSHI,0); appendCode(Operator.JUMP, iseg.getAddress()+2); appendCode(Operator.PUSHI,1); }
属性文法 構文規則+意味規則 attribute grammar スタックマシン用コードの属性文法
スタックマシン用コードの属性文法 構文規則 意味規則を書くために書き方を変える (0)S→E”$” S→E”$” (1)E→E”+”EE0→E1”+”E2 (2)E→E”*”EE0→E1”*”E2 (3)E→”(”E”)” E0→”(”E1”)” (4)E→”i” E→”i” (注)構文規則では単にEを 意味規則を記述するためE1,E2などと書く 同じEでも意味 (値)が異なる⇒ E0,E1,E2
スタックマシン用コードの属性文法 構文規則 意味規則 (0)S→E”$” S.code=E.code (1)E0→E1”+”E2 E0.code=E1.code||E2.code||"ADD\n” (2)E0→E1”*”E2 E0.code=E1.code||E2.code||"MUL\n” (3)E0→”(”E1”)” E0.code=E1.code (4)E→”i” E.code="PUSH " || i.name || "\n” (注) || は文字列をつなぐ演算子とする.
★ 加算 構文規則 意味規則 E→T1”+”T2 E.code=T1.code||T2.code||"ADD\n” Javaプログラム void parseE(){ parseT(); if(token.checkSymbol(ADD)) nextToken(); parseT(); iseg.appendCode(“ADD\n”); } T.codeを生成 T.codeを生成
繰り返し加算 構文規則 意味規則 E→T1{“+”T2} E.code=T1.code{||T2.code||"ADD\n”} Javaプログラム void parseE(){ parseT(); while(token.checkSymbol(ADD)) { nextToken(); parseT(); iseg.appendCode(“ADD\n”); } } T.codeを生成 T.codeを生成
課題7:下記構文のコンパイラを書きなさい <Program>::=<Main_function> <Main_function>::= “main” “(“ “)” <Block> <Block>::= “{“ { <Var_decl> } { <Statement> } “}” <Var_decl>::= “int” NAME { “,” NAME } “;” <Statement>::= <Assignment> | “{“ <Statement> “}” | “;” <Assignment>::= <Lefthand_side> “=” <Arithmetic_expression> “;” <Lefthand_side>::= NAME <Arithmetic_expression>::=<Arithmetic_term> { (“+”|”-“) <Arithmetic_term> } <Arithmetic_term>::=<Arithmetic_factor> { (“*”|”/”|”%”) <Arithmetic_factor> } <Arithmetic_factor>::=<Unsigned_factor> | “-“ <Unsigned_factor> <Unsigned_factor>::=NAME | INTEGER | “(“ <Arithmetic_expression> “)”
問題1 T→F{*F} T.code=F1.code {||F2.code ||“MUL\n”} ①appendCode(F1) ②appendCode(F2) ③appendCode(MUL) ④replaceCode(ADD) ⑤appendCode(F) ⑥正解なし (注) iseg.を省略 問(1) 実際にコードを 生成する部分は?
問題2 F→”-”F; F0.code=F1.code || ① “SUB\n” ② “MINUS” ③ “CSIGN\n” ④ appendCode(SUB) ⑤ appendCode(CSIGN) ⑥正解なし 問(2)
問題3 後置-- elseif(token.checkSymbol(DEC)){ getToken(); appendCode(PUSH, varTable.getAddress(name)); appendCode(COPY); appendCode(POP, varTable.getAddress(name)); } ①appendCode(SUB) ②appendCode(DEC) ③appendCode(PUSH) ④appendCode(LOAD) ⑤appendCode(PUSHI) ⑥正解なし 問(3)
問題4while void parseWhile(){ nextToken(); if(token.checkSymbol(LPAREN)) nextToken(); int adr1=iseg.getAddress(); parseExpression(); if(token.checkSymbol(RPAREN)) nextToken(); int adr2=appendCode(BEQ,-1); parseStatement(); appendCode(JUMP,adr1); int adr3=iseg.getAddress(); } ①appendCode(BEQ,adr1); ②replaceCode(adr2,adr3); ③replaceCode(adr1,adr2); ④BEQ adr2 ⑤aqppendCode(JUMP); ⑥正解なし 問(4)
問題5 “>=“ parseArithmetic_expression(); if(token.checkSymbol(GREATEQ)) { nextToken(); parseArithmetic_expression(); appendCode(COMP); appendCode(BGE, iseg.getAddress()+3); appendCode(JUMP, iseg.getAddress()+2); appendCode(PUSHI,1); } ①appendCode(PUSHI,1); ②appendCode(PUSH,1); ③appendCode(PUSH,0); ④appendCode(PUSHI,0); ⑤replaceCode(JUMP); ⑥正解なし 問(5)