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.

66 lines
2.2 KiB

  1. import logging
  2. from collections import defaultdict
  3. from ..utils import classify, classify_bool, bfs, fzset
  4. from ..common import GrammarError, is_terminal
  5. from .grammar_analysis import GrammarAnalyzer
  6. ACTION_SHIFT = 0
  7. class LALR_Analyzer(GrammarAnalyzer):
  8. def compute_lookahead(self):
  9. self.states = {}
  10. def step(state):
  11. lookahead = defaultdict(list)
  12. sat, unsat = classify_bool(state, lambda rp: rp.is_satisfied)
  13. for rp in sat:
  14. for term in self.FOLLOW.get(rp.rule.origin, ()):
  15. lookahead[term].append(('reduce', rp.rule))
  16. d = classify(unsat, lambda rp: rp.next)
  17. for sym, rps in d.items():
  18. rps = {rp.advance(sym) for rp in rps}
  19. for rp in set(rps):
  20. if not rp.is_satisfied and not is_terminal(rp.next):
  21. rps |= self.expand_rule(rp.next)
  22. lookahead[sym].append(('shift', fzset(rps)))
  23. yield fzset(rps)
  24. for k, v in lookahead.items():
  25. if len(v) > 1:
  26. if self.debug:
  27. logging.warn("Shift/reduce conflict for %s: %s. Resolving as shift.", k, v)
  28. for x in v:
  29. # XXX resolving shift/reduce into shift, like PLY
  30. # Give a proper warning
  31. if x[0] == 'shift':
  32. lookahead[k] = [x]
  33. for k, v in lookahead.items():
  34. if not len(v) == 1:
  35. raise GrammarError("Collision in %s: %s" %(k, v))
  36. self.states[state] = {k:v[0] for k, v in lookahead.items()}
  37. for _ in bfs([self.init_state], step):
  38. pass
  39. # --
  40. self.enum = list(self.states)
  41. self.enum_rev = {s:i for i,s in enumerate(self.enum)}
  42. self.states_idx = {}
  43. for s, la in self.states.items():
  44. la = {k:(ACTION_SHIFT, self.enum_rev[v[1]]) if v[0]=='shift'
  45. else (v[0], (v[1], len(v[1].expansion))) # Reduce
  46. for k,v in la.items()}
  47. self.states_idx[ self.enum_rev[s] ] = la
  48. self.init_state_idx = self.enum_rev[self.init_state]