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

adicionado atribuição de variaveis e if then else #41

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
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<className>Parser</className>
<symbolsName>SymbolConstants</symbolsName>
<symbolsInterface>true</symbolsInterface>
<expectedConflicts>1</expectedConflicts>
<!-- Makes CUP generate xleft/xright handles for accessing Location objects for symbol start/end inside actions. -->
<locations>true</locations>
</configuration>
Expand Down
7 changes: 5 additions & 2 deletions src/main/cup/parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ terminal String ID;
terminal PLUS, MINUS, TIMES, DIV, UMINUS;
terminal AND, OR;
terminal LPAREN, RPAREN;
terminal COMMA, SEMICOLON;
terminal COMMA, SEMICOLON, ASSIGN;
terminal VAR, EQ, COLON;
terminal LET, IN;
terminal LET, IN, IF, THEN, ELSE;

non terminal Exp program;
non terminal Exp exp;
Expand Down Expand Up @@ -84,6 +84,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:e {: RESULT = new ExpAssign(loc(vxleft,exright), v, e);:}
| IF:i exp:t THEN exp:e1 {: RESULT = new ExpIf(loc(ixleft,e1xright), t, e1, null);:}
| IF:i exp:t THEN exp:e1 ELSE exp:e2 {: RESULT = new ExpIf(loc(ixleft,e2xright), t, e1, e2);:}
;

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

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

import static semantic.SemanticHelper.typeMismatch;

public class ExpAssign extends Exp {

public final Var variable;
public final Exp exp;

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

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

@Override
protected Type semantic_(Env env) {
Type t_var = variable.semantic(env);
Type t_exp = exp.semantic_(env);
if (!t_exp.is(t_var)) {
throw typeMismatch(exp.loc, t_exp, t_var);
}
return t_var;
}
}
60 changes: 60 additions & 0 deletions src/main/java/absyn/ExpIf.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package absyn;

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

import static semantic.SemanticHelper.typeMismatch;

public class ExpIf extends Exp {

public final Exp test;
public final Exp e1;
public final Exp e2;

public ExpIf(Loc loc, Exp test, Exp e1, Exp e2) {
super(loc);
this.test = test;
this.e1 = e1;
this.e2 = e2;
}

@Override
public Tree.Node<String> toTree() {
List<Tree.Node<String>> children = List.of(test.toTree());
children = children.append(e1.toTree());
if (e2 != null)
children = children.append(e2.toTree());
return Tree.of("ExpIf", children);
}

@Override
protected Type semantic_(Env env) {
Type t_test = test.semantic(env);
if (!t_test.is(BOOL.T)) {
throw typeMismatch(test.loc, t_test, BOOL.T);
}

Type t_e1 = e1.semantic(env);
if (e2 != null) {
Type t_e2 = e2.semantic(env);
if (!t_e1.is(t_e2)) {
if (!t_e2.is(t_e1)) {
throw typeMismatch(e2.loc, t_e2, t_e1);
} else {
return t_e2;
}
}
return t_e1;
} else {
if (!t_e1.is(UNIT.T)) {
throw typeMismatch(e1.loc, t_e1, UNIT.T);
}
return t_e1;
}
}
}
4 changes: 4 additions & 0 deletions src/main/jflex/lexer.jflex
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ 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 +98,6 @@ 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()); }
154 changes: 89 additions & 65 deletions src/test/java/Test/SemantTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,101 @@

public class SemantTest {

private Type runSemantic(String input) throws Exception {
Lexer lexer = new Lexer(new StringReader(input), "unknown");
Parser parser = new Parser(lexer);
Symbol program = parser.parse();
Exp parseTree = (Exp) program.value;
return parseTree.semantic(new Env());
}
private Type runSemantic(String input) throws Exception {
Lexer lexer = new Lexer(new StringReader(input), "unknown");
Parser parser = new Parser(lexer);
Symbol program = parser.parse();
Exp parseTree = (Exp) program.value;
return parseTree.semantic(new Env());
}

private void trun(String input, Type type) {
try {
softly.assertThat(runSemantic(input))
.as("%s", input)
.isEqualTo(type);
}
catch (Exception e) {
e.printStackTrace();
}
}
private void trun(String input, Type type) {
try {
softly.assertThat(runSemantic(input))
.as("%s", input)
.isEqualTo(type);
} catch (Exception e) {
e.printStackTrace();
}
}

private void erun(String input, String message) throws IOException {
softly.assertThatThrownBy(() -> runSemantic(input))
.as("%s", input)
.isInstanceOf(CompilerError.class)
.hasToString(message);
}
private void erun(String input, String message) throws IOException {
softly.assertThatThrownBy(() -> runSemantic(input))
.as("%s", input)
.isInstanceOf(CompilerError.class)
.hasToString(message);
}

@Rule
public final JUnitSoftAssertions softly = new JUnitSoftAssertions();
@Rule
public final JUnitSoftAssertions softly = new JUnitSoftAssertions();

@Test
public void testLiterals() throws Exception {
trun("true", BOOL.T);
trun("123", INT.T);
trun("12.34", REAL.T);
}
@Test
public void testLiterals() throws Exception {
trun("true", BOOL.T);
trun("123", INT.T);
trun("12.34", REAL.T);
}

@Test
public void testFunctionCall() throws Exception {
erun("fat(9)",
"error.CompilerError: 1/1-1/7 undefined function 'fat'");
erun("fat(g(), h())",
"error.CompilerError: 1/5-1/8 undefined function 'g'");
trun("print_int(123)",
UNIT.T);
erun("print_int(true)",
"error.CompilerError: 1/11-1/15 type mismatch: found bool but expected int");
erun("print_int(123, true, f())",
"error.CompilerError: 1/22-1/25 undefined function 'f'");
erun("print_int()",
"error.CompilerError: 1/1-1/12 too few arguments in call to 'print_int'");
}
@Test
public void testFunctionCall() throws Exception {
erun("fat(9)",
"error.CompilerError: 1/1-1/7 undefined function 'fat'");
erun("fat(g(), h())",
"error.CompilerError: 1/5-1/8 undefined function 'g'");
trun("print_int(123)",
UNIT.T);
erun("print_int(true)",
"error.CompilerError: 1/11-1/15 type mismatch: found bool but expected int");
erun("print_int(123, true, f())",
"error.CompilerError: 1/22-1/25 undefined function 'f'");
erun("print_int()",
"error.CompilerError: 1/1-1/12 too few arguments in call to 'print_int'");
}

@Test
public void testSequence() throws Exception {
trun("()", UNIT.T);
trun("(true)", BOOL.T);
trun("(print_int(23); 2.3)", REAL.T);
}
@Test
public void testSequence() throws Exception {
trun("()", UNIT.T);
trun("(true)", BOOL.T);
trun("(print_int(23); 2.3)", REAL.T);
}

@Test
public void testSimpleVariableAndLet() throws Exception {
erun("x",
"error.CompilerError: 1/1-1/2 undefined variable 'x'");
trun("let var x: int = 10 in x",
INT.T);
trun("let var x = 0.56 in x",
REAL.T);
erun("let var x: int = 3.4 in x",
"error.CompilerError: 1/18-1/21 type mismatch: found real but expected int");
erun("(let var x = 5 in print_int(x); x)",
"error.CompilerError: 1/33-1/34 undefined variable 'x'");
}
@Test
public void testSimpleVariableAndLet() throws Exception {
erun("x",
"error.CompilerError: 1/1-1/2 undefined variable 'x'");
trun("let var x: int = 10 in x",
INT.T);
trun("let var x = 0.56 in x",
REAL.T);
erun("let var x: int = 3.4 in x",
"error.CompilerError: 1/18-1/21 type mismatch: found real but expected int");
erun("(let var x = 5 in print_int(x); x)",
"error.CompilerError: 1/33-1/34 undefined variable 'x'");
}

@Test
public void testExpAssign() throws Exception {
trun("let var x = 5.2 in x:=6.6", REAL.T);
trun("let var x = 5 var y = 4 in x := 2*y", INT.T);
trun("let var x = 5.2 var y = 4.3 in x := 2*y", REAL.T);
trun("let var x = false in x := true", BOOL.T);
trun("let var x = 5 in x:=2*x", INT.T);
erun("let var x = 5.2 in z := x",
"error.CompilerError: 1/20-1/21 undefined variable 'z'");
erun("let var x = 5.2 in x:=true",
"error.CompilerError: 1/23-1/27 type mismatch: found bool but expected real");
}

@Test
public void testExpIf() throws Exception {
trun("if true then print_int(4)", UNIT.T);
trun("if false then 4/4 else 3/2", INT.T);
trun("if not(true && false) then print_int(5) else print_real(4.3)", UNIT.T);
erun("if false then true else 3/2",
"error.CompilerError: 1/25-1/28 type mismatch: found int but expected bool");
erun("if true then 4*5",
"error.CompilerError: 1/14-1/17 type mismatch: found int but expected unit");
erun("if 2+2 then print_int(4)",
"error.CompilerError: 1/4-1/7 type mismatch: found int but expected bool");
}
}