def _non_nullable_head(self, symbol): "Returns the non-nullable subset of the FIRST set of the given symbol." if symbol == '': return set_new() elif is_nonterminal(symbol): return [s for s in self._first[symbol] if s != ''] else: return set_new([symbol])
def _fill_table(self, nonterminal, terminal, production): """Adds the given production to the entry (nonterminal, terminal) of the parsing table.""" key = (nonterminal, terminal) if key not in self._parse_table: self._parse_table[key] = set_new() self._parse_table[key][id(production)] = production
def first(self, alpha): """Returns the FIRST set of a string alpha (FIRST(alpha)). A terminal symbol x is in FIRST(alpha) iff alpha =>* x... The empty string '' is in FIRST(alpha) iff alpha =>* ''""" first_set = set_new() self._build_first_seq(first_set, alpha) return first_set
def _build_table(self): "Builds the LL(1) parsing table." self._parse_table = {} for nonterminal in self.all_nonterminals(): for production in self.syntax[nonterminal]: follow = set_new() self._build_follow_seq(nonterminal, follow, production.rule) for terminal in follow: self._fill_table(nonterminal, terminal, production)
def _build_follow(self): "Builds a table that associates each nonterminal with its FOLLOW set." self._follow = {} for nonterminal in self.all_nonterminals(): self._follow[nonterminal] = set_new() self._follow['<start>'] = set_new(['EOF']) change = True while change: change = False for nonterminal in self.all_nonterminals(): for production in self.syntax[nonterminal]: for i in range(len(production.rule)): rule = production.rule[i] if not is_nonterminal(rule): continue beta = production.rule[i + 1:] if self._build_follow_seq(nonterminal, self._follow[rule], beta): change = True
def _build_first(self): """Builds a table that associates each nonterminal with its FIRST set.""" self._first = {} for nonterminal in self.all_nonterminals(): self._first[nonterminal] = set_new() change = True while change: change = False for nonterminal in self.all_nonterminals(): for production in self.syntax[nonterminal]: if self._build_first_seq(self._first[nonterminal], production.rule): change = True
def push_env(self): "Push an empty environment into the stack of environment ribs." self.ribs.append(set_new())
def __init__(self, enable_errors): self.ribs = [set_new()] self.global_context = {} self.context = {} self.init_builtins() self.enable_errors = enable_errors