diff --git a/examples/README.md b/examples/README.md index 88d3bb0..3fbe3ea 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,6 +10,7 @@ ### Advanced +- [error\_reporting\_lalr.py](error_reporting_lalr.py) - A demonstration of example-driven error reporting with the LALR parser - [python\_parser.py](python_parser.py) - A fully-working Python 2 & 3 parser (but not production ready yet!) - [conf.py](conf.py) - Demonstrates the power of LALR's contextual lexer on a toy configuration language - [reconstruct\_json.py](reconstruct_json.py) - Demonstrates the experimental text-reconstruction feature diff --git a/examples/error_reporting_lalr.py b/examples/error_reporting_lalr.py new file mode 100644 index 0000000..a1055fd --- /dev/null +++ b/examples/error_reporting_lalr.py @@ -0,0 +1,81 @@ +# +# This demonstrates example-driven error reporting with the LALR parser +# + +from lark import Lark, UnexpectedToken + +from .json_parser import json_grammar # Using the grammar from the json_parser example + +json_parser = Lark(json_grammar, parser='lalr') + +class JsonSyntaxError(SyntaxError): + def __str__(self): + context, line, column = self.args + return '%s at line %s, column %s.\n\n%s' % (self.label, line, column, context) + +class JsonMissingValue(JsonSyntaxError): + label = 'Missing Value' + +class JsonMissingOpening(JsonSyntaxError): + label = 'Missing Opening' + +class JsonMissingClosing(JsonSyntaxError): + label = 'Missing Closing' + +class JsonMissingComma(JsonSyntaxError): + label = 'Missing Comma' + +class JsonTrailingComma(JsonSyntaxError): + label = 'Trailing Comma' + + +def parse(json_text): + try: + j = json_parser.parse(json_text) + except UnexpectedToken as ut: + exc_class = ut.match_examples(json_parser.parse, { + JsonMissingValue: ['{"foo": }'], + JsonMissingOpening: ['{"foo": ]}', + '{"foor": }}'], + JsonMissingClosing: ['{"foo": [}', + '{', + '{"a": 1', + '[1'], + JsonMissingComma: ['[1 2]', + '[false 1]', + '["b" 1]', + '{"a":true 1:4}', + '{"a":1 1:4}', + '{"a":"b" 1:4}'], + JsonTrailingComma: ['[,]', + '[1,]', + '[1,2,]', + '{"foo":1,}', + '{"foo":false,"bar":true,}'] + }) + if not exc_class: + raise + raise exc_class(ut.get_context(json_text), ut.line, ut.column) + + +def test(): + try: + parse('{"key":') + except JsonMissingValue: + pass + + try: + parse('{"key": "value"') + except JsonMissingClosing: + pass + + try: + parse('{"key": ] ') + except JsonMissingOpening: + pass + + +if __name__ == '__main__': + test() + +