@@ -1,6 +1,6 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
from typing import Dict, Iterable, Callable, Union, TypeVar, Tuple | |||||
from typing import Dict, Iterable, Callable, Union, TypeVar, Tuple, Any, List, Set | |||||
from .tree import Tree | from .tree import Tree | ||||
from .lexer import Token | from .lexer import Token | ||||
@@ -25,7 +25,10 @@ T = TypeVar('T') | |||||
class UnexpectedInput(LarkError): | class UnexpectedInput(LarkError): | ||||
line: int | |||||
column: int | |||||
pos_in_stream: int | pos_in_stream: int | ||||
state: Any | |||||
def get_context(self, text: str, span: int = ...): | def get_context(self, text: str, span: int = ...): | ||||
... | ... | ||||
@@ -41,12 +44,14 @@ class UnexpectedInput(LarkError): | |||||
class UnexpectedToken(ParseError, UnexpectedInput): | class UnexpectedToken(ParseError, UnexpectedInput): | ||||
pass | |||||
expected: List[str] | |||||
considered_rules: Set[str] | |||||
puppet: Any | |||||
accepts: List[str] | |||||
class UnexpectedCharacters(LexError, UnexpectedInput): | class UnexpectedCharacters(LexError, UnexpectedInput): | ||||
line: int | |||||
column: int | |||||
allowed: Set[str] | |||||
considered_tokens: Set[Any] | |||||
class VisitError(LarkError): | class VisitError(LarkError): | ||||
@@ -105,7 +105,7 @@ class UnexpectedCharacters(LexError, UnexpectedInput): | |||||
class UnexpectedToken(ParseError, UnexpectedInput): | class UnexpectedToken(ParseError, UnexpectedInput): | ||||
def __init__(self, token, expected, considered_rules=None, state=None, puppet=None): | |||||
def __init__(self, token, expected, considered_rules=None, state=None, puppet=None, accepts=None): | |||||
self.token = token | self.token = token | ||||
self.expected = expected # XXX str shouldn't necessary | self.expected = expected # XXX str shouldn't necessary | ||||
self.line = getattr(token, 'line', '?') | self.line = getattr(token, 'line', '?') | ||||
@@ -114,10 +114,11 @@ class UnexpectedToken(ParseError, UnexpectedInput): | |||||
self.state = state | self.state = state | ||||
self.pos_in_stream = getattr(token, 'pos_in_stream', None) | self.pos_in_stream = getattr(token, 'pos_in_stream', None) | ||||
self.puppet = puppet | self.puppet = puppet | ||||
self.accepts = accepts | |||||
message = ("Unexpected token %r at line %s, column %s.\n" | message = ("Unexpected token %r at line %s, column %s.\n" | ||||
"Expected one of: \n\t* %s\n" | "Expected one of: \n\t* %s\n" | ||||
% (token, self.line, self.column, '\n\t* '.join(self.expected))) | |||||
% (token, self.line, self.column, '\n\t* '.join(self.accepts or self.expected))) | |||||
super(UnexpectedToken, self).__init__(message) | super(UnexpectedToken, self).__init__(message) | ||||
@@ -62,9 +62,18 @@ class _Parser: | |||||
expected = [s for s in states[state].keys() if s.isupper()] | expected = [s for s in states[state].keys() if s.isupper()] | ||||
try: | try: | ||||
puppet = ParserPuppet(self, state_stack, value_stack, start, stream, set_state) | puppet = ParserPuppet(self, state_stack, value_stack, start, stream, set_state) | ||||
accepts = [] | |||||
for t in expected: | |||||
new_puppet = puppet.copy() | |||||
try: | |||||
new_puppet.feed_token(Token(t, '')) | |||||
except KeyError: | |||||
pass | |||||
else: | |||||
accepts.append(t) | |||||
except NameError: | except NameError: | ||||
puppet = None | |||||
raise UnexpectedToken(token, expected, state=state, puppet=puppet) | |||||
puppet = accepts = None | |||||
raise UnexpectedToken(token, expected, state=state, puppet=puppet, accepts=accepts) | |||||
def reduce(rule): | def reduce(rule): | ||||
size = len(rule.expansion) | size = len(rule.expansion) | ||||