eval: remove utf8 encoding comment, to fix
[trinary.git] / digital_simulator / Parser.py
blob8dcef8d6012600f568a3c451dd4e95bd70e78717
2 # Parser.py
3 #
5 # Created by Antonio on 2/17/08.
6 # Trinary Research Project: Digital logic simulator
7 # Upon testing the first phase of this program, correctly defined programs generate
8 # no output.
11 from tokenizer import nextToken
12 from Keyword import *
13 from Token import *
14 from Trits import *
15 from Literal import *
16 from Identifier import *
17 from Port import *
18 from Entity import *
20 def compareIdentifiers(current, expected, infile):
21 '''compare current identifier with expected identifier. If they are equal then return
22 the next token. If they are not then an raise and exeption and exit the program.
23 '''
24 if not isinstance(current, Identifier):
25 raise "Expected '%s', found '%s'" % (expected, current)
26 else:
27 print "parsed: %s" % current #for debugging
28 return nextToken(infile)
30 def compareTokens(current, expected, infile):
31 '''compare token current with expected token. If they are equal then return the next
32 token, if they are not then an raise exeption and exit program.
33 '''
34 if not isinstance(current, Token) or current.name != expected.name:
35 raise "Expected '%s', found '%s'" % (expected, current)
36 else:
37 print "parsed: %s" % current #for debugging
38 return nextToken(infile)
40 def compareKeywords(current, expected, infile):
41 '''compare current keyword with expected keyword. If they are equal then return
42 the next token. If they are not then an raise and exeption and exit the program.
43 '''
44 if not isinstance(current, Keyword) or current.name != expected.name:
45 raise "Expected '%s', found '%s'" % (expected, current)
46 else:
47 print "parsed: %s" % current #for debugging
48 return nextToken(infile)
50 def printError(current, expected):
51 '''Function prints an error message and raises an exeption
52 '''
53 raise "Expected '%s', found '%s'\n" % (expected, current)
55 def parse_datatype(current, infile):
56 '''parse the datatype and return Trit object that identifies the datatype
57 '''
58 if isinstance (current, Keyword):
59 if current.name == "trit":
60 return (nextToken(infile), "trit", 0)
61 next = compareKeywords(current, Keyword("trit_vector"), infile)
63 valueOne = compareTokens(next, Token("("), infile)
65 if not isinstance(valueOne, Literal):
66 printError(valueOne, Literal("integer"))
67 elif valueOne.value <= 0:
68 printError(valueOne, Literal("greater than zero"))
69 valueTwo = nextToken(infile)
71 length = valueOne.value + 1
73 valueThree = compareTokens(valueTwo, Keyword("downto"), infile)
74 if not isinstance(valueThree, Literal):
75 printError(valueThree, Literal("integer"))
76 elif valueThree.value != 0:
77 printError(valueThree, Literal(0))
78 valueFour = nextToken(infile)
80 valueFive = compareTokens(valueFour, Token(")"), infile)
82 # construct datatype object for trit_vector and return it
83 # along with the next token
84 return (valueFive, "trit_vector", length)
86 printError(current, Keyword("trit|trit_vector"))
88 def parse_flow(current, infile):
89 '''identify the direction of the flow of the port
90 '''
91 if isinstance(current, Keyword):
92 if current.name == "in":
93 return (nextToken(infile), "in")
94 elif current.name == "out":
95 return (nextToken(infile), "out")
96 elif current.name == "inout":
97 return (nextToken(infile), "inout")
99 printError(current, Keyword("in|out|inout"))
101 def parse_port(next, infile, entity):
102 '''parse the port and return a 'port' object
104 names = []
106 while 1:
107 cont = compareIdentifiers(next, Identifier(" "), infile)
108 names.append(next.name)
109 if not isinstance(cont, Token) or cont.name != ",":
110 break
111 else:
112 next = nextToken(infile)
114 valueOne = compareTokens(cont, Token(":"), infile)
115 (valueTwo, flow) = parse_flow(valueOne, infile)
116 (valueThree, type, length) = parse_datatype(valueTwo, infile)
118 # store derived port information into Entity
119 for i in names:
120 if flow == "in":
121 entity.IN.append(Port.Port(i, Port.IN, type, length))
122 elif flow == "out":
123 entity.OUT.append(Port.Port(i, Port.OUT, type, length))
124 else:
125 entity.INOUT.append(Port.Port(i, Port.INOUT, type, length))
127 # recurse if there are more ports defined
128 if isinstance (valueThree, Token) and valueThree.name == ";":
129 return parse_port(nextToken(infile), infile, entity)
130 else:
131 return (valueThree, entity)
133 def parse_entitytype(current, infile, entity):
134 '''parse the type of the entity
136 value1 = compareKeywords(current, Keyword("port"), infile)
137 value2 = compareTokens(value1, Token("("), infile)
138 (value3, rtn) = parse_port(value2, infile, entity)
139 value4 = compareTokens(value3, Token(")"), infile)
141 return (value4, entity);
143 def parse_entity(current, infile):
144 '''Parse the entity'''
145 value1 = compareKeywords(current, Keyword("entity"), infile)
146 value2 = compareIdentifiers(value1, Identifier(" "), infile)
148 # create entity object
149 entity = Entity(value1.name, [])
151 value3 = compareKeywords(value2, Keyword("is"), infile)
152 (value4, rtn) = parse_entitytype(value3, infile, entity)
153 value5 = compareTokens(value4, Token(";"), infile)
154 value6 = compareKeywords(value5, Keyword("end"), infile)
155 value7 = compareIdentifiers(value6, Identifier(" "), infile)
157 # identifier names must match
158 if value6.name != value1.name:
159 printError(value6, value1)
161 value8 = compareTokens(value7, Token(";"), infile)
163 # return Entity object
164 return (value8, entity)
166 def parse_architecture(current, infile):
167 '''Parse the archtecture component.'''
168 value1 = compareKeywords(current, Keyword("architecture"), infile)
169 value2 = compareKeywords(value1, Keyword("dataflow"), infile)
170 value3 = compareKeywords(value2, Keyword("of"), infile)
171 value4 = compareIdentifiers(value3, Identifier(" "), infile)
173 archi = Architecture(value3.name)
175 value5 = compareKeywords(value4, Keyword("is"), infile)
176 value6 = compareKeywords(value5, Keyword("begin"), infile)
177 value7 = compareKeywords(value6, Keyword("end"), infile)
178 value8 = compareKeywords(value7, Keyword("dataflow"), infile)
179 value9 = compareTokens(value8, Token(";"), infile)
181 return (value9, archi)
183 def parse_program(current, infile):
184 '''parse the individual components of the program'''
185 while isinstance(current, Keyword):
186 if current.name == "entity":
187 (current, entity) = parse_entity(current, infile)
188 print "Parsed Entity: %s" % entity
189 elif current.name == "architecture":
190 (current, architecture) = parse_architecture(current, infile)
191 print "Parsed Architecture: %s" % architecture
193 def Parser(filename):
194 '''Parse a file into components.
195 Arguments (1): filename of the file to parse.
197 infile = file(filename, "r")
198 parse_program(nextToken(infile), infile)
200 if __name__ == "__main__":
201 Parser("testParser");