package IR.Flat;
import IR.*;
import IR.Tree.*;
+
import java.util.*;
public class BuildFlat {
return new NodePair(cond.getBegin(), nopend);
}
+
+ private NodePair flattenSwitchStatementNode(SwitchStatementNode ssn) {
+ TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.INT));
+ NodePair cond=flattenExpressionNode(ssn.getCondition(),cond_temp);
+ FlatNop nopend=new FlatNop();
+ NodePair sbody = flattenSwitchBodyNode(ssn.getSwitchBody(), cond_temp, nopend);
+
+ cond.getEnd().addNext(sbody.getBegin());
+ return new NodePair(cond.getBegin(), sbody.getEnd());
+ }
+
+ private NodePair flattenSwitchBodyNode(BlockNode bn, TempDescriptor cond_temp, FlatNode endnode) {
+ FlatNode begin=null;
+ FlatNode end=endnode;
+ NodePair prev_true_branch = null;
+ NodePair prev_false_branch = null;
+ for(int i=0; i<bn.size(); i++) {
+ SwitchBlockNode sbn = (SwitchBlockNode)bn.get(i);
+ HashSet oldbs=breakset;
+ breakset=new HashSet();
+
+ NodePair body=flattenBlockNode(sbn.getSwitchBlockStatement());
+ Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+ FlatNode cond_begin = null;
+ NodePair prev_fnp = null;
+ for(int j = 0; j < slnv.size(); j++) {
+ SwitchLabelNode sln = slnv.elementAt(j);
+ NodePair left = null;
+ NodePair false_np = null;
+ if(sln.isDefault()) {
+ left = body;
+ } else {
+ TempDescriptor cond_tmp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
+ TempDescriptor temp_left=TempDescriptor.tempFactory("leftop", sln.getCondition().getType());
+ Operation op=new Operation(Operation.EQUAL);
+ left=flattenExpressionNode(sln.getCondition(), temp_left);
+ FlatOpNode fon=new FlatOpNode(cond_tmp, temp_left, cond_temp, op);
+ left.getEnd().addNext(fon);
+
+ FlatCondBranch fcb=new FlatCondBranch(cond_tmp);
+ fcb.setTrueProb(State.TRUEPROB);
+
+ FlatNop nop=new FlatNop();
+ false_np=new NodePair(nop,nop);
+
+ fon.addNext(fcb);
+ fcb.addTrueNext(body.getBegin());
+ fcb.addFalseNext(false_np.getBegin());
+ }
+ if((prev_fnp != null) && (prev_fnp.getEnd() != null)) {
+ prev_fnp.getEnd().addNext(left.getBegin());
+ }
+ prev_fnp = false_np;
+
+ if (begin==null) {
+ begin = left.getBegin();
+ }
+ if(cond_begin == null) {
+ cond_begin = left.getBegin();
+ }
+ }
+ if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
+ prev_false_branch.getEnd().addNext(cond_begin);
+ }
+ prev_false_branch = prev_fnp;
+ if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
+ prev_true_branch.getEnd().addNext(body.getBegin());
+ }
+ prev_true_branch = body;
+ for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
+ FlatNode fn=(FlatNode)breakit.next();
+ breakit.remove();
+ fn.addNext(endnode);
+ }
+ breakset=oldbs;
+ }
+ if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
+ prev_true_branch.getEnd().addNext(endnode);
+ }
+ if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
+ prev_false_branch.getEnd().addNext(endnode);
+ }
+ if(begin == null) {
+ end=begin=new FlatNop();
+ }
+ return new NodePair(begin,end);
+ }
+
private NodePair flattenLoopNode(LoopNode ln) {
HashSet oldbs=breakset;
HashSet oldcs=continueset;
case Kind.IfStatementNode:
return flattenIfStatementNode((IfStatementNode)bsn);
+
+ case Kind.SwitchStatementNode:
+ return flattenSwitchStatementNode((SwitchStatementNode)bsn);
case Kind.LoopNode:
return flattenLoopNode((LoopNode)bsn);
blockstatements.add(new IfStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
parseSingleBlock(pn.getChild("statement").getFirstChild()),
pn.getChild("else_statement")!=null ? parseSingleBlock(pn.getChild("else_statement").getFirstChild()) : null));
+ } else if ((state.MGC) && (isNode(pn,"switch_statement"))) {
+ // TODO add version for normal Java later
+ blockstatements.add(new SwitchStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
+ parseSingleBlock(pn.getChild("statement").getFirstChild())));
+ } else if ((state.MGC) && (isNode(pn,"switch_block_list"))) {
+ // TODO add version for normal Java later
+ ParseNodeVector pnv=pn.getChildren();
+ for(int i=0; i<pnv.size(); i++) {
+ ParseNode sblockdecl=pnv.elementAt(i);
+
+ if(isNode(sblockdecl, "switch_block")) {
+ ParseNode lpn=sblockdecl.getChild("switch_labels").getChild("switch_label_list");
+ ParseNodeVector labelv=lpn.getChildren();
+ Vector<SwitchLabelNode> slv = new Vector<SwitchLabelNode>();
+ for(int j=0; j<labelv.size(); j++) {
+ ParseNode labeldecl=labelv.elementAt(j);
+ if(isNode(labeldecl, "switch_label")) {
+ slv.addElement(new SwitchLabelNode(parseExpression(labeldecl.getChild("constant_expression").getFirstChild()), false));
+ } else if(isNode(labeldecl, "default_switch_label")) {
+ slv.addElement(new SwitchLabelNode(null, true));
+ }
+ }
+
+ blockstatements.add(new SwitchBlockNode(slv,
+ parseSingleBlock(sblockdecl.getChild("switch_statements").getFirstChild())));
+
+ }
+ }
} else if (isNode(pn,"taskexit")) {
Vector vfe=null;
if (pn.getChild("flag_effects_list")!=null)
public final static int ArrayInitializerNode=27;
public final static int SynchronizedNode=28;
public final static int GenReachNode=29;
+ public final static int SwitchStatementNode=30;
+ public final static int SwitchLabelNode=31;
+ public final static int SwitchBlockNode=32;
}
case Kind.IfStatementNode:
checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
return;
+
+ case Kind.SwitchStatementNode:
+ checkSwitchStatementNode(md, nametable, (SwitchStatementNode)bsn);
+ return;
case Kind.LoopNode:
checkLoopNode(md, nametable, (LoopNode)bsn);
if (isn.getFalseBlock()!=null)
checkBlockNode(md, nametable, isn.getFalseBlock());
}
+
+ void checkSwitchStatementNode(Descriptor md, SymbolTable nametable, SwitchStatementNode ssn) {
+ checkExpressionNode(md, nametable, ssn.getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+
+ BlockNode sbn = ssn.getSwitchBody();
+ boolean hasdefault = false;
+ for(int i = 0; i < sbn.size(); i++) {
+ boolean containdefault = checkSwitchBlockNode(md, nametable, (SwitchBlockNode)sbn.get(i));
+ if(hasdefault && containdefault) {
+ throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+ }
+ hasdefault = containdefault;
+ }
+ }
+
+ boolean checkSwitchBlockNode(Descriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
+ Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+ int defaultb = 0;
+ for(int i = 0; i < slnv.size(); i++) {
+ if(slnv.elementAt(i).isdefault) {
+ defaultb++;
+ } else {
+ checkConstantExpressionNode(md, nametable, slnv.elementAt(i).getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+ }
+ }
+ if(defaultb > 1) {
+ throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+ } else {
+ checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+ return (defaultb > 0);
+ }
+ }
+
+ void checkConstantExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+ switch(en.kind()) {
+ case Kind.FieldAccessNode:
+ checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
+ return;
+
+ case Kind.LiteralNode:
+ checkLiteralNode(md,nametable,(LiteralNode)en,td);
+ return;
+ }
+ throw new Error();
+ }
void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
switch(en.kind()) {
cd = ((MethodDescriptor)md).getClassDesc();
SymbolTable fieldtbl = cd.getFieldTable();
FieldDescriptor fd=(FieldDescriptor)fieldtbl.get(varname);
- if((fd == null) || (!fd.isStatic()) || (!fd.isVolatile())){
+ if((fd == null) || (!fd.isStatic())){
// no such field in the class or it is not a static field
throw new Error("Name "+varname+" should not be used in static block: "+md);
} else {
non terminal ParseNode expression_statement, statement_expression;
non terminal ParseNode if_then_statement;
non terminal ParseNode if_then_else_statement, if_then_else_statement_no_short_if;
-//non terminal ParseNode switch_statement, switch_block;
-//non terminal ParseNode switch_block_statement_groups;
-//non terminal ParseNode switch_block_statement_group;
-//non terminal ParseNode switch_labels, switch_label;
+non terminal ParseNode switch_statement, switch_block;
+non terminal ParseNode switch_block_statement_groups;
+non terminal ParseNode switch_block_statement_group;
+non terminal ParseNode switch_labels, switch_label;
non terminal ParseNode while_statement, while_statement_no_short_if;
non terminal ParseNode do_statement;
non terminal ParseNode for_statement, for_statement_no_short_if;
non terminal ParseNode assignment;
non terminal ParseNode assignment_operator;
non terminal ParseNode expression_opt, expression;
-//non terminal ParseNode constant_expression;
+non terminal ParseNode constant_expression;
//failure aware computation keywords
terminal FLAG;
terminal OPTIONAL;
block:st {: RESULT=st; :}
| empty_statement:st {: RESULT=st; :}
| expression_statement:st {: RESULT=st; :}
-// | switch_statement
+ | switch_statement:st {: RESULT=st; :}
| do_statement:dos {:RESULT=dos; :}
| break_statement:st {: RESULT=st; :}
| continue_statement:st {: RESULT=st; :}
RESULT=pn;
:}
;
-//switch_statement ::=
-// SWITCH LPAREN expression RPAREN switch_block
-// ;
-//switch_block ::=
-// LBRACE switch_block_statement_groups switch_labels RBRACE
-// | LBRACE switch_block_statement_groups RBRACE
-// | LBRACE switch_labels RBRACE
-// | LBRACE RBRACE
-// ;
-//switch_block_statement_groups ::=
-// switch_block_statement_group
-// | switch_block_statement_groups switch_block_statement_group
-// ;
-//switch_block_statement_group ::=
-// switch_labels block_statements
-// ;
-//switch_labels ::=
-// switch_label
-// | switch_labels switch_label
-// ;
-//switch_label ::=
-// CASE constant_expression COLON
-// | DEFAULT COLON
-// ;
+switch_statement ::=
+ SWITCH LPAREN expression:exp RPAREN switch_block:body
+ {:
+ ParseNode pn=new ParseNode("switch_statement");
+ pn.addChild("condition").addChild(exp);
+ pn.addChild("statement").addChild(body);
+ RESULT=pn;
+ :}
+ ;
+switch_block ::=
+ LBRACE switch_block_statement_groups:sbsg switch_labels:sl RBRACE
+ {:
+ ParseNode pn = new ParseNode("switch_block");
+ pn.addChild("switch_labels").addChild(sl);
+ pn.addChild("switch_statements").addChild(new ParseNode("empty"));
+ sbsg.addChild(pn);
+ RESULT=sbsg;
+ :}
+ | LBRACE switch_block_statement_groups:sbsg RBRACE
+ {:
+ RESULT=sbsg;
+ :}
+ | LBRACE switch_labels:sl RBRACE
+ {:
+ ParseNode pnb = new ParseNode("switch_block_list");
+ ParseNode pn = new ParseNode("switch_block");
+ pn.addChild("switch_labels").addChild(sl);
+ pn.addChild("switch_statements").addChild(new ParseNode("empty"));
+ pnb.addChild(pn);
+ RESULT=pnb;
+ :}
+ | LBRACE RBRACE {: RESULT=new ParseNode("empty"); :}
+ ;
+switch_block_statement_groups ::=
+ switch_block_statement_group:sbsg
+ {:
+ ParseNode pn = new ParseNode("switch_block_list");
+ pn.addChild(sbsg);
+ RESULT=pn;
+ :}
+ | switch_block_statement_groups:sbsgs switch_block_statement_group:sbsg
+ {:
+ sbsgs.addChild(sbsg);
+ RESULT=sbsgs;
+ :}
+ ;
+switch_block_statement_group ::=
+ switch_labels:sls block_statements:body
+ {:
+ ParseNode pn=new ParseNode("switch_block");
+ pn.addChild("switch_labels").addChild(sls);
+ pn.addChild("switch_statements").addChild(body);
+ RESULT=pn;
+ :}
+ ;
+switch_labels ::=
+ switch_label:sl
+ {:
+ ParseNode pn=new ParseNode("switch_label_list");
+ pn.addChild(sl);
+ RESULT=pn;
+ :}
+ | switch_labels:sls switch_label:sl
+ {:
+ sls.addChild(sl);
+ RESULT=sls;
+ :}
+ ;
+switch_label ::=
+ CASE constant_expression:ce COLON
+ {:
+ ParseNode pn=new ParseNode("switch_label");
+ pn.addChild(ce);
+ RESULT=pn;
+ :}
+ | DEFAULT COLON
+ {:
+ RESULT=new ParseNode("default_switch_label");
+ :}
+ ;
while_statement ::=
WHILE LPAREN expression:exp RPAREN statement:st {:
;
// note that this constraint must be enforced during semantic checking
// 'constant_expression' should include enumerated constants.
-//constant_expression ::=
-// expression
-// ;
+constant_expression ::=
+ expression:exp
+ {:
+ ParseNode pn = new ParseNode("constant_expression");
+ pn.addChild(exp);
+ RESULT=pn;
+ :}
+ ;
genreach_statement ::=
--- /dev/null
+public class SwitchCaseTest {
+ public SwitchCaseTest(){}
+
+ public static void main(String[] args) {
+ Random rand = new Random(47);
+ for(int i = 0; i < 30; i++) {
+ int c = rand.nextInt(26) + 'a';
+ System.out.printString((char)c + ", " + c + ": ");
+ switch(c) {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u': System.out.printString("vowel\n");
+ //break;
+ case 'y':
+ case 'w': System.out.printString("Sometimes a vowel\n");
+ break;
+ default: System.out.printString("consonant\n");
+ }
+ }
+ }
+} /* Output:
+y, 121: Sometimes a vowel
+n, 110: consonant
+z, 122: consonant
+b, 98: consonant
+r, 114: consonant
+n, 110: consonant
+y, 121: Sometimes a vowel
+g, 103: consonant
+c, 99: consonant
+f, 102: consonant
+o, 111: vowel
+w, 119: Sometimes a vowel
+z, 122: consonant
+...
+*///:~