@@ -186,6 +186,13 @@ class LineCounter: | |||||
self.column = 1 | self.column = 1 | ||||
self.line_start_pos = 0 | self.line_start_pos = 0 | ||||
def __eq__(self, other): | |||||
if not isinstance(other, LineCounter): | |||||
return False | |||||
return (self.newline_char == other.newline_char and self.char_pos == other.char_pos | |||||
and self.line == other.line and self.column == other.column | |||||
and self.line_start_pos == other.line_start_pos) | |||||
def feed(self, token, test_newline=True): | def feed(self, token, test_newline=True): | ||||
"""Consume a token and calculate the new line & column. | """Consume a token and calculate the new line & column. | ||||
@@ -405,6 +412,13 @@ class LexerState: | |||||
self.line_ctr = line_ctr | self.line_ctr = line_ctr | ||||
self.last_token = last_token | self.last_token = last_token | ||||
def __eq__(self, other): | |||||
if not isinstance(other, LexerState): | |||||
return False | |||||
return (self.text == other.text and self.line_ctr == other.line_ctr | |||||
and self.last_token == other.last_token) | |||||
def __copy__(self): | def __copy__(self): | ||||
return type(self)(self.text, copy(self.line_ctr), self.last_token) | return type(self)(self.text, copy(self.line_ctr), self.last_token) | ||||
@@ -465,4 +479,12 @@ class LexerThread: | |||||
def lex(self, parser_state): | def lex(self, parser_state): | ||||
return self.lexer.lex(self.state, parser_state) | return self.lexer.lex(self.state, parser_state) | ||||
def __copy__(self): | |||||
copied = type(self)( | |||||
self.lexer, | |||||
'' | |||||
) | |||||
copied.state = copy(self.state) | |||||
return copied | |||||
###} | ###} |
@@ -95,7 +95,7 @@ class ParserState(object): | |||||
def __eq__(self, other): | def __eq__(self, other): | ||||
if not isinstance(other, ParserState): | if not isinstance(other, ParserState): | ||||
return False | return False | ||||
return self.position == other.position | |||||
return len(self.state_stack) == len(other.state_stack) and self.position == other.position | |||||
def __copy__(self): | def __copy__(self): | ||||
return type(self)( | return type(self)( | ||||
@@ -2408,9 +2408,18 @@ def _make_parser_test(LEXER, PARSER): | |||||
# Skip comma | # Skip comma | ||||
return True | return True | ||||
elif e.token.type == 'SIGNED_NUMBER': | elif e.token.type == 'SIGNED_NUMBER': | ||||
# Make a copy and ensure it is properly made | |||||
puppet_copy = e.puppet.copy() | |||||
assert puppet_copy.parser_state == e.puppet.parser_state | |||||
assert puppet_copy.lexer_state.state == e.puppet.lexer_state.state | |||||
assert puppet_copy.parser_state is not e.puppet.parser_state | |||||
assert puppet_copy.lexer_state.state is not e.puppet.lexer_state.state | |||||
assert puppet_copy.lexer_state.state.line_ctr is not e.puppet.lexer_state.state.line_ctr | |||||
# Try to feed a comma and retry the number | # Try to feed a comma and retry the number | ||||
e.puppet.feed_token(Token('COMMA', ',')) | e.puppet.feed_token(Token('COMMA', ',')) | ||||
e.puppet.feed_token(e.token) | e.puppet.feed_token(e.token) | ||||
return True | return True | ||||
# Unhandled error. Will stop parse and raise exception | # Unhandled error. Will stop parse and raise exception | ||||