def _rule_state_to_string(rule_state: RuleState, grammar: Grammar) -> Tuple[str, str, str]: rule = grammar.rule_at(rule_state.rule_index) key = rule.key processed_str = ' '.join(rule.symbols[:rule_state.num_processed]) unprocessed_str = ' '.join(rule.symbols[rule_state.num_processed:]) lookaheads_str = ' '.join( [str(symbol) for symbol in rule_state.lookaheads]) return f'{key}', f'{processed_str}⬤{unprocessed_str}', f'{lookaheads_str}'
def parse(tokens: List[Node], grammar: Grammar, table: ParseTable) -> Node: from cmaj.parser.table import Action assert table.num_rows > 0 stack: Stack = [] row = 0 tokens = tokens + [Node(Grammar.AUGMENTED_EOF)] token_index = 0 while True: token = tokens[token_index] action = table.action(row, token.key) if action is None: raise ParserError(f'Unexpected token: {tokens[token_index]!r}') elif action.key == Action.ACCEPT: break elif action.key == Action.SHIFT: stack.append((row, tokens[token_index])) row = action.index token_index += 1 elif action.key == Action.GOTO: row = action.index elif action.key == Action.REDUCE: rule_index = action.index rule = grammar.rule_at(rule_index) stack, row, nodes = _reduce_stack(stack, rule) node = _reduce_nodes(nodes, rule) stack.append((row, node)) action = table.action(row, node.key) assert action.key == Action.GOTO row = action.index else: raise ParserError(f'Unexpected parser action {action!r} for token: {tokens[token_index]!r}') if len(stack) != 1: raise ParserError(f'Found unprocessed tokens: {_to_symbols(stack)!r}') return stack[0][1]
def __init__(self, state: RuleState, grammar: Grammar) -> None: rule = grammar.rule_at(state.rule_index) self._key = rule.key self._unprocessed_symbols = rule.symbols[state.num_processed:]