This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

74 rindas
2.4 KiB

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