Parser.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #
  2. # Parser.py
  3. #
  4. #
  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.
  9. #
  10. from tokenizer import nextToken
  11. from Keyword import *
  12. from Token import *
  13. from Trits import *
  14. from Literal import *
  15. from Identifier import *
  16. from Port import *
  17. from Entity import *
  18. def compareIdentifiers(current, expected, infile):
  19. '''compare current identifier with expected identifier. If they are equal then return
  20. the next token. If they are not then an raise and exeption and exit the program.
  21. '''
  22. if not isinstance(current, Identifier):
  23. raise "Expected '%s', found '%s'" % (expected, current)
  24. else:
  25. print "parsed: %s" % current #for debugging
  26. return nextToken(infile)
  27. def compareTokens(current, expected, infile):
  28. '''compare token current with expected token. If they are equal then return the next
  29. token, if they are not then an raise exeption and exit program.
  30. '''
  31. if not isinstance(current, Token) or current.name != expected.name:
  32. raise "Expected '%s', found '%s'" % (expected, current)
  33. else:
  34. print "parsed: %s" % current #for debugging
  35. return nextToken(infile)
  36. def compareKeywords(current, expected, infile):
  37. '''compare current keyword with expected keyword. If they are equal then return
  38. the next token. If they are not then an raise and exeption and exit the program.
  39. '''
  40. if not isinstance(current, Keyword) or current.name != expected.name:
  41. raise "Expected '%s', found '%s'" % (expected, current)
  42. else:
  43. print "parsed: %s" % current #for debugging
  44. return nextToken(infile)
  45. def printError(current, expected):
  46. '''Function prints an error message and raises an exeption
  47. '''
  48. raise "Expected '%s', found '%s'\n" % (expected, current)
  49. def parse_datatype(current, infile):
  50. '''parse the datatype and return Trit object that identifies the datatype
  51. '''
  52. if isinstance (current, Keyword):
  53. if current.name == "trit":
  54. return (nextToken(infile), "trit", 0)
  55. next = compareKeywords(current, Keyword("trit_vector"), infile)
  56. valueOne = compareTokens(next, Token("("), infile)
  57. if not isinstance(valueOne, Literal):
  58. printError(valueOne, Literal("integer"))
  59. elif valueOne.value <= 0:
  60. printError(valueOne, Literal("greater than zero"))
  61. valueTwo = nextToken(infile)
  62. length = valueOne.value + 1
  63. valueThree = compareTokens(valueTwo, Keyword("downto"), infile)
  64. if not isinstance(valueThree, Literal):
  65. printError(valueThree, Literal("integer"))
  66. elif valueThree.value != 0:
  67. printError(valueThree, Literal(0))
  68. valueFour = nextToken(infile)
  69. valueFive = compareTokens(valueFour, Token(")"), infile)
  70. # construct datatype object for trit_vector and return it
  71. # along with the next token
  72. return (valueFive, "trit_vector", length)
  73. printError(current, Keyword("trit|trit_vector"))
  74. def parse_flow(current, infile):
  75. '''identify the direction of the flow of the port
  76. '''
  77. if isinstance(current, Keyword):
  78. if current.name == "in":
  79. return (nextToken(infile), "in")
  80. elif current.name == "out":
  81. return (nextToken(infile), "out")
  82. elif current.name == "inout":
  83. return (nextToken(infile), "inout")
  84. printError(current, Keyword("in|out|inout"))
  85. def parse_port(next, infile, entity):
  86. '''parse the port and return a 'port' object
  87. '''
  88. names = []
  89. while 1:
  90. cont = compareIdentifiers(next, Identifier(" "), infile)
  91. names.append(next.name)
  92. if not isinstance(cont, Token) or cont.name != ",":
  93. break
  94. else:
  95. next = nextToken(infile)
  96. valueOne = compareTokens(cont, Token(":"), infile)
  97. (valueTwo, flow) = parse_flow(valueOne, infile)
  98. (valueThree, type, length) = parse_datatype(valueTwo, infile)
  99. # store derived port information into Entity
  100. for i in names:
  101. if flow == "in":
  102. entity.IN.append(Port.Port(i, Port.IN, type, length))
  103. elif flow == "out":
  104. entity.OUT.append(Port.Port(i, Port.OUT, type, length))
  105. else:
  106. entity.INOUT.append(Port.Port(i, Port.INOUT, type, length))
  107. # recurse if there are more ports defined
  108. if isinstance (valueThree, Token) and valueThree.name == ";":
  109. return parse_port(nextToken(infile), infile, entity)
  110. else:
  111. return (valueThree, entity)
  112. def parse_entitytype(current, infile, entity):
  113. '''parse the type of the entity
  114. '''
  115. value1 = compareKeywords(current, Keyword("port"), infile)
  116. value2 = compareTokens(value1, Token("("), infile)
  117. (value3, rtn) = parse_port(value2, infile, entity)
  118. value4 = compareTokens(value3, Token(")"), infile)
  119. return (value4, entity);
  120. def parse_entity(current, infile):
  121. '''Parse the entity'''
  122. value1 = compareKeywords(current, Keyword("entity"), infile)
  123. value2 = compareIdentifiers(value1, Identifier(" "), infile)
  124. # create entity object
  125. entity = Entity(value1.name, [])
  126. value3 = compareKeywords(value2, Keyword("is"), infile)
  127. (value4, rtn) = parse_entitytype(value3, infile, entity)
  128. value5 = compareTokens(value4, Token(";"), infile)
  129. value6 = compareKeywords(value5, Keyword("end"), infile)
  130. value7 = compareIdentifiers(value6, Identifier(" "), infile)
  131. # identifier names must match
  132. if value6.name != value1.name:
  133. printError(value6, value1)
  134. value8 = compareTokens(value7, Token(";"), infile)
  135. # return Entity object
  136. return (value8, entity)
  137. def parse_architecture(current, infile):
  138. '''Parse the archtecture component.'''
  139. value1 = compareKeywords(current, Keyword("architecture"), infile)
  140. value2 = compareKeywords(value1, Keyword("dataflow"), infile)
  141. value3 = compareKeywords(value2, Keyword("of"), infile)
  142. value4 = compareIdentifiers(value3, Identifier(" "), infile)
  143. archi = Architecture(value3.name)
  144. value5 = compareKeywords(value4, Keyword("is"), infile)
  145. value6 = compareKeywords(value5, Keyword("begin"), infile)
  146. value7 = compareKeywords(value6, Keyword("end"), infile)
  147. value8 = compareKeywords(value7, Keyword("dataflow"), infile)
  148. value9 = compareTokens(value8, Token(";"), infile)
  149. return (value9, archi)
  150. def parse_program(current, infile):
  151. '''parse the individual components of the program'''
  152. while isinstance(current, Keyword):
  153. if current.name == "entity":
  154. (current, entity) = parse_entity(current, infile)
  155. print "Parsed Entity: %s" % entity
  156. elif current.name == "architecture":
  157. (current, architecture) = parse_architecture(current, infile)
  158. print "Parsed Architecture: %s" % architecture
  159. def Parser(filename):
  160. '''Parse a file into components.
  161. Arguments (1): filename of the file to parse.
  162. '''
  163. infile = file(filename, "r")
  164. parse_program(nextToken(infile), infile)
  165. if __name__ == "__main__":
  166. Parser("testParser");