diff --git a/src/parse.py b/src/parse.py index d85fe55..9a37535 100644 --- a/src/parse.py +++ b/src/parse.py @@ -10,6 +10,7 @@ TEST_TASK = enum.auto() # pragma: no mutate PARSE_NOTE = enum.auto() # pragma: no mutate CLEAR_NOTES = enum.auto() # pragma: no mutate + PARSE_TEXT = enum.auto() # pragma: no mutate PARSE_BOOL = enum.auto() # pragma: no mutate @@ -130,16 +131,17 @@ # The recursive descent parser in a wrapper class for easy testing class Parser: # Parses a text syntax node - def parse_text(self, stream): + def parse_text(self, stream, parent_context): + context = ParseContext(ParseTask.PARSE_TEXT, stream.peek(), parent_context) buffer = "" - s = read_token(stream, "StartText", None) + s = read_token(stream, "StartText", context) location = s.location # Parse following tokens while True: - s = read_token(stream, None, None) + s = read_token(stream, None, context) # Don't allow StartText in text if s.value in ["StartText"]: - raise ParseErrorException(ParseError.FOUND_STARTTEXT, s, None, None) + raise ParseErrorException(ParseError.FOUND_STARTTEXT, s, None, context) # EndText found, end things elif s.value == "EndText": break diff --git a/tests/parse/test_text.py b/tests/parse/test_text.py index f433698..11d559c 100644 --- a/tests/parse/test_text.py +++ b/tests/parse/test_text.py @@ -11,11 +11,14 @@ ) from src.parse import ( + ParseContext, ParseError, ParseErrorException, + ParseTask, Parser, ) from src.syntax import Syntax, SyntaxStream, SyntaxType +from tests.parse.test_parse import draw_parse_context from tests.test_syntax import ( draw_token_by_value, draw_syntax_random, @@ -65,7 +68,7 @@ def test_parse_text_valid(canary, test_data): (tokens, result) = test_data stream = SyntaxStream(tokens + [canary]) - parsed = Parser().parse_text(stream) + parsed = Parser().parse_text(stream, None) assert parsed is not None assert parsed == result assert stream.pop() == canary @@ -80,20 +83,23 @@ @composite def draw_syntax_text_invalid_nostarttext(draw): (tokens, _) = draw(draw_syntax_text_valid()) + parent_context = draw(draw_parse_context()) if draw(booleans()): token = draw(draw_syntax_random()) assume(not (token.type == SyntaxType.TOKEN and token.value == "StartText")) new_tokens = [token] + tokens[1:0] + context = ParseContext(ParseTask.PARSE_TEXT, new_tokens[0], parent_context) if token.type == SyntaxType.TOKEN: error = ParseErrorException( - ParseError.WRONG_TOKEN, token, "StartText", None + ParseError.WRONG_TOKEN, token, "StartText", context ) else: - error = ParseErrorException(ParseError.NOT_TOKEN, token, None, None) - return (new_tokens, error) + error = ParseErrorException(ParseError.NOT_TOKEN, token, None, context) + return (new_tokens, error, parent_context) else: - error = ParseErrorException(ParseError.NO_TOKEN, None, None, None) - return ([], error) + context = ParseContext(ParseTask.PARSE_TEXT, None, parent_context) + error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) + return ([], error, parent_context) # Generate text with invalid content tokens @@ -105,8 +111,10 @@ token = draw(draw_syntax_random()) assume(token.type != SyntaxType.TOKEN) new_tokens = insert_random(draw, tokens, token) - error = ParseErrorException(ParseError.NOT_TOKEN, token, None, None) - return (new_tokens, error) + parent_context = draw(draw_parse_context()) + context = ParseContext(ParseTask.PARSE_TEXT, new_tokens[0], parent_context) + error = ParseErrorException(ParseError.NOT_TOKEN, token, None, context) + return (new_tokens, error, parent_context) # Generate text with a StartText token in it @@ -117,8 +125,10 @@ (tokens, _) = draw(draw_syntax_text_valid()) start = draw(draw_token_by_value("StartText")) new_tokens = insert_random(draw, tokens, start) - error = ParseErrorException(ParseError.FOUND_STARTTEXT, start, None, None) - return (new_tokens, error) + parent_context = draw(draw_parse_context()) + context = ParseContext(ParseTask.PARSE_TEXT, new_tokens[0], parent_context) + error = ParseErrorException(ParseError.FOUND_STARTTEXT, start, None, context) + return (new_tokens, error, parent_context) # Generate text without EndText @@ -127,8 +137,10 @@ @composite def draw_syntax_text_invalid_noendtext(draw): (tokens, _) = draw(draw_syntax_text_valid()) - error = ParseErrorException(ParseError.NO_TOKEN, None, None, None) - return (tokens[0:-1], error) + parent_context = draw(draw_parse_context()) + context = ParseContext(ParseTask.PARSE_TEXT, tokens[0], parent_context) + error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) + return (tokens[0:-1], error, parent_context) # Generate an invalid text case @@ -146,10 +158,10 @@ # Test that parse_text errors in invalid cases @given(draw_syntax_text_invalid()) def test_parse_text_invalid(test_data): - (tokens, error) = test_data + (tokens, error, context) = test_data stream = SyntaxStream(tokens) try: - parsed = Parser().parse_text(stream) + parsed = Parser().parse_text(stream, context) raise AssertionError("Parsed invalid data: %s" % (parsed)) except ParseErrorException as e: assert e == error