def init(self): bos = BOS(Terminal(""), 0, []) eos = EOS(FinishSymbol(), 0, []) bos.next_term = eos eos.prev_term = bos root = TextNode(Nonterminal("Root"), 0, [bos, eos]) self.parent = root
def __init__(self, start_symbol, grammar, lr_type=0): self.grammar = grammar self.start_symbol = start_symbol self.state_sets = [] self.edges = {} self.ids = {} self.todo = [] self.done = set() self.maybe_compatible = {} self.goto_time = 0 self.add_time = 0 self.closure_time = 0 self.closure_count = 0 self.addcount = 0 self.weakly = 0 self.weakly_count = 0 self.mergetime = 0 helper = Helper(grammar) self.helper = helper if lr_type == LR0: self.closure = helper.closure_0 self.goto = helper.goto_0 self.start_set = StateSet( [LR0Element(Production(None, [self.start_symbol]), 0)]) elif lr_type == LR1 or lr_type == LALR: self.closure = helper.closure_1 self.goto = helper.goto_1 self.start_set = StateSet() self.start_set.add( LR0Element(Production(None, [self.start_symbol]), 0), set([FinishSymbol()]))
def prepare_input(self, _input): l = [] # XXX need an additional lexer to do this right if _input != "": for i in _input.split(" "): l.append(Terminal(i)) l.append(FinishSymbol()) return l
def init_ast(self, magic_parent=None): bos = BOS(Terminal(""), 0, []) eos = EOS(FinishSymbol(), 0, []) bos.magic_parent = magic_parent eos.magic_parent = magic_parent bos.next_term = eos eos.prev_term = bos root = Node(Nonterminal("Root"), 0, [bos, eos]) self.previous_version = AST(root) root.save(0) bos.save(0) eos.save(0)
def check(self, _input): self.reset() l = [] # XXX need an additional lexer to do this right for i in _input.split(" "): l.append(Terminal(i)) l.append(FinishSymbol()) _input = l self.stack.append(FinishSymbol()) self.stack.append(0) i = 0 while i < len(_input): c = _input[i] state_id = self.stack[-1] element = self.syntaxtable.lookup(state_id, c) if element is None: return False if isinstance(element, Shift): self.stack.append(c) self.stack.append(element.action) i += 1 if isinstance(element, Reduce): for x in range(2 * element.amount()): self.stack.pop() state_id = self.stack[-1] self.stack.append(element.action.left) element = self.syntaxtable.lookup(state_id, element.action.left) assert isinstance(element, Goto) self.stack.append(element.action) if isinstance(element, Accept): return True
def get_ast(self): bos = Node(Terminal("bos"), 0, []) eos = Node(FinishSymbol(), 0, []) root = Node(Nonterminal("Root"), 0, [bos, self.ast_stack[0], eos]) return AST(root)
def inc_parse(self, line_indents=[], reparse=False): logging.debug("============ NEW INCREMENTAL PARSE ================= ") self.validating = False self.error_node = None self.stack = [] self.undo = [] self.current_state = 0 self.stack.append(Node(FinishSymbol(), 0, [])) bos = self.previous_version.parent.children[0] self.loopcount = 0 USE_OPT = True self.pm.do_incparse_inc_parse_top() la = self.pop_lookahead(bos) while (True): logging.debug("\x1b[35mProcessing\x1b[0m %s %s %s %s", la, la.changed, id(la), la.indent) self.loopcount += 1 if isinstance(la.symbol, Terminal) or isinstance( la.symbol, FinishSymbol) or la.symbol == Epsilon(): if la.changed: assert False # with prelexing you should never end up here! else: lookup_symbol = self.get_lookup(la) result = self.parse_terminal(la, lookup_symbol) if result == "Accept": self.last_status = True return True elif result == "Error": self.last_status = False return False elif result != None: la = result else: # Nonterminal if la.changed or reparse: # deconstruct the #la.changed = False # as all nonterminals that have changed are being rebuild, there is no need to change this flag (this also solves problems with comments) self.undo.append((la, 'changed', True)) la = self.left_breakdown(la) else: if USE_OPT: #Follow parsing/syntax table goto = self.syntaxtable.lookup(self.current_state, la.symbol) if goto: # can we shift this Nonterminal in the current state? logging.debug("OPTShift: %s in state %s -> %s", la.symbol, self.current_state, goto) self.pm.do_incparse_optshift(la) follow_id = goto.action self.stack.append(la) la.state = follow_id #XXX this fixed goto error (I should think about storing the states on the stack instead of inside the elements) self.current_state = follow_id logging.debug("USE_OPT: set state to %s", self.current_state) la = self.pop_lookahead(la) self.validating = True continue else: #XXX can be made faster by providing more information in syntax tables first_term = la.find_first_terminal() lookup_symbol = self.get_lookup(first_term) element = self.syntaxtable.lookup( self.current_state, lookup_symbol) if isinstance(element, Reduce): self.reduce(element) else: la = self.left_breakdown(la) else: # PARSER WITHOUT OPTIMISATION if la.lookup != "": lookup_symbol = Terminal(la.lookup) else: lookup_symbol = la.symbol element = self.syntaxtable.lookup( self.current_state, lookup_symbol) if self.shiftable(la): logging.debug("\x1b[37mis shiftable\x1b[0m") self.stack.append(la) self.current_state = la.state self.right_breakdown() la = self.pop_lookahead(la) else: la = self.left_breakdown(la) logging.debug("============ INCREMENTAL PARSE END ================= ")