Skip to content

Commit 798dfa8

Browse files
authored
Fix ranges and for loops (#5)
1 parent e6c9919 commit 798dfa8

File tree

3 files changed

+33
-26
lines changed

3 files changed

+33
-26
lines changed

semantic_listener.py

+22-26
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def get_resulting_type(
3737

3838

3939
class SemanticListener(MyParserListener):
40-
"""Checks break and continue statements, variable declarations,types and assignments."""
40+
"""Checks break and continue statements, variable declarations, types, assignments, etc."""
4141

4242
def __init__(self):
4343
self.nested_loop_counter = 0
@@ -46,43 +46,27 @@ def __init__(self):
4646
ParserRuleContext, Type | tuple | None
4747
] = {} # values should be either Type or (Type, int | None, int | None, ...)
4848

49-
# LOOP CHECKING
50-
5149
def enterForLoop(self, ctx: MyParser.ForLoopContext):
5250
self.nested_loop_counter += 1
51+
self.variables[ctx.getChild(1).getText()] = Type.INT
5352

5453
def exitForLoop(self, ctx: MyParser.ForLoopContext):
5554
self.nested_loop_counter -= 1
5655

56+
def exitRange(self, ctx: MyParser.RangeContext):
57+
children_types = {self.expr_type[ctx.getChild(i)] for i in [0, 2]}
58+
if children_types != {Type.INT}:
59+
ctx.parser.notifyErrorListeners(
60+
"Range bounds must be integers", ctx.getChild(1).getSymbol()
61+
)
62+
self.expr_type[ctx] = None
63+
5764
def enterWhileLoop(self, ctx: MyParser.WhileLoopContext):
5865
self.nested_loop_counter += 1
5966

6067
def exitWhileLoop(self, ctx: MyParser.WhileLoopContext):
6168
self.nested_loop_counter -= 1
6269

63-
def enterBreak(self, ctx: MyParser.BreakContext):
64-
if self.nested_loop_counter == 0:
65-
ctx.parser.notifyErrorListeners(
66-
"Break statement outside of loop", ctx.BREAK().getSymbol()
67-
)
68-
69-
def enterContinue(self, ctx: MyParser.ContinueContext):
70-
if self.nested_loop_counter == 0:
71-
ctx.parser.notifyErrorListeners(
72-
"Continue statement outside of loop", ctx.CONTINUE().getSymbol()
73-
)
74-
75-
# VARIABLES & TYPES CHECKING
76-
77-
def enterRange(self, ctx: MyParser.RangeContext):
78-
pass
79-
80-
def exitRange(self, ctx: MyParser.RangeContext):
81-
pass
82-
83-
def enterComparison(self, ctx: MyParser.ComparisonContext):
84-
pass
85-
8670
def exitComparison(self, ctx: MyParser.ComparisonContext):
8771
children_types = {self.expr_type[ctx.getChild(i)] for i in [0, 2]}
8872
if not (
@@ -194,6 +178,18 @@ def exitSpecialMatrixFunction(self, ctx: MyParser.SpecialMatrixFunctionContext):
194178
else:
195179
self.expr_type[ctx] = (Type.INT, *type_dimentions)
196180

181+
def enterBreak(self, ctx: MyParser.BreakContext):
182+
if self.nested_loop_counter == 0:
183+
ctx.parser.notifyErrorListeners(
184+
"Break statement outside of loop", ctx.BREAK().getSymbol()
185+
)
186+
187+
def enterContinue(self, ctx: MyParser.ContinueContext):
188+
if self.nested_loop_counter == 0:
189+
ctx.parser.notifyErrorListeners(
190+
"Continue statement outside of loop", ctx.CONTINUE().getSymbol()
191+
)
192+
197193
def exitVector(self, ctx: MyParser.VectorContext):
198194
elements = ctx.children[1::2]
199195
for i in range(1, len(elements)):

test_main.py

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def test_ast(n: int):
4646
("binary_operations", [7, 8, 14, 16, 17], "binary operation"),
4747
("comparisons", [7, 9], "comparison"),
4848
("compound_assignments", [10, 11, 12], "assignment"),
49+
("ranges", [9], "range"),
4950
],
5051
)
5152
def test_sem_errors(name: str, line_numbers: list[int], additional: str):

tests/semantic/input_ranges.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
for i = 1:4
2+
print i;
3+
4+
n = 10;
5+
for j = 1:n
6+
print j;
7+
8+
m = 2.0;
9+
for k = 1:m
10+
print k;

0 commit comments

Comments
 (0)