Skip to content

Commit 22b63d1

Browse files
authored
Merge pull request #1 from Timoite/parser_dev
Parser dev
2 parents ea00aa8 + 65df2d5 commit 22b63d1

2 files changed

Lines changed: 189 additions & 29 deletions

File tree

parse.py

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,170 @@ class Parser:
3636
def __init__(self, names, devices, network, monitors, scanner):
3737
"""Initialise constants."""
3838

39+
def _error(self, error_type, stopping_symbol):
40+
self.error_count += 1
41+
42+
def _name(self):
43+
name = ""
44+
while (self.symbol.type == self.scanner.STRING or self.symbol.type == self.scanner.INTEGER
45+
or self.symbol.type == self.scanner.UNDERSCORE):
46+
name = name + self.symbol.id
47+
self.symbol = self.scanner.get_symbol()
48+
if not (self.symbol.type == self.scanner.EQUALS or self.symbol.type == self.scanner.DASH):
49+
self._error()
50+
else:
51+
return name
52+
53+
def _portID(self):
54+
portID = ""
55+
if self.symbol.type == self.STRING:
56+
portID = portID + self.symbol.id
57+
self.symbol = self.scanner.get_symbol()
58+
if self.symbol.type == self.INTEGER:
59+
portID = portID + str(self.symbol.ID)
60+
self.symbol = self.scanner.get_symbol()
61+
if not (self.symbol.type == self.scanner.ARROW or self.symbol.type == self.scanner.EQUALS):
62+
self._error()
63+
else:
64+
return portID
65+
else:
66+
self._error()
67+
68+
def _signalID(self):
69+
deviceID = self._name()
70+
if self.symbol.type == self.scanner.DASH:
71+
self.symbol = self.scanner.get_symbol()
72+
portID = self._portID()
73+
return [deviceID, portID]
74+
else:
75+
if not self.symbol.type == self.scanner.COMMA:
76+
self._error()
77+
else:
78+
return [deviceID, ""] #Not quite sure what this needs to be yet?
79+
80+
def _devicetype(self):
81+
if self.symbol.type == self.scanner.DEVICE_TYPE:
82+
devicetype = self.symbol.id
83+
self.symbol = self.scanner.get_symbol()
84+
return devicetype
85+
else:
86+
self._error()
87+
88+
def _device(self):
89+
deviceID = self._name()
90+
if self.symbol.type == self.scanner.EQUALS:
91+
self.symbol = self.scanner.get_symbol()
92+
device = self._devicetype()
93+
if self.symbol.type == self.scanner.SLASH:
94+
self.symbol = self.scanner.get_symbol()
95+
if self.symbol.type == self.scanner.INTEGER:
96+
qualifier = self.symbol.ID()
97+
self.symbol = self.scanner.get_symbol()
98+
else:
99+
self.error()
100+
elif self.symbol.type == self.scanner.COMMA:
101+
self.symbol = self.scanner.get_symbol()
102+
qualifier = None
103+
else:
104+
self._error()
105+
else:
106+
self._error()
107+
if self.error_found == 0:
108+
error_type = self._make_device(device, deviceID, qualifier)
109+
if error_type != self.devices.NO_ERROR():
110+
self._error()
111+
112+
def _make_device(self, device, deviceID, qualifier):
113+
if device in ["AND", "OR", "NAND", "NOR", "XOR"]:
114+
error = self.devices.make_gate(deviceID, device, qualifier)
115+
elif device == "CLOCK":
116+
error = self.devices.make_clock(deviceID, qualifier)
117+
elif device == "SWITCH":
118+
error = self.devices.make_clock(deviceID, qualifier)
119+
elif device == "DTYPE":
120+
error = self.devices.make_d_type(deviceID)
121+
else:
122+
error = self.error()
123+
return error
124+
125+
126+
def _connection(self):
127+
connectionID = self._name()
128+
if self.symbol.type == self.scanner.EQUALS:
129+
self.symbol = self.scanner.get_symbol()
130+
signal1 = self._signalID()
131+
if self.symbol.type == self.scanner.ARROW:
132+
self.symbol = self.scanner.get_symbol()
133+
signal2 = self._signalID()
134+
else:
135+
self._error()
136+
else:
137+
self._error()
138+
if self.error_found == 0:
139+
error_type = self.network.make_connection(signal1[0], signal1[1], signal2[0], signal2[1])
140+
if error_type != self.network.NO_ERROR():
141+
self._error()
142+
143+
def _monitor(self):
144+
monitorID = self._name()
145+
if self.symbol.type == self.scanner.EQUALS:
146+
self.symbol = self.scanner.get_symbol()
147+
port = self._signalID()
148+
else:
149+
self._error()
150+
if self.error_found == 0:
151+
error_type = self.monitors.make_monitor(port[0], port[1])
152+
if error_type != self.monitors.NO_ERROR():
153+
self._error()
154+
155+
def _devices_list(self):
156+
if (self.symbol.type == self.scanner.KEYWORD and self.symbol.id == self.scanner.DEVICES_ID):
157+
self.symbol = self.scanner.get_symbol()
158+
self._device()
159+
while self.symbol.type == self.scanner.COMMA:
160+
self.symbol = self.scanner.get_symbol()
161+
self._device()
162+
if not self.symbol.type == self.scanner.KEYWORD:
163+
self._error()
164+
else:
165+
self._error()
166+
167+
def _connections_list(self):
168+
if (self.symbol.type == self.scanner.KEYWORD and self.symbol.id == self.scanner.CONNECTIONS_ID):
169+
self.symbol = self.scanner.get_symbol()
170+
self._connection()
171+
while self.symbol.type == self.scanner.COMMA:
172+
self.symbol = self.scanner.get_symbol()
173+
self._connection()
174+
if not self.symbol.type == self.scanner.KEYWORD:
175+
self._error()
176+
else:
177+
self._error()
178+
179+
def _monitors_list(self):
180+
if (self.symbol.type == self.scanner.KEYWORD and self.symbol.id == self.scanner.MONITORS_ID):
181+
self.symbol = self.scanner.get_symbol()
182+
self._monitor()
183+
while self.symbol.type == self.scanner.COMMA:
184+
self.symbol = self.scanner.get_symbol()
185+
self._monitor()
186+
if not (self.symbol.type == self.scanner.KEYWORD and self.symbol.id == self.scanner.END_ID):
187+
self._error()
188+
else:
189+
self._error()
190+
39191
def parse_network(self):
40-
"""Parse the circuit definition file."""
192+
self.error_count = 0
193+
self._devices_list()
194+
self._connections_list()
195+
self._monitors_list()
196+
if self.error_count == 0:
197+
"""Parse the circuit definition file."""
198+
return True
199+
else:
200+
return False
41201
# For now just return True, so that userint and gui can run in the
42202
# skeleton code. When complete, should return False when there are
43203
# errors in the circuit definition file.
44-
return True
204+
205+

scanner.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def __init__(self, path, names):
8080
self.names = names
8181
self.symbol_type_list = [self.KEYWORD, self.DEVICE_TYPE, self.STRING, self.INTEGER,
8282
self.COMMA, self.ARROW, self.EQUALS, self.SLASH, self.DASH, self.UNDERSCORE]
83-
self.keywords_list = ["DEVICES", "CONNECTIONS", "MONITORS"]
83+
self.keywords_list = ["DEVICES", "CONNECTIONS", "MONITORS", "END"]
8484
self.device_list = ["AND", "OR", "NAND", "NOR", "CLOCK", "SWITCH", "DTYPE"]
8585
[self.DEVICES_ID, self.CONNECTIONS_ID, self.MONITORS_ID, self.END_ID] = self.names.lookup(self.keywords_list)
8686
[self.AND_ID, self.OR_ID, self.NAND_ID, self.NOR_ID, self.CLOCK_ID, self.SWITCH_ID, self.DTYPE_ID] = self.names.lookup(self.device_list)
@@ -89,41 +89,43 @@ def __init__(self, path, names):
8989
def get_symbol(self):
9090
"""Translate the next sequence of characters into a symbol."""
9191
symbol = Symbol()
92-
self.skip_whitespace()
92+
self._skip_whitespace()
9393
if self.current_character == "#": # comment identifier
94-
self.skip_comment()
94+
self._skip_comment()
9595
if self.current_character.isalpha(): # string
96-
string = self.get_string()
96+
string = self._get_string()
9797
if string in self.keywords_list:
9898
symbol.type = self.KEYWORD
99+
elif string in self.device_list:
100+
symbol.type = self.DEVICE_TYPE
99101
else:
100102
symbol.type = self.STRING
101103
symbol.id = self.names.lookup(string)
102104
elif self.current_character.isdigit(): # integer
103-
symbol.id = self.get_integer()
105+
symbol.id = self._get_integer()
104106
symbol.type = self.INTEGER
105107
elif self.current_character == "=": # punctuation
106108
symbol.type = self.EQUALS
107-
self.advance()
109+
self._advance()
108110
elif self.current_character == "-":
109111
symbol.type = self.DASH
110-
self.advance()
112+
self._advance()
111113
elif self.current_character == "/":
112114
symbol.type = self.SLASH
113-
self.advance()
115+
self._advance()
114116
elif self.current_character == ",":
115117
symbol.type = self.COMMA
116-
self.advance()
118+
self._advance()
117119
elif self.current_character == ">":
118120
symbol.type = self.ARROW
119-
self.advance()
121+
self._advance()
120122
elif self.current_character == "_":
121123
symbol.type = self.UNDERSCORE
122-
self.advance()
124+
self._advance()
123125
elif self.current_character == "": # end of file
124126
symbol.type = self.EOF
125127
else: # not a valid character
126-
self.advance()
128+
self._advance()
127129
return symbol
128130

129131

@@ -135,21 +137,23 @@ def _skip_whitespace(self):
135137
if self.current_character not in [" ", "/n"]:
136138
exit = 1
137139

138-
def skip_comment(self):
140+
def _skip_comment(self):
141+
"""skip comment by detecting and remove the line starting with the comment symbol '#'"""
139142
exit = 0
140143
while exit == 0:
141-
self.advance()
144+
self._advance()
142145
if self.current_character == "#":
143-
self.advance()
146+
self._advance()
144147
exit = 1
145148

146-
def get_string(self):
149+
def _get_string(self):
150+
"""get the string (seperate by space)"""
147151
string = self.current_character
148152
exit = 0
149153
while exit == 0:
150-
self.advance()
154+
self._advance()
151155
if self.current_character == "#":
152-
self.skip_comment()
156+
self._skip_comment()
153157
elif self.current_character.isalpha():
154158
string = string + self.current_character
155159
else:
@@ -158,26 +162,21 @@ def get_string(self):
158162

159163

160164
def _get_integer(self):
161-
"""Extract the integer
162-
163-
Returns:
164-
_type_: _description_
165-
"""
165+
'''As with _get_string, but with digits instead of characters.'''
166166
integer = self.current_character
167167
exit = 0
168168
while exit == 0:
169-
self.advance()
169+
self._advance()
170170
if self.current_character == "#":
171-
self.skip_comment()
171+
self._skip_comment()
172172
elif self.current_character.isdigit():
173173
integer = integer + self.current_character
174174
else:
175175
exit = 1
176176
return integer
177-
# As with _get_string, but with digits instead of characters.
178177

179178
def _advance(self):
180-
'''Read the next character from the input file.'''
179+
'''Used to _advance to the next character when the current character has been analyzed.'''
181180
self.current_character = self.contents[0]
182181
self.contents = self.contents[1]
183182

0 commit comments

Comments
 (0)