Skip to content

Commit a942e4e

Browse files
authored
Merge pull request #4 from IagoMendes/v2.2
merging v2.2
2 parents aa7967c + 9d0c853 commit a942e4e

File tree

5 files changed

+209
-18
lines changed

5 files changed

+209
-18
lines changed

Diff for: Classes/node.py

+44-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ def Evaluate(self):
2525
return int(self.children[0].Evaluate() / self.children[1].Evaluate())
2626
elif self.value == '*':
2727
return self.children[0].Evaluate() * self.children[1].Evaluate()
28+
elif self.value == '||':
29+
return self.children[0].Evaluate() or self.children[1].Evaluate()
30+
elif self.value == '&&':
31+
return self.children[0].Evaluate() and self.children[1].Evaluate()
32+
elif self.value == '==':
33+
return self.children[0].Evaluate() == self.children[1].Evaluate()
34+
elif self.value == '<':
35+
return self.children[0].Evaluate() < self.children[1].Evaluate()
36+
elif self.value == '>':
37+
return self.children[0].Evaluate() > self.children[1].Evaluate()
38+
2839

2940
class UnOp(Node): # Single children
3041
def __init__(self, value):
@@ -36,6 +47,8 @@ def Evaluate(self):
3647
return self.children[0].Evaluate()
3748
elif self.value == '-':
3849
return - self.children[0].Evaluate()
50+
elif self.value == '!':
51+
return not(self.children[0].Evaluate())
3952

4053
class IntVal(Node):
4154
def __init__(self, value):
@@ -80,4 +93,34 @@ def __init__(self, children):
8093

8194
def Evaluate(self):
8295
print(self.children[0].Evaluate())
83-
96+
97+
class Read(Node):
98+
def __init__(self):
99+
self.children = None
100+
101+
def Evaluate(self):
102+
self.value = int(input())
103+
return self.value
104+
105+
class While(Node):
106+
def __init__(self, children):
107+
self.children = children # 0 = RelEx & 1 = Block
108+
109+
def Evaluate(self):
110+
while (self.children[0].Evaluate()):
111+
self.children[1].Evaluate()
112+
113+
class If(Node):
114+
def __init__(self, children):
115+
self.children = children
116+
117+
def Evaluate(self):
118+
if (self.children[2] is None):
119+
if (self.children[0].Evaluate()):
120+
self.children[1].Evaluate()
121+
else:
122+
if (self.children[0].Evaluate()):
123+
self.children[1].Evaluate()
124+
else:
125+
self.children[2].Evaluate()
126+

Diff for: Classes/parser.py

+98-10
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
2+
from Classes.node import IntVal, UnOp, BinOp, NoOp, Node, Assignment, Identifier, Statement, Print, Read, While, If
33

44
class Parser:
55
tokens = None
@@ -14,7 +14,8 @@ def run(code):
1414
@staticmethod
1515
def parseBlock():
1616
stat = Statement()
17-
while (Parser.tokens.actual.type != "EOF"):
17+
while (Parser.tokens.actual.type != "EOF" and Parser.tokens.actual.type != "END"
18+
and Parser.tokens.actual.type != "ELSE" and Parser.tokens.actual.type != "ELSEIF"):
1819
stat.children.append(Parser.parseCommand())
1920

2021
return stat
@@ -35,15 +36,27 @@ def parseCommand():
3536
if (Parser.tokens.actual.type == 'EQUAL'):
3637
result = Assignment([iden, None])
3738
Parser.tokens.selectNext()
38-
result.children[1] = Parser.parseExpression()
39+
40+
if (Parser.tokens.actual.type == 'READ'):
41+
Parser.tokens.selectNext()
42+
if (Parser.tokens.actual.type == 'OPEN_P'):
43+
Parser.tokens.selectNext()
44+
result.children[1] = Read()
45+
46+
if (Parser.tokens.actual.type == 'CLOSE_P'):
47+
Parser.tokens.selectNext()
48+
else:
49+
raise NameError("Expected to Close Parenthesis")
50+
else:
51+
result.children[1] = Parser.parseRelExpression()
3952
else:
4053
raise NameError('Expected "=", received ' + Parser.tokens.actual.type)
4154

4255
elif (Parser.tokens.actual.type == 'PRINT'):
4356
Parser.tokens.selectNext()
4457
if (Parser.tokens.actual.type == 'OPEN_P'):
4558
Parser.tokens.selectNext()
46-
result = Print(Parser.parseExpression())
59+
result = Print(Parser.parseRelExpression())
4760

4861
if (Parser.tokens.actual.type == 'CLOSE_P'):
4962
Parser.tokens.selectNext()
@@ -52,18 +65,93 @@ def parseCommand():
5265
else:
5366
raise NameError("Expected Parenthesis")
5467

68+
elif (Parser.tokens.actual.type == 'WHILE'):
69+
Parser.tokens.selectNext()
70+
result = While([Parser.parseRelExpression(), None])
71+
72+
if (Parser.tokens.actual.type == 'LINE_END'):
73+
Parser.tokens.selectNext()
74+
result.children[1] = Parser.parseBlock()
75+
76+
if (Parser.tokens.actual.type == 'END'):
77+
Parser.tokens.selectNext()
78+
if (Parser.tokens.actual.type == 'LINE_END'):
79+
Parser.tokens.selectNext()
80+
else:
81+
raise NameError("Expected End")
82+
83+
elif (Parser.tokens.actual.type == 'IF'):
84+
Parser.tokens.selectNext()
85+
result = If([Parser.parseRelExpression(), None, None])
86+
87+
if (Parser.tokens.actual.type == 'LINE_END'):
88+
Parser.tokens.selectNext()
89+
atual = 0
90+
result.children[1] = Parser.parseBlock()
91+
92+
if (Parser.tokens.actual.type == 'ELSEIF'):
93+
while(Parser.tokens.actual.type == "ELSEIF"):
94+
Parser.tokens.selectNext()
95+
newIf = If([Parser.parseRelExpression(), None, None])
96+
97+
if (Parser.tokens.actual.type == 'LINE_END'):
98+
Parser.tokens.selectNext()
99+
newIf.children[1] = Parser.parseBlock()
100+
101+
if (atual == 0):
102+
result.children[2] = newIf
103+
atual = newIf
104+
else:
105+
atual.children[2] = newIf
106+
atual = newIf
107+
108+
if (Parser.tokens.actual.type == 'ELSE'):
109+
Parser.tokens.selectNext()
110+
if (Parser.tokens.actual.type == 'LINE_END'):
111+
Parser.tokens.selectNext()
112+
if (atual == 0):
113+
result.children[2] = Parser.parseBlock()
114+
else:
115+
atual.children[2] = Parser.parseBlock()
116+
117+
if (Parser.tokens.actual.type == 'END'):
118+
Parser.tokens.selectNext()
119+
if (Parser.tokens.actual.type == 'LINE_END'):
120+
Parser.tokens.selectNext()
121+
122+
else:
123+
raise NameError("Expected End, Else or Elseif")
124+
55125
else:
56126
raise NameError(f"Unexpected token {Parser.tokens.actual.type}")
57127

58128
return result
59129

130+
@staticmethod
131+
def parseRelExpression():
132+
result = Parser.parseExpression()
133+
134+
if (Parser.tokens.actual != None):
135+
while (Parser.tokens.actual.type == "EQUAL_I" or Parser.tokens.actual.type == "LESSER" or Parser.tokens.actual.type == "GREATER"):
136+
if (Parser.tokens.actual.type == "EQUAL_I" or Parser.tokens.actual.type == "LESSER" or Parser.tokens.actual.type == "GREATER"):
137+
result = BinOp(Parser.tokens.actual.value, [result, None])
138+
139+
Parser.tokens.selectNext()
140+
result.children[1] = Parser.parseExpression() # Right Child
141+
142+
else:
143+
raise NameError(f"Got type {Parser.tokens.actual.type} when expecting <, > or ==")
144+
else:
145+
raise NameError(f"Invalid Syntax")
146+
return result
147+
60148
@staticmethod
61149
def parseExpression():
62150
result = Parser.parseTerm()
63151

64152
if (Parser.tokens.actual != None):
65-
while (Parser.tokens.actual.type == "PLUS" or Parser.tokens.actual.type == "MINUS"):
66-
if (Parser.tokens.actual.type == 'PLUS' or Parser.tokens.actual.type == 'MINUS'):
153+
while (Parser.tokens.actual.type == "PLUS" or Parser.tokens.actual.type == "MINUS" or Parser.tokens.actual.type == "OR"):
154+
if (Parser.tokens.actual.type == 'PLUS' or Parser.tokens.actual.type == 'MINUS' or Parser.tokens.actual.type == "OR"):
67155
result = BinOp(Parser.tokens.actual.value, [result, None])
68156

69157
Parser.tokens.selectNext()
@@ -80,8 +168,8 @@ def parseTerm():
80168
result = Parser.parseFactor()
81169

82170
if (Parser.tokens.actual != None):
83-
while (Parser.tokens.actual.type == "MULT" or Parser.tokens.actual.type == "DIV"):
84-
if (Parser.tokens.actual.type == 'MULT' or Parser.tokens.actual.type == 'DIV'):
171+
while (Parser.tokens.actual.type == "MULT" or Parser.tokens.actual.type == "DIV" or Parser.tokens.actual.type == "AND"):
172+
if (Parser.tokens.actual.type == 'MULT' or Parser.tokens.actual.type == 'DIV' or Parser.tokens.actual.type == "AND"):
85173
result = BinOp(Parser.tokens.actual.value, [result, None])
86174

87175
Parser.tokens.selectNext()
@@ -105,14 +193,14 @@ def parseFactor():
105193
result = Identifier(Parser.tokens.actual.value)
106194
Parser.tokens.selectNext()
107195

108-
elif (Parser.tokens.actual.type == 'MINUS' or Parser.tokens.actual.type == 'PLUS'):
196+
elif (Parser.tokens.actual.type == 'MINUS' or Parser.tokens.actual.type == 'PLUS' or Parser.tokens.actual.type == "NOT"):
109197
result = UnOp(Parser.tokens.actual.value)
110198
Parser.tokens.selectNext()
111199
result.children[0] = Parser.parseFactor()
112200

113201
elif (Parser.tokens.actual.type == 'OPEN_P'):
114202
Parser.tokens.selectNext()
115-
result = Parser.parseExpression()
203+
result = Parser.parseRelExpression()
116204

117205
if (Parser.tokens.actual.type == 'CLOSE_P'):
118206
Parser.tokens.selectNext()

Diff for: Classes/tokenizer.py

+43-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@
88
"(": "OPEN_P",
99
")": "CLOSE_P",
1010
"\n": "LINE_END",
11-
"=": "EQUAL"
11+
"=": "EQUAL",
12+
"<": "LESSER",
13+
">": "GREATER",
14+
"!": "NOT"
15+
}
16+
17+
keywords = {
18+
"println" : "PRINT",
19+
"readline" : "READ",
20+
"if" : "IF",
21+
"else" : "ELSE",
22+
"elseif" : "ELSEIF",
23+
"while" : "WHILE",
24+
"end" : "END"
1225
}
1326

1427
class Tokenizer:
@@ -18,18 +31,41 @@ def __init__(self, origin):
1831
self.actual = None
1932

2033
def selectNext(self):
21-
2234
if (self.position == len(self.origin)):
2335
self.actual = Token('', 'EOF')
2436
return
2537

26-
elif (self.origin[self.position].isspace()):
38+
elif (self.origin[self.position] == " "):
2739
self.position += 1
2840
self.selectNext()
2941

3042
elif (self.origin[self.position] in tokens):
3143
self.actual = Token(self.origin[self.position], tokens[self.origin[self.position]])
32-
self.position += 1
44+
self.position += 1
45+
46+
if (self.position < len(self.origin)):
47+
if (self.origin[self.position] == "="):
48+
self.actual = Token("==", "EQUAL_I")
49+
self.position += 1
50+
51+
elif (self.origin[self.position] == "&"):
52+
self.position += 1
53+
54+
if (self.position < len(self.origin)):
55+
if (self.origin[self.position] == "&"):
56+
self.actual = Token("&&", "AND")
57+
self.position += 1
58+
else:
59+
raise NameError("Error with character '&'")
60+
61+
elif (self.origin[self.position] == "|"):
62+
self.position += 1
63+
if (self.position < len(self.origin)):
64+
if (self.origin[self.position] == "|"):
65+
self.actual = Token("||", "OR")
66+
self.position += 1
67+
else:
68+
raise NameError("Error with character '|'")
3369

3470
elif (self.origin[self.position].isnumeric()):
3571
resToken = ""
@@ -49,12 +85,12 @@ def selectNext(self):
4985
resToken += self.origin[self.position]
5086
self.position += 1
5187

52-
if resToken == "println":
53-
self.actual = Token(resToken, "PRINT")
88+
if resToken in keywords:
89+
self.actual = Token(resToken, keywords[resToken])
5490
else:
5591
self.actual = Token(resToken, "IDENTIFIER")
5692

5793
else:
5894
raise NameError("Unknown token")
59-
95+
6096
return

Diff for: Diagrams/diagrama5.png

77.6 KB
Loading

Diff for: README.md

+24
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,29 @@ EBNF:
6060
DIGIT = ( 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 ) ;
6161

6262

63+
## If, While and logical operations (!, &&, ||, ==, >, <) v2.2.1
64+
65+
Syntactic diagram: https://github.com/IagoMendes/CompiladorJulia/blob/master/Diagrams/diagrama5.png
66+
67+
EBNF:
68+
69+
BLOCK = { COMMAND };
70+
COMMAND = ( ASSIGNMENT | PRINT | IF | WHILE );
71+
ASSIGNMENT = IDENTIFIER, “=”, ( RELEX | “readline()”);
72+
PRINT = “println”, “(“, RELEX, “)”;
73+
WHILE = “while”, RELEX, BLOCK, “end”;
74+
IF = “if”, RELEX, BLOCK, { ELSE | ELSEIF }, “end”;
75+
ELSEIF = “elseif”, RELEX, BLOCK, { ELSE | ELSEIF };
76+
ELSE = “else”, BLOCK;
77+
RELEX = EXPRESSION, { (“==” | “<” | “>”), EXPRESSION };
78+
EXPRESSION = TERM, { (“+” | “-” | “||”), TERM };
79+
TERM = FACTOR, { (“*” | “/” | “&&”), FACTOR };
80+
FACTOR = ( ( “+” | “-” | “!”), FACTOR) | NUMBER | IDENTIFIER | “(“, RELEX, “)”;
81+
IDENTIFIER = LETTER, { LETTER | DIGIT | “_” };
82+
NUMBER = DIGIT, { DIGIT };
83+
LETTER = ( a | … | z | A | … | Z );
84+
DIGIT = ( 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 );
85+
86+
6387
## Version Control
6488
v(Major).(Minor).(Build)

0 commit comments

Comments
 (0)