Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add operation for assignment and add structure conditional for IF and ELSE #42

Open
wants to merge 1 commit into
base: assignment
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/cup/parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ terminal LPAREN, RPAREN;
terminal COMMA, SEMICOLON;
terminal VAR, EQ, COLON;
terminal LET, IN;
terminal ASSIGN;
terminal IF, THEN, ELSE;

non terminal Exp program;
non terminal Exp exp;
Expand Down Expand Up @@ -84,6 +86,9 @@ exp ::=
| var:v {: RESULT = new ExpVar(loc(vxleft,vxright), v); :}
| LET:l decs:ds IN exp:b {: RESULT = new ExpLet(loc(lxleft,bxright), ds, b); :}
| LPAREN:l expseq:es RPAREN:r {: RESULT = new ExpSeq(loc(lxleft,rxright), es); :}
| var:v ASSIGN exp:x {: RESULT = new ExpAssign(loc(vxleft,xxright), v, x); :}
/*| IF:i exp:cond THEN exp:e1 {: RESULT = new ExpIf(loc(ixleft,e2xright), cond, e1); :}*/
| IF:i exp:cond THEN exp:e1 ELSE exp:e2 {: RESULT = new ExpIf(loc(ixleft,e2xright), cond, e1, e2); :}
;

exps ::=
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/absyn/ExpAssign.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package absyn;

import env.Env;
import javaslang.collection.Tree;
import parse.Loc;
import types.INT;
import types.Type;

import static error.ErrorHelper.*;
import static semantic.SemanticHelper.*;
import static semantic.SemanticHelper.typeMismatch;

public class ExpAssign extends Exp {

public final Var var;
public final Exp value;

public ExpAssign(Loc loc, Var var, Exp value) {
super(loc);
this.var = var;
this.value = value;
}

@Override
public Tree.Node<String> toTree() {
return Tree.of(annotateType("ExpAssign"), var.toTree(), value.toTree());
}

@Override
protected Type semantic_(Env env) {
Type t1 = var.semantic(env);
Type t2 = value.semantic(env);
if(t1.is(t2))
return t1;
else
throw typeMismatch(value.loc, t2, t1);
}
}
62 changes: 62 additions & 0 deletions src/main/java/absyn/ExpIf.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package absyn;

import env.Env;
import javaslang.collection.List;
import javaslang.collection.Tree;
import parse.Loc;
import types.BOOL;
import types.INT;
import types.Type;
import types.UNIT;

import static semantic.SemanticHelper.typeMismatch;

public class ExpIf extends Exp {

public final Exp condition;
public final Exp expTrue;
public final Exp expFalse;

public ExpIf(Loc loc, Exp condition, Exp expTrue, Exp expFalse) {
super(loc);
this.condition = condition;
this.expTrue = expTrue;
this.expFalse = expFalse;
}

public ExpIf(Loc loc, Exp condition, Exp expTrue) {
super(loc);
this.condition = condition;
this.expTrue = expTrue;
this.expFalse = null;
}

@Override
public Tree.Node<String> toTree() {
List<Tree.Node<String>> children = List.of(condition.toTree());
children = children.append(expTrue.toTree());
if (expFalse != null)
children = children.append(expFalse.toTree());
return Tree.of(annotateType("ExpIf"), children);
}

@Override
protected Type semantic_(Env env) {
Type tCondition = condition.semantic(env);
if(tCondition.is(BOOL.T)){
Type tExp1 = expTrue.semantic(env);
if(expFalse == null){
if(!tExp1.is(UNIT.T)){
throw typeMismatch(expTrue.loc, tExp1, UNIT.T);
}
}
Type tExp2 = expFalse.semantic(env);
if(tExp2.is(tExp1))
return tExp1;
else
throw typeMismatch(expFalse.loc, tExp2, tExp1);
}
else
throw typeMismatch(condition.loc, tCondition, BOOL.T);
}
}
7 changes: 7 additions & 0 deletions src/main/jflex/lexer.jflex
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ id = [a-zA-Z][a-zA-Z0-9_]*
var { return tok(VAR); }
let { return tok(LET); }
in { return tok(IN); }
if { return tok(IF); }
then { return tok(THEN); }
else { return tok(ELSE); }


{id} { return tok(ID, yytext().intern()); }

Expand All @@ -95,5 +99,8 @@ in { return tok(IN); }
";" { return tok(SEMICOLON); }
":" { return tok(COLON); }
"=" { return tok(EQ); }
":=" { return tok(ASSIGN); }



. { throw error(Loc.loc(locLeft()), "unexpected char '%s'", yytext()); }
17 changes: 17 additions & 0 deletions src/test/java/Test/SemantTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,21 @@ public void testSimpleVariableAndLet() throws Exception {
"error.CompilerError: 1/33-1/34 undefined variable 'x'");
}

@Test
public void testExpressionOfAssign() throws IOException {
trun("let var a : int = 10 in a := 5", INT.T);
trun("let var a = 100.8 in a := 5 * 43.56", REAL.T);
erun("let var a = 10 in a := 5 * 43.56", "error.CompilerError: 1/24-1/33 type mismatch: found real but expected int");
trun("let var a = false in a := true || false", BOOL.T);
erun("let var a = 10 in a := true", "error.CompilerError: 1/24-1/28 type mismatch: found bool but expected int");
}

@Test
public void testExpressionIf() throws IOException {
trun("if false then () else ()", UNIT.T);
trun("if true then 57*3.14 else 10.4", REAL.T);
trun("if true || false then true else false", BOOL.T);
erun("if 4.234 then true else false", "error.CompilerError: 1/4-1/9 type mismatch: found real but expected bool");
erun("if false then 57*3.14 else false", "error.CompilerError: 1/28-1/33 type mismatch: found bool but expected real");
}
}