def P2(self): # 'name' is replaced in newSentence() return [ Production(None, self.callback, priority=self.priority, attributes=self.attributes) ]
class ProductionTestCase(unittest.TestCase): def setUp(self): # A -> B<b> C self.production = Production('A', self.callback) self.production.addSymbol('B', 'b') self.production.addSymbol('C') self.calls = list() def callback(self, grammar, **kwargs): self.calls.append(kwargs) return 42 def test_duplicate(self): try: self.production.addSymbol('D', 'b') except GrammarError: pass else: self.fail() def test_kwargs(self): cb, kwargs = self.production.apply([1, 2], None) cb(self, **kwargs) self.assertEqual(self.calls, [{'b': 1}])
def __addList(self, productions, prod, symbol, name, allowEmpty, sep): class ListSymbol(metaclass=Singleton): __reprval__ = 'List(%s, "%s")' % (symbol, '*' if allowEmpty else '+') if allowEmpty: clone = prod.cloned() self._wrapCallbackEmpty(name, clone) productions.append(clone) prod.addSymbol(ListSymbol, name=name) productions.append(prod) listProd = Production(ListSymbol, self._wrapCallbackOne()) listProd.addSymbol(symbol, name='item') productions.append(listProd) listProd = Production(ListSymbol, self._wrapCallbackNext()) listProd.addSymbol(ListSymbol, name='items') if sep is not None: listProd.addSymbol(sep) listProd.addSymbol(symbol, name='item') productions.append(listProd)
def prepare(cls, **kwargs): # pylint: disable=R0915 # Obviously cannot use @production here # When mixing async and sync parsers in the same program this may be called twice, # because AsyncProductionParser inherits from ProductionParser if cls.productions(): return # DECL -> identifier "->" PRODS prod = Production('DECL', cls.DECL) prod.addSymbol('LEFT', 'left') prod.addSymbol('arrow') prod.addSymbol('PRODS', 'prods') cls.__productions__.append(prod) # LEFT -> identifier prod = Production('LEFT', cls.LEFT) prod.addSymbol('identifier', 'name') cls.__productions__.append(prod) # LEFT -> identifier "<" posarg ">" prod = Production('LEFT', cls.LEFT) prod.addSymbol('identifier', 'name') prod.addSymbol('lchev') prod.addSymbol('identifier', 'posarg') prod.addSymbol('rchev') cls.__productions__.append(prod) # PRODS -> P prod = Production('PRODS', cls.PRODS1) prod.addSymbol('P', 'prodlist') cls.__productions__.append(prod) # PRODS -> PRODS "|" P prod = Production('PRODS', cls.PRODS2) prod.addSymbol('PRODS', 'prods') prod.addSymbol('union') prod.addSymbol('P', 'prodlist') cls.__productions__.append(prod) # P -> P SYM prod = Production('P', cls.P1) prod.addSymbol('P', 'prodlist') prod.addSymbol('SYM', 'sym') cls.__productions__.append(prod) # P -> ɛ prod = Production('P', cls.P2) cls.__productions__.append(prod) # SYM -> SYMNAME PROPERTIES prod = Production('SYM', cls.SYM) prod.addSymbol('SYMNAME', 'symname') prod.addSymbol('PROPERTIES', 'properties') cls.__productions__.append(prod) # SYM -> SYMNAME repeat PROPERTIES prod = Production('SYM', cls.SYMREP) prod.addSymbol('SYMNAME', 'symname') prod.addSymbol('repeat', 'repeat') prod.addSymbol('PROPERTIES', 'properties') cls.__productions__.append(prod) # SYM -> SYMNAME repeat lparen identifier rparen PROPERTIES prod = Production('SYM', cls.SYMREP) prod.addSymbol('SYMNAME', 'symname') prod.addSymbol('repeat', 'repeat') prod.addSymbol('lparen') prod.addSymbol('identifier', 'separator') prod.addSymbol('rparen') prod.addSymbol('PROPERTIES', 'properties') cls.__productions__.append(prod) # SYM -> SYMNAME repeat lparen litteral rparen PROPERTIES prod = Production('SYM', cls.SYMREP_LIT) prod.addSymbol('SYMNAME', 'symname') prod.addSymbol('repeat', 'repeat') prod.addSymbol('lparen') prod.addSymbol('litteral', 'separator') prod.addSymbol('rparen') prod.addSymbol('PROPERTIES', 'properties') cls.__productions__.append(prod) # SYMNAME -> identifier prod = Production('SYMNAME', cls.SYMNAME1) prod.addSymbol('identifier', 'identifier') cls.__productions__.append(prod) # SYMNAME -> litteral prod = Production('SYMNAME', cls.SYMNAME2) prod.addSymbol('litteral', 'litteral') cls.__productions__.append(prod) # PROPERTIES -> ɛ prod = Production('PROPERTIES', cls.PROPERTIES1) cls.__productions__.append(prod) # PROPERTIES -> lchev identifier rchev prod = Production('PROPERTIES', cls.PROPERTIES2) prod.addSymbol('lchev') prod.addSymbol('identifier', 'name') prod.addSymbol('rchev') cls.__productions__.append(prod) super().prepare(**kwargs)
def prepare(cls): for prod in cls.productions(): if prod.name is _StartState: break else: def acceptor(_, result): raise _Accept(result) prod = Production(_StartState, acceptor) prod.addSymbol(cls._defaultStartSymbol() if cls.startSymbol is None else cls.startSymbol, name='result') cls.__productions__.insert(0, prod) cls.startSymbol = _StartState super().prepare() states, goto = cls.__computeStates(prod) reachable = cls.__computeActions(states, goto) logger = logging.getLogger('LRParser') cls.__resolveConflicts(logger) usedTokens = set([ symbol for state, symbol in cls.__actions__.keys() if symbol is not EOF ]) if usedTokens != cls.tokenTypes(): # pragma: no cover logger.warning( 'The following tokens are not used: %s', ','.join([ repr(sym) for sym in sorted(cls.tokenTypes() - usedTokens) ])) if reachable != cls.nonterminals(): # pragma: no cover logger.warning( 'The following nonterminals are not reachable: %s', ','.join([ repr(sym) for sym in sorted(cls.nonterminals() - reachable) ])) # Reductions only need goto entries for nonterminals cls._goto = dict([((state, symbol), newState) for (state, symbol), newState in goto.items() if symbol not in cls.tokenTypes()]) parts = list() if cls.nSR: parts.append('%d shift/reduce conflicts' % cls.nSR) if cls.nRR: parts.append('%d reduce/reduce conflicts' % cls.nRR) if parts: logger.warning(', '.join(parts)) # Cast to tuple because sets are not totally ordered for index, state in enumerate([tuple(cls._startState)] + sorted( [tuple(state) for state in states if state != cls._startState])): logger.debug('State %d', index) for item in sorted(state): logger.debug(' %s', item) item.index = index cls.__lrstates__.append(sorted(state)) logger.info('%d states.', len(states))
def setUp(self): # A -> B<b> C self.production = Production('A', self.callback) self.production.addSymbol('B', 'b') self.production.addSymbol('C') self.calls = list()