Skip to content

Commit ef208e3

Browse files
committed
#18 Add relevant tests from Kolasu, lint
1 parent ab8451c commit ef208e3

File tree

6 files changed

+67
-11
lines changed

6 files changed

+67
-11
lines changed

.github/workflows/pythonapp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
run: |
2424
python -m pip install --upgrade pip
2525
pip install -r Requirements.txt
26-
curl -O https://www.antlr.org/download/antlr-4.11.1-complete.jar
26+
pip install antlr4-cli
2727
- name: Lint with flake8
2828
run: |
2929
pip install flake8

pylasu/parsing/antlr.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import time
22
from abc import abstractmethod
3-
from typing import Optional, List
3+
from typing import Optional, List, Union
44

55
from antlr4 import CommonTokenStream, InputStream, Lexer, Parser, ParserATNSimulator, ParserRuleContext, \
66
PredictionContextCache, Recognizer, Token, TokenStream
@@ -22,8 +22,8 @@ class PylasuANTLRParser:
2222
def __init__(self):
2323
self.prediction_context_cache = PredictionContextCache()
2424

25-
def parse(self, input_stream: InputStream, consider_range: bool = True, measure_lexing_time: bool = False,
26-
source: Optional[Source] = None):
25+
def parse(self, input_stream: Union[InputStream, str], consider_range: bool = True,
26+
measure_lexing_time: bool = False, source: Optional[Source] = None):
2727
"""Parses source code, returning a result that includes an AST and a collection of parse issues
2828
(errors, warnings).
2929
The parsing is done in accordance to the StarLasu methodology i.e. a first-stage parser builds a parse tree
@@ -34,6 +34,8 @@ def parse(self, input_stream: InputStream, consider_range: bool = True, measure_
3434
@param measureLexingTime if true, the result will include a measurement of the time spent in lexing i.e.
3535
breaking the input stream into tokens."""
3636
start = time.time_ns()
37+
if type(input_stream) is str:
38+
input_stream = InputStream(input_stream)
3739
first_stage = self.parse_first_stage(input_stream, measure_lexing_time)
3840
issues = first_stage.issues
3941
ast = self.parse_tree_to_ast(first_stage.root, consider_range, issues, source)
@@ -120,12 +122,12 @@ def create_token_stream(self, lexer: Lexer) -> TokenStream:
120122
return CommonTokenStream(lexer)
121123

122124
@abstractmethod
123-
def create_antlr_lexer(self, input_stream: InputStream):
125+
def create_antlr_lexer(self, input_stream: InputStream) -> Lexer:
124126
"""Creates the lexer."""
125127
pass
126128

127129
@abstractmethod
128-
def create_antlr_parser(self, token_stream: TokenStream):
130+
def create_antlr_parser(self, token_stream: TokenStream) -> Parser:
129131
"""Creates the first-stage parser."""
130132
pass
131133

@@ -147,4 +149,5 @@ def syntaxError(self, recognizer, offending_symbol, line, column, msg, e):
147149
end_point = start_point
148150
if isinstance(offending_symbol, Token):
149151
end_point = token_end_point(offending_symbol)
150-
self.issues.append(Issue(IssueType.SYNTACTIC, msg or "unspecified", position=Position(start_point, end_point)))
152+
msg = (msg or "unspecified").capitalize()
153+
self.issues.append(Issue(IssueType.SYNTACTIC, msg, position=Position(start_point, end_point)))

tests/SimpleLangParser.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ parser grammar SimpleLangParser;
33
options { tokenVocab = SimpleLangLexer; }
44

55
compilationUnit:
6-
statement+;
6+
statement+ EOF;
77

88
statement:
99
DISPLAY expression #displayStmt

tests/generate-test-parsers.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
java -cp ../antlr-4.11.1-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 -visitor -o simple_lang SimpleLangLexer.g4 SimpleLangParser.g4
2-
java -cp ../antlr-4.11.1-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 -visitor -o antlr_entity AntlrEntityLexer.g4 AntlrEntityParser.g4
3-
java -cp ../antlr-4.11.1-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 -visitor -o antlr_script AntlrScriptLexer.g4 AntlrScriptParser.g4
1+
antlr4 -Dlanguage=Python3 -visitor -o simple_lang SimpleLangLexer.g4 SimpleLangParser.g4
2+
antlr4 -Dlanguage=Python3 -visitor -o antlr_entity AntlrEntityLexer.g4 AntlrEntityParser.g4
3+
antlr4 -Dlanguage=Python3 -visitor -o antlr_script AntlrScriptLexer.g4 AntlrScriptParser.g4

tests/parsing/__init__.py

Whitespace-only changes.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import unittest
2+
from typing import List, Optional
3+
4+
from antlr4 import TokenStream, InputStream
5+
6+
from pylasu.model import Source, Node, Position, Point
7+
from pylasu.parsing.antlr import PylasuANTLRParser
8+
from pylasu.validation import Issue
9+
from tests.simple_lang.SimpleLangLexer import SimpleLangLexer
10+
from tests.simple_lang.SimpleLangParser import SimpleLangParser
11+
12+
13+
class SimpleLangPylasuParser(PylasuANTLRParser):
14+
15+
def create_antlr_lexer(self, input_stream: InputStream):
16+
return SimpleLangLexer(input_stream)
17+
18+
def create_antlr_parser(self, token_stream: TokenStream):
19+
return SimpleLangParser(token_stream)
20+
21+
def parse_tree_to_ast(self, root, consider_range: bool, issues: List[Issue], source: Source) -> Optional[Node]:
22+
return None
23+
24+
25+
class KolasuParserTest(unittest.TestCase):
26+
def test_lexing(self):
27+
parser = SimpleLangPylasuParser()
28+
result = parser.parse("""set a = 10
29+
set b = ""
30+
display c
31+
""")
32+
self.assertIsNotNone(result)
33+
# TODO we don't have Pylasu Tokens yet
34+
35+
def test_issues_are_capitalized(self):
36+
parser = SimpleLangPylasuParser()
37+
result = parser.parse("""set set a = 10
38+
display c
39+
""")
40+
self.assertTrue(result.issues)
41+
self.assertTrue([i for i in result.issues if i.message.startswith("Extraneous input 'set'")])
42+
self.assertTrue([i for i in result.issues if i.message.startswith("Mismatched input 'c'")])
43+
44+
def test_issues_have_not_flat_position(self):
45+
parser = SimpleLangPylasuParser()
46+
result = parser.parse("""set set a = 10
47+
display c
48+
""")
49+
self.assertTrue(result.issues)
50+
extraneous_input = [i for i in result.issues if i.message.startswith("Extraneous input 'set'")][0]
51+
self.assertEqual(Position(Point(1, 4), Point(1, 7)), extraneous_input.position)
52+
mismatched_input = [i for i in result.issues if i.message.startswith("Mismatched input 'c'")][0]
53+
self.assertEqual(Position(Point(2, 8), Point(2, 9)), mismatched_input.position)

0 commit comments

Comments
 (0)