This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.8 KiB

  1. from ..utils import classify, classify_bool, bfs, fzset
  2. from ..common import GrammarError, is_terminal
  3. from lalr_analysis import Rule, RulePtr, GrammarAnalyzer
  4. class Item:
  5. def __init__(self, rule_ptr, start):
  6. self.rule_ptr = rule_ptr
  7. self.start = start
  8. @property
  9. def expect(self):
  10. return self.rule_ptr.next
  11. @property
  12. def is_complete(self):
  13. return self.rule_ptr.is_satisfied
  14. def advance(self):
  15. return Item(self.rule_ptr.advance(self.expect), self.start)
  16. def __eq__(self, other):
  17. return self.rule_ptr == other.rule_ptr and self.start == other.start
  18. def __hash__(self):
  19. return hash((self.rule_ptr, self.start))
  20. def __repr__(self):
  21. return '%s (%s)' % (self.rule_ptr, self.start)
  22. class Parser:
  23. def __init__(self, rules, start):
  24. self.analyzer = GrammarAnalyzer(rules, start)
  25. self.start = start
  26. def parse(self, stream):
  27. # Define parser functions
  28. def predict(symbol, i):
  29. assert not is_terminal(symbol), symbol
  30. return {Item(rp, i) for rp in self.analyzer.expand_rule(symbol)}
  31. def scan(item, inp):
  32. if item.expect == inp: # TODO Do a smarter match, i.e. regexp
  33. return {item.advance()}
  34. else:
  35. return set()
  36. def complete(item, table):
  37. print "Complete:", item
  38. name = item.rule_ptr.rule.origin
  39. return {old_item.advance() for old_item in table[item.start]
  40. if old_item.expect == name}
  41. def process_column(i, char):
  42. cur_set = table[-1]
  43. next_set = set()
  44. table.append(next_set)
  45. to_process = cur_set
  46. while to_process:
  47. new_items = set()
  48. for item in to_process:
  49. if item.is_complete:
  50. new_items |= complete(item, table)
  51. else:
  52. if is_terminal(item.expect):
  53. next_set |= scan(item, char)
  54. else:
  55. new_items |= predict(item.expect, i)
  56. to_process = new_items - cur_set
  57. cur_set |= to_process
  58. # Main loop starts
  59. table = [predict(self.start, 0)]
  60. for i, char in enumerate(stream):
  61. process_column(i, char)
  62. process_column(len(stream), None)
  63. # rules = [
  64. # ('a', ['a', 'A']),
  65. # ('a', ['A']),
  66. # ]
  67. # p = Parser(rules, 'a')
  68. # p.parse('AAA')
  69. rules = [
  70. ('sum', ['sum', "A", 'product']),
  71. ('sum', ['product']),
  72. ('product', ['product', "M", 'factor']),
  73. ('product', ['factor']),
  74. ('factor', ['L', 'sum', 'R']),
  75. ('factor', ['number']),
  76. ('number', ['N', 'number']),
  77. ('number', ['N']),
  78. ]
  79. p = Parser(rules, 'sum')
  80. p.parse('NALNMNANR')