Skip to content

Commit 50dee7e

Browse files
authored
Merge pull request #7 from IagoMendes/v2.3
Added variable types, strings and bools (also updated README and adde…
2 parents 04a4b90 + c48cf9d commit 50dee7e

File tree

6 files changed

+213
-30
lines changed

6 files changed

+213
-30
lines changed

Diff for: Classes/node.py

+123-22
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,77 @@ def __init__(self, value, children):
1717
self.children = children # 0 = left child & 1 = right child
1818

1919
def Evaluate(self):
20+
res0 = self.children[0].Evaluate()
21+
res1 = self.children[1].Evaluate()
22+
2023
if self.value == '+':
21-
return self.children[0].Evaluate() + self.children[1].Evaluate()
24+
if (res0[0] == res1[0]):
25+
return [res0[0], res0[1] + res1[1]]
26+
elif (res0[0] == "STRING" or res1[0] == "STRING"):
27+
raise NameError (f'Unable perform {res0[0]} + {res1[0]}')
28+
return ['INT', res0[1] + res1[1]]
29+
2230
elif self.value == '-':
23-
return self.children[0].Evaluate() - self.children[1].Evaluate()
31+
if (res0[0] == "STRING" or res1[0] == "STRING"):
32+
raise NameError (f'Unable perform {res0[0]} - {res1[0]}')
33+
return ['INT', res0[1] - res1[1]]
34+
2435
elif self.value == '/':
25-
return int(self.children[0].Evaluate() / self.children[1].Evaluate())
36+
if (res0[0] == "STRING" or res1[0] == "STRING"):
37+
raise NameError (f'Unable perform {res0[0]} / {res1[0]}')
38+
return ['INT', int(res0[1] / res1[1])]
39+
2640
elif self.value == '*':
27-
return self.children[0].Evaluate() * self.children[1].Evaluate()
41+
if (res0[0] == "STRING" or res1[0] == "STRING"):
42+
if (res0[0] == "BOOL"):
43+
if (res0[1] == 1):
44+
res0[1] = "true"
45+
else:
46+
res0[1] = "false"
47+
48+
if (res1[0] == "BOOL"):
49+
if (res1[1] == 1):
50+
res1[1] = "true"
51+
else:
52+
res1[1] = "false"
53+
54+
return ["STRING", str(res0[1]) + str(res1[1])]
55+
else:
56+
return ['INT', res0[1] * res1[1]]
57+
2858
elif self.value == '||':
29-
return self.children[0].Evaluate() or self.children[1].Evaluate()
59+
if (res0[1] or res1[1]):
60+
return ['BOOL', 1]
61+
else:
62+
return ['BOOL', 0]
63+
3064
elif self.value == '&&':
31-
return self.children[0].Evaluate() and self.children[1].Evaluate()
65+
if (res0[0] == "STRING" or res1[0] == "STRING"):
66+
raise NameError (f'Unable perform {res0[0]} && {res1[0]}')
67+
68+
if (res0[1] and res1[1]):
69+
return ['BOOL', 1]
70+
else:
71+
return ['BOOL', 0]
72+
3273
elif self.value == '==':
33-
return self.children[0].Evaluate() == self.children[1].Evaluate()
74+
if (res0[1] == res1[1]):
75+
return ['BOOL', 1]
76+
else:
77+
return ['BOOL', 0]
78+
3479
elif self.value == '<':
35-
return self.children[0].Evaluate() < self.children[1].Evaluate()
80+
if (res0[1] < res1[1]):
81+
return ['BOOL', 1]
82+
else:
83+
return ['BOOL', 0]
84+
3685
elif self.value == '>':
37-
return self.children[0].Evaluate() > self.children[1].Evaluate()
38-
86+
if (res0[1] > res1[1]):
87+
return ['BOOL', 1]
88+
else:
89+
return ['BOOL', 0]
90+
3991

4092
class UnOp(Node): # Single children
4193
def __init__(self, value):
@@ -44,19 +96,45 @@ def __init__(self, value):
4496

4597
def Evaluate(self):
4698
if self.value == '+':
47-
return self.children[0].Evaluate()
99+
return ['INT', self.children[0].Evaluate()[1]]
48100
elif self.value == '-':
49-
return - self.children[0].Evaluate()
101+
return ['INT', -self.children[0].Evaluate()[1]]
50102
elif self.value == '!':
51-
return not(self.children[0].Evaluate())
103+
if not(self.children[0].Evaluate()[1]):
104+
return ['BOOL', 1]
105+
else:
106+
return ['BOOL', 0]
107+
52108

53109
class IntVal(Node):
54110
def __init__(self, value):
55111
self.value = value
56112
self.children = None
57113

58114
def Evaluate(self):
59-
return self.value
115+
return ["INT", self.value]
116+
117+
118+
class BoolVal(Node):
119+
def __init__(self, value):
120+
self.value = value
121+
self.children = None
122+
123+
def Evaluate(self):
124+
if (self.value == "true"):
125+
return ["BOOL", 1]
126+
if (self.value == "false"):
127+
return ["BOOL", 0]
128+
129+
130+
class StringVal(Node):
131+
def __init__(self, value):
132+
self.value = value
133+
self.children = None
134+
135+
def Evaluate(self):
136+
return ["STRING", self.value]
137+
60138

61139
class NoOp(Node):
62140
def __init__(self):
@@ -65,19 +143,31 @@ def __init__(self):
65143
def Evaluate(self):
66144
pass
67145

146+
68147
class Identifier(Node):
69148
def __init__(self, value):
70149
self.value = value
71150

72151
def Evaluate(self):
73152
return table.getter(self.value)
74153

154+
75155
class Assignment(Node): # Two children
76-
def __init__(self, children):
77-
self.children = children # 0 = Identifier & 1 = Expression
156+
def __init__(self, children, value):
157+
self.children = children # 0 = Identifier & 1 = Expression/Type
158+
self.value = value
78159

79160
def Evaluate(self):
80-
table.setter(self.children[0], self.children[1].Evaluate())
161+
if (self.value == "::"):
162+
table.setter(self.children[0], self.children[1], None)
163+
164+
elif (self.value == "="):
165+
res = self.children[1].Evaluate()
166+
if (res[0] == table.getter(self.children[0])[0]):
167+
table.setter(self.children[0], res[0], res[1])
168+
else:
169+
raise NameError(f"Types for variable {self.children[0]} don't match")
170+
81171

82172
class Statement(Node):
83173
def __init__(self):
@@ -87,39 +177,50 @@ def Evaluate(self):
87177
for i in range(len(self.children)):
88178
self.children[i].Evaluate()
89179

180+
90181
class Print(Node): # Single children
91182
def __init__(self, children):
92183
self.children = [children] # 0 = child
93184

94185
def Evaluate(self):
95-
print(self.children[0].Evaluate())
186+
res = self.children[0].Evaluate()
187+
if (res[0] == "BOOL"):
188+
if (res[1] == 1):
189+
print(True)
190+
elif (res[1] == 0):
191+
print(False)
192+
else:
193+
print(self.children[0].Evaluate()[1])
194+
96195

97196
class Read(Node):
98197
def __init__(self):
99198
self.children = None
100199

101200
def Evaluate(self):
102201
self.value = int(input())
103-
return self.value
202+
return ['INT', self.value]
203+
104204

105205
class While(Node):
106206
def __init__(self, children):
107207
self.children = children # 0 = RelEx & 1 = Block
108208

109209
def Evaluate(self):
110-
while (self.children[0].Evaluate()):
210+
while (self.children[0].Evaluate()[1]):
111211
self.children[1].Evaluate()
112212

213+
113214
class If(Node):
114215
def __init__(self, children):
115216
self.children = children
116217

117218
def Evaluate(self):
118219
if (self.children[2] is None):
119-
if (self.children[0].Evaluate()):
220+
if (self.children[0].Evaluate()[1]):
120221
self.children[1].Evaluate()
121222
else:
122-
if (self.children[0].Evaluate()):
223+
if (self.children[0].Evaluate()[1]):
123224
self.children[1].Evaluate()
124225
else:
125226
self.children[2].Evaluate()

Diff for: Classes/parser.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from Classes.tokenizer import Tokenizer
2-
from Classes.node import IntVal, UnOp, BinOp, NoOp, Node, Assignment, Identifier, Statement, Print, Read, While, If
2+
from Classes.node import *
33

44
class Parser:
55
tokens = None
@@ -37,12 +37,27 @@ def parseCommand():
3737
if (not result):
3838
result = NoOp()
3939

40+
elif (Parser.tokens.actual.type == 'LOCAL'):
41+
Parser.tokens.selectNext()
42+
43+
if (Parser.tokens.actual.type == 'IDENTIFIER'):
44+
result = Assignment([Parser.tokens.actual.value, None], None)
45+
Parser.tokens.selectNext()
46+
47+
if (Parser.tokens.actual.type == 'COLON_I'):
48+
result.value = Parser.tokens.actual.value
49+
Parser.tokens.selectNext()
50+
51+
if (Parser.tokens.actual.type == 'INT' or Parser.tokens.actual.type == 'BOOL' or Parser.tokens.actual.type == 'STRING'):
52+
result.children[1] = Parser.tokens.actual.type
53+
Parser.tokens.selectNext()
54+
4055
elif (Parser.tokens.actual.type == 'IDENTIFIER'):
4156
iden = Parser.tokens.actual.value
4257
Parser.tokens.selectNext()
4358

4459
if (Parser.tokens.actual.type == 'EQUAL'):
45-
result = Assignment([iden, None])
60+
result = Assignment([iden, None], Parser.tokens.actual.value)
4661
Parser.tokens.selectNext()
4762

4863
if (Parser.tokens.actual.type == 'READ'):
@@ -197,10 +212,18 @@ def parseFactor():
197212
result = IntVal(int(Parser.tokens.actual.value))
198213
Parser.tokens.selectNext()
199214

215+
elif (Parser.tokens.actual.type == 'STRING'):
216+
result = StringVal(Parser.tokens.actual.value)
217+
Parser.tokens.selectNext()
218+
200219
elif (Parser.tokens.actual.type == 'IDENTIFIER'):
201220
result = Identifier(Parser.tokens.actual.value)
202221
Parser.tokens.selectNext()
203222

223+
elif (Parser.tokens.actual.type == 'TRUE' or Parser.tokens.actual.type == 'TRUE'):
224+
result = BoolVal(Parser.tokens.actual.value)
225+
Parser.tokens.selectNext()
226+
204227
elif (Parser.tokens.actual.type == 'MINUS' or Parser.tokens.actual.type == 'PLUS' or Parser.tokens.actual.type == "NOT"):
205228
result = UnOp(Parser.tokens.actual.value)
206229
Parser.tokens.selectNext()

Diff for: Classes/symbolTable.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# key: [type, value]
12
class SymbolTable:
23
def __init__(self):
34
self.table = {}
@@ -8,5 +9,13 @@ def getter(self, value):
89
else:
910
raise NameError('Tried to access unknown identifier')
1011

11-
def setter(self, key, value):
12-
self.table[key] = value
12+
def setter(self, key, varType, value):
13+
if (value == None):
14+
self.table[key] = [varType, None]
15+
16+
else:
17+
if (key in self.table):
18+
if (varType == self.table[key][0]):
19+
self.table[key][1] = value
20+
else:
21+
raise NameError(f"Expected definition for variable {key}")

Diff for: Classes/tokenizer.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"=": "EQUAL",
1212
"<": "LESSER",
1313
">": "GREATER",
14-
"!": "NOT"
14+
"!": "NOT",
15+
":": "COLON"
1516
}
1617

1718
keywords = {
@@ -21,7 +22,13 @@
2122
"else" : "ELSE",
2223
"elseif" : "ELSEIF",
2324
"while" : "WHILE",
24-
"end" : "END"
25+
"end" : "END",
26+
"local" : "LOCAL",
27+
"Int" : "INT",
28+
"Bool" : "BOOL",
29+
"String" : "STRING",
30+
"true" : "TRUE",
31+
"false" : "FALSE"
2532
}
2633

2734
class Tokenizer:
@@ -48,6 +55,10 @@ def selectNext(self):
4855
self.actual = Token("==", "EQUAL_I")
4956
self.position += 1
5057

58+
elif (self.origin[self.position] == ":"):
59+
self.actual = Token("::", "COLON_I")
60+
self.position += 1
61+
5162
elif (self.origin[self.position] == "&"):
5263
self.position += 1
5364

@@ -90,7 +101,18 @@ def selectNext(self):
90101
else:
91102
self.actual = Token(resToken, "IDENTIFIER")
92103

104+
elif (self.origin[self.position] == '"'):
105+
resToken = ""
106+
self.position += 1
107+
108+
while (self.position < len(self.origin) and self.origin[self.position] != '"'):
109+
resToken += self.origin[self.position]
110+
self.position += 1
111+
112+
self.position += 1
113+
self.actual = Token(resToken, "STRING")
114+
93115
else:
94116
raise NameError("Unknown token")
95-
96-
return
117+
118+
return

Diff for: Diagrams/diagrama6.png

101 KB
Loading

Diff for: README.md

+28
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,33 @@ EBNF:
8484
DIGIT = ( 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 );
8585

8686

87+
## Variable types and Strings v2.3.1
88+
89+
Syntactic diagram: https://github.com/IagoMendes/CompiladorJulia/blob/master/Diagrams/diagrama6.png
90+
91+
EBNF:
92+
93+
BLOCK = { COMMAND };
94+
COMMAND = ( LOCAL | ASSIGNMENT | PRINT | IF | WHILE );
95+
LOCAL = "local", IDENTIFIER, "::", TYPE;
96+
ASSIGNMENT = IDENTIFIER, “=”, ( RELEX | “readline()”);
97+
PRINT = “println”, “(“, RELEX, “)”;
98+
WHILE = “while”, RELEX, BLOCK, “end”;
99+
IF = “if”, RELEX, BLOCK, { ELSE | ELSEIF }, “end”;
100+
ELSEIF = “elseif”, RELEX, BLOCK, { ELSE | ELSEIF };
101+
ELSE = “else”, BLOCK;
102+
RELEX = EXPRESSION, { (“==” | “<” | “>”), EXPRESSION };
103+
EXPRESSION = TERM, { (“+” | “-” | “||”), TERM };
104+
TERM = FACTOR, { (“*” | “/” | “&&”), FACTOR };
105+
FACTOR = ( ( “+” | “-” | “!”), FACTOR) | NUMBER | BOOL | STRING | IDENTIFIER | “(“, RELEX, “)”;
106+
IDENTIFIER = LETTER, { LETTER | DIGIT | “_” };
107+
NUMBER = DIGIT, { DIGIT };
108+
LETTER = ( a | … | z | A | … | Z );
109+
DIGIT = ( 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 );
110+
TYPE = "Int" | "Bool" | "String";
111+
BOOL = "true" | "false";
112+
STRING = '"', {.*?}, '"';
113+
114+
87115
## Version Control
88116
v(Major).(Minor).(Build)

0 commit comments

Comments
 (0)