Skip to content

Commit

Permalink
Implemented checking for expressions that are no full statements (refs
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-eberle committed Nov 23, 2014
1 parent 8f6334b commit 140b946
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 36 deletions.
27 changes: 22 additions & 5 deletions Compiler/src/compiler/semantic/DeepCheckingVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import compiler.semantic.exceptions.InvalidMethodCallException;
import compiler.semantic.exceptions.MissingReturnStatementOnAPathException;
import compiler.semantic.exceptions.NoSuchMemberException;
import compiler.semantic.exceptions.NotAnExpressionStatementException;
import compiler.semantic.exceptions.RedefinitionErrorException;
import compiler.semantic.exceptions.SemanticAnalysisException;
import compiler.semantic.exceptions.TypeErrorException;
Expand All @@ -75,7 +76,8 @@ public class DeepCheckingVisitor implements AstVisitor {
private MethodDefinition currentMethodDefinition = null;

private boolean isStaticMethod;
private boolean returnOnAllPaths = false;
private boolean returnOnAllPaths;
private boolean isExpressionStatement;

public DeepCheckingVisitor(HashMap<Symbol, ClassScope> classScopes) {
this.classScopes = classScopes;
Expand Down Expand Up @@ -183,6 +185,8 @@ public void visit(AdditionExpression additionExpression) {

@Override
public void visit(AssignmentExpression assignmentExpression) {
this.isExpressionStatement = true;

checkBinaryOperandEqualityOrNull(assignmentExpression);

Expression operand1 = assignmentExpression.getOperand1();
Expand Down Expand Up @@ -469,6 +473,8 @@ public void visit(NegateExpression negateExpression) {

@Override
public void visit(ReturnStatement returnStatement) {
isExpressionStatement = true;

if (returnStatement.getOperand() != null) {
returnStatement.getOperand().accept(this);
expectType(currentMethodDefinition.getType(), returnStatement.getOperand());
Expand Down Expand Up @@ -522,7 +528,7 @@ public void visit(Block block) {

for (Statement statement : block.getStatements()) {
returnOnAllPaths = false;
statement.accept(this);
acceptStatement(statement);
returnInBlockFound |= returnOnAllPaths;
}

Expand Down Expand Up @@ -554,13 +560,13 @@ public void visit(IfStatement ifStatement) {
Statement trueCase = ifStatement.getTrueCase();

returnOnAllPaths = false;
trueCase.accept(this);
acceptStatement(trueCase);
returnInTrueCase = returnOnAllPaths;

Statement falseCase = ifStatement.getFalseCase();
if (falseCase != null) {
returnOnAllPaths = false;
falseCase.accept(this);
acceptStatement(falseCase);
returnInFalseCase = returnOnAllPaths;
}

Expand All @@ -573,7 +579,18 @@ public void visit(WhileStatement whileStatement) {
condition.accept(this);
expectType(BasicType.BOOLEAN, condition);

whileStatement.getBody().accept(this);
acceptStatement(whileStatement.getBody());
}

private void acceptStatement(Statement statement) {
isExpressionStatement = false;

statement.accept(this);

if (statement instanceof Expression && !isExpressionStatement
&& !(statement instanceof MethodInvocationExpression || statement instanceof NewObjectExpression)) {
exceptions.add(new NotAnExpressionStatementException(statement.getPosition()));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package compiler.semantic.exceptions;

import compiler.lexer.Position;

public class NotAnExpressionStatementException extends SemanticAnalysisException {

private static final long serialVersionUID = 7607378965250581103L;

public NotAnExpressionStatementException(Position position) {
super(position, "error: Insert assignment operator to complete expression at " + position);
}
}
2 changes: 1 addition & 1 deletion Compiler/testdata/parser5/CorrectGrammar1.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void i_accept_one_param(Cl1 cl1)
public void i_accept_a_lot_of_params(int a, int[] vec, int[][] A, int[][][] cube) {}

public void i_accept_no_params2(void a,void b,void c) { /* semantic error x3 */
a + b - c + (d) - (-1); /*semantic error void to + and void to - and d undefined*/
a + b - c + (d) - (-1); /*semantic error void to + and void to - and d undefined and no expression statement*/
return;
}

Expand Down
2 changes: 1 addition & 1 deletion Compiler/testdata/parser5/CorrectGrammar1.sc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error
19
20
2 changes: 1 addition & 1 deletion Compiler/testdata/parser5/CorrectGrammar3.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void main ( String[] args)
}
}

;( oO ); /*semantic error - oO is undefined*/
;( oO ); /*semantic error - oO is undefined and no expression statement*/

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
2 changes: 1 addition & 1 deletion Compiler/testdata/parser5/CorrectGrammar3.sc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error
18
19
2 changes: 1 addition & 1 deletion Compiler/testdata/pw-tests/correct_2.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public __0_ _0__ (_0I_ _oO0) { /* semantic error 2x: _OI_ and __0_ is not define
{
{
{
_._; /* semantic error first _ is a variable of array of [] */
_._; /* semantic error first _ is a variable of array of [] and no expression statement */
}
_._((((this = _ * this))), new _[_][]); /* maybe an error, but i can't read this*/
}
Expand Down
2 changes: 1 addition & 1 deletion Compiler/testdata/pw-tests/correct_2.sc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error
14
15
2 changes: 1 addition & 1 deletion Compiler/testdata/semantic5/expressions_errors.sc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error
38
39
2 changes: 1 addition & 1 deletion Compiler/testdata/semantic5/names_errors.sc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error
19
21
48 changes: 25 additions & 23 deletions Compiler/tests/compiler/semantic/DeepCheckingVisitorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import compiler.utils.TestUtils;

public class DeepCheckingVisitorTest {

private HashMap<Symbol, ClassScope> classScopes = new HashMap<Symbol, ClassScope>();
private final DeepCheckingVisitor visitor = new DeepCheckingVisitor(classScopes);

Expand Down Expand Up @@ -48,21 +48,23 @@ public void testFromString() throws IOException, ParsingFailedException {

parser = TestUtils.initParser("class Class { public static void main(String[] args) {} public void function(Class param) { paramA; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertEquals(2, errors.size());
assertNotNull(errors.get(0));
assertNotNull(errors.get(1));

parser = TestUtils.initParser("class Class { public static void main(String[] args) {} public void function(Class param) { param.asdf; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertEquals(2, errors.size());
assertNotNull(errors.get(0));
assertNotNull(errors.get(1));

parser = TestUtils
.initParser("class Class { public int memberInt; public static void main(String[] args) {} public void function(Class param) { param.memberInt; } }");
.initParser("class Class { public int memberInt; public static void main(String[] args) {} public void function(Class param) { param.memberInt=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(0, errors.size());

parser = TestUtils
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { param.memberClass.memberClass.asdf; } }");
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { param.memberClass.memberClass.asdf=null; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));
Expand All @@ -74,13 +76,13 @@ public void testFromString() throws IOException, ParsingFailedException {
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { int locVarInt; locVarInt.asdf; } }");
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { int locVarInt; locVarInt.asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { Class locVarClass; locVarClass.memberClass; } }");
.initParser("class Class { public Class memberClass; public static void main(String[] args) {} public void function(Class param) { Class locVarClass; locVarClass.memberClass=null; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(0, errors.size());

Expand All @@ -101,40 +103,40 @@ public void testFromString() throws IOException, ParsingFailedException {
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public void method() {} public static void main(String[] args) {} public void function(Class param) { param.method().asdf; } }");
.initParser("class Class { public void method() {} public static void main(String[] args) {} public void function(Class param) { param.method().asdf=null; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public int asdf; public Class method() { return null; } public static void main(String[] args) {} public void function(Class param) { param.method().asdf; } }");
.initParser("class Class { public int asdf; public Class method() { return null; } public static void main(String[] args) {} public void function(Class param) { param.method().asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(0, errors.size());

parser = TestUtils
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1).asdf; } }");
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1).asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(0, errors.size());

parser = TestUtils
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1, 1).asdf; } }");
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1, 1).asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1, 1).asdf; } }");
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function(Class param) { param.method(1, 1, 1).asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));

parser = TestUtils
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function() { this.asdf; this.method(12,12); } }");
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function() { this.asdf=1; this.method(12,12); } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(0, errors.size());

parser = TestUtils
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function() { this.asdf3; this.method(12,12).asdf; } }");
.initParser("class Class { public int asdf; public Class method(int a, int b) { return null; } public static void main(String[] args) {} public void function() { this.asdf3=1; this.method(12,12).asdf=1; } }");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());
assertNotNull(errors.get(0));
Expand Down Expand Up @@ -181,46 +183,46 @@ public void testFromString() throws IOException, ParsingFailedException {
assertEquals(1, errors.size());

parser = TestUtils
.initParser("class Main{public static void main(String[] vargs){vargs[5];}}");
.initParser("class Main{public static void main(String[] vargs){vargs[5]=null;}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(2, errors.size());

parser = TestUtils
.initParser("class Main{public static void main(String[] vargs){int a = a;}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());

parser = TestUtils
.initParser("class Main{public static void asdf(String[] vargs){return 0;}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(2, errors.size());

parser = TestUtils
.initParser("class Main{public void asdf; public static void main(String[] vargs){}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());

parser = TestUtils
.initParser("class Main{public void[] asdf() { return null; } public static void main(String[] vargs){}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());

parser = TestUtils
.initParser("class Main{public __0_ _0__ (_0I_ _oO0) { return null; } public static void main(String[] vargs){}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(2, errors.size());

parser = TestUtils
.initParser("class Main{public void asdf() { this.asdf(classA); } public static void main(String[] vargs){}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(1, errors.size());

parser = TestUtils
.initParser("class Main{public int asdf() { return this * 42; } public static void main(String[] vargs){}}");
errors = SemanticChecker.checkSemantic(parser.parse());
assertEquals(2, errors.size());
}

@Test
public void testVoidParams() throws IOException, ParsingFailedException {
Parser parser = TestUtils
Expand Down

0 comments on commit 140b946

Please sign in to comment.