Merge branch 'master-upstream'

This commit is contained in:
Mike Lischke 2019-08-18 11:18:41 +02:00
commit 8651498f41
25 changed files with 377 additions and 43 deletions

1
.gitignore vendored
View File

@ -97,3 +97,4 @@ xcuserdata
# VSCode Java plugin temporary files
javac-services.0.log
javac-services.0.log.lck
test/

View File

@ -19,8 +19,9 @@ stages:
matrix:
include:
- os: linux
dist: trusty
compiler: clang
jdk: openjdk7
jdk: openjdk8
env:
- TARGET=cpp
- CXX=g++-5
@ -36,8 +37,9 @@ matrix:
- uuid-dev
- clang-3.7
- os: linux
dist: trusty
compiler: clang
jdk: openjdk7
jdk: openjdk8
env:
- TARGET=cpp
- CXX=g++-5
@ -53,8 +55,9 @@ matrix:
- uuid-dev
- clang-3.7
- os: linux
dist: trusty
compiler: clang
jdk: openjdk7
jdk: openjdk8
env:
- TARGET=cpp
- CXX=g++-5
@ -137,23 +140,20 @@ matrix:
- GROUP=RECURSION
stage: extended-test
- os: linux
dist: trusty
jdk: openjdk7
env: TARGET=java
stage: extended-test
- os: linux
jdk: openjdk8
env: TARGET=java
stage: extended-test
- os: linux
jdk: oraclejdk8
env: TARGET=java
stage: smoke-test
- os: linux
jdk: openjdk7
jdk: openjdk8
env: TARGET=csharp
stage: main-test
- os: linux
jdk: oraclejdk8
jdk: openjdk8
dist: trusty
env:
- TARGET=dotnet
@ -167,18 +167,18 @@ matrix:
- GROUP=PARSER
stage: extended-test
- os: linux
jdk: oraclejdk8
jdk: openjdk8
dist: trusty
env:
- TARGET=dotnet
- GROUP=RECURSION
stage: extended-test
- os: linux
jdk: openjdk7
jdk: openjdk8
env: TARGET=python2
stage: main-test
- os: linux
jdk: openjdk7
jdk: openjdk8
env: TARGET=python3
addons:
apt:

View File

@ -3,6 +3,6 @@
set -euo pipefail
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb http://download.mono-project.com/repo/debian xenial main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
sudo apt-get update -qq
echo "deb http://download.mono-project.com/repo/debian wheezy/snapshots/3.12.1 main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
sudo apt-get install -qq mono-complete

View File

@ -3,3 +3,7 @@
set -euo pipefail
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python2.* test
cd ../runtime/Python2/tests
python run.py

View File

@ -3,3 +3,7 @@
set -euo pipefail
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python3.* test
cd ../runtime/Python3/test
python3.6 run.py

View File

@ -203,6 +203,8 @@ YYYY/MM/DD, github id, Full name, email
2018/06/16, EternalPhane, Zongyuan Zuo, eternalphane@gmail.com
2018/07/03, jgoppert, James Goppert, james.goppert@gmail.com
2018/07/27, Maksim Novikov, mnovikov.work@gmail.com
2018/08/03, ENDOH takanao, djmchl@gmail.com
2018/10/18, edirgarcia, Edir García Lazo, edirgl@hotmail.com
2018/07/31, Lucas Henrqiue, lucashenrique580@gmail.com
2018/08/03, ENDOH takanao, djmchl@gmail.com
2018/10/29, chrisaycock, Christopher Aycock, chris[at]chrisaycock[dot]com
@ -212,3 +214,10 @@ YYYY/MM/DD, github id, Full name, email
2018/11/29, hannemann-tamas, Ralf Hannemann-Tamas, ralf.ht@gmail.com
2018/12/20, WalterCouto, Walter Couto, WalterCouto@users.noreply.github.com
2018/12/23, youkaichao, Kaichao You, youkaichao@gmail.com
2019/02/06, ralucado, Cristina Raluca Vijulie, ralucris.v[at]gmail[dot]com
2019/03/13, base698, Justin Thomas, justin.thomas1@gmail.com
2019/03/18, carlodri, Carlo Dri, carlo.dri@gmail.com
2019/05/02, askingalot, Andy Collins, askingalot@gmail.com
2019/07/11, olowo726, Olof Wolgast, olof@baah.se
2019/07/16, abhijithneilabraham, Abhijith Neil Abraham, abhijithneilabrahampk@gmail.com
2019/07/26, Braavos96, Eric Hettiaratchi, erichettiaratchi@gmail.com

View File

@ -30,7 +30,7 @@ Let's suppose that your grammar is named `MyGrammar`. The tool will generate for
Now a fully functioning code might look like the following for start rule `StartRule`:
```
```csharp
using Antlr4.Runtime;
using Antlr4.Runtime.Tree;
@ -59,7 +59,7 @@ Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value".
The antlr4 tool will have generated the following listener (only partial code shown here):
```
```csharp
interface IMyGrammarParserListener : IParseTreeListener {
void EnterKey (MyGrammarParser.KeyContext context);
void ExitKey (MyGrammarParser.KeyContext context);
@ -70,7 +70,7 @@ interface IMyGrammarParserListener : IParseTreeListener {
In order to provide custom behavior, you might want to create the following class:
```
```csharp
class KeyPrinter : MyGrammarBaseListener {
// override default listener behavior
void ExitKey (MyGrammarParser.KeyContext context) {
@ -82,7 +82,7 @@ class KeyPrinter : MyGrammarBaseListener {
In order to execute this listener, you would simply add the following lines to the above code:
```
```csharp
...
IParseTree tree = parser.StartRule() - only repeated here for reference
KeyPrinter printer = new KeyPrinter();

View File

@ -112,8 +112,11 @@ Now test it:
```
$ grun Hello r -tree
(Now enter something like the string below)
hello parrt
(now,do:)
^D
(The output:)
(r hello parrt)
(That ^D means EOF on unix; it's ^Z in Windows.) The -tree option prints the parse tree in LISP notation.
It's nicer to look at parse trees visually.

View File

@ -21,6 +21,8 @@ This documentation is a reference and summarizes grammar syntax and the key sema
<a href="https://vimeo.com/59285751"><img src=images/tertalk.png width=200></a>
For those using Java, here's a great [set of ANTLR in Intellij notes](https://docs.google.com/document/d/1gQ2lsidvN2cDUUsHEkT05L-wGbX5mROB7d70Aaj3R64/edit#heading=h.xr0jj8vcdsgc) by Andreas Stefik.
## Sections
* [Getting Started with ANTLR v4](getting-started.md)

View File

@ -117,6 +117,44 @@ This program will work. But it won't be useful unless you do one of the followin
(please note that production code is target specific, so you can't have multi target grammars that include production code)
## How do I create and run a visitor?
```javascript
// test.js
var antlr4 = require('antlr4');
var MyGrammarLexer = require('./QueryLexer').QueryLexer;
var MyGrammarParser = require('./QueryParser').QueryParser;
var MyGrammarListener = require('./QueryListener').QueryListener;
var input = "field = 123 AND items in (1,2,3)"
var chars = new antlr4.InputStream(input);
var lexer = new MyGrammarLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new MyGrammarParser(tokens);
parser.buildParseTrees = true;
var tree = parser.query();
class Visitor {
visitChildren(ctx) {
if (!ctx) {
return;
}
if (ctx.children) {
return ctx.children.map(child => {
if (child.children && child.children.length != 0) {
return child.accept(this);
} else {
return child.getText();
}
});
}
}
}
tree.accept(new Visitor());
````
## How do I create and run a custom listener?
Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value". The antlr4 tool will have generated the following listener:

View File

@ -50,8 +50,8 @@ from MyGrammarLexer import MyGrammarLexer
from MyGrammarParser import MyGrammarParser
def main(argv):
input = FileStream(argv[1])
lexer = MyGrammarLexer(input)
input_stream = FileStream(argv[1])
lexer = MyGrammarLexer(input_stream)
stream = CommonTokenStream(lexer)
parser = MyGrammarParser(stream)
tree = parser.startRule()

View File

@ -68,7 +68,8 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>[9.3.24.v20180605,)</version>
<!-- stick to version 9 for jdk compatibility -->
<version>9.4.19.v20190610</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -31,6 +31,8 @@ namespace Antlr4.Runtime
private readonly string _grammarFileName;
private readonly ATN _atn;
private readonly Dfa.DFA[] _decisionToDFA;
protected internal readonly BitSet pushRecursionContextStates;
@ -61,8 +63,17 @@ namespace Antlr4.Runtime
this.pushRecursionContextStates.Set(state.stateNumber);
}
}
// get atn simulator that knows how to do predictions
Interpreter = new ParserATNSimulator(this, atn, null, null);
//init decision DFA
int numberofDecisions = atn.NumberOfDecisions;
this._decisionToDFA = new Dfa.DFA[numberofDecisions];
for (int i = 0; i < numberofDecisions; i++)
{
DecisionState decisionState = atn.GetDecisionState(i);
_decisionToDFA[i] = new Dfa.DFA(decisionState, i);
}
// get atn simulator that knows how to do predictions
Interpreter = new ParserATNSimulator(this, atn, _decisionToDFA, null);
}
public override ATN Atn

View File

@ -612,7 +612,6 @@ namespace Antlr4.Runtime
}
// throw exception unless disjoint or identical
bool disjoint = prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex;
bool same = prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex;
// Delete special case of replace (text==null):
// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right)
if (prevRop.text == null && rop.text == null && !disjoint)
@ -628,7 +627,7 @@ namespace Antlr4.Runtime
}
else
{
if (!disjoint && !same)
if (!disjoint)
{
throw new ArgumentException("replace op boundaries of " + rop + " overlap with previous " + prevRop);
}

View File

@ -348,7 +348,6 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
}
// throw exception unless disjoint or identical
bool disjoint = prevRop->lastIndex < rop->index || prevRop->index > rop->lastIndex;
bool same = prevRop->index == rop->index && prevRop->lastIndex == rop->lastIndex;
// Delete special case of replace (text==null):
// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right)
if (prevRop->text.empty() && rop->text.empty() && !disjoint) {
@ -358,7 +357,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
rop->lastIndex = std::max(prevRop->lastIndex, rop->lastIndex);
std::cout << "new rop " << rop << std::endl;
}
else if (!disjoint && !same) {
else if (!disjoint) {
throw IllegalArgumentException("replace op boundaries of " + rop->toString() +
" overlap with previous " + prevRop->toString());
}

View File

@ -22,7 +22,7 @@ namespace antlrcpp {
inline std::string utf32_to_utf8(T const& data)
{
// Don't make the converter static or we have to serialize access to it.
UTF32Converter converter;
thread_local UTF32Converter converter;
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
auto p = reinterpret_cast<const int32_t *>(data.data());
@ -34,7 +34,7 @@ namespace antlrcpp {
inline UTF32String utf8_to_utf32(const char* first, const char* last)
{
UTF32Converter converter;
thread_local UTF32Converter converter;
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
auto r = converter.from_bytes(first, last);

View File

@ -101,14 +101,11 @@ class TokenStreamRewriter(object):
return self.programs.setdefault(program_name, [])
def getDefaultText(self):
return self.getText(self.DEFAULT_PROGRAM_NAME, 0, len(self.tokens.tokens))
return self.getText(self.DEFAULT_PROGRAM_NAME, 0, len(self.tokens.tokens) - 1)
def getText(self, program_name, start, stop):
"""
:type interval: IntervalSet.Interval
:param program_name:
:param interval:
:return:
:return: the text in tokens[start, stop](closed interval)
"""
rewrites = self.programs.get(program_name)
@ -160,13 +157,12 @@ class TokenStreamRewriter(object):
rewrites[prevRop.instructionIndex] = None
continue
isDisjoint = any((prevRop.last_index < rop.index, prevRop.index > rop.last_index))
isSame = all((prevRop.index == rop.index, prevRop.last_index == rop.last_index))
if all((prevRop.text is None, rop.text is None, not isDisjoint)):
rewrites[prevRop.instructionIndex] = None
rop.index = min(prevRop.index, rop.index)
rop.last_index = min(prevRop.last_index, rop.last_index)
print('New rop {}'.format(rop))
elif not all((isDisjoint, isSame)):
elif (not(isDisjoint)):
raise ValueError("replace op boundaries of {} overlap with previous {}".format(rop, prevRop))
# Walk inserts before

View File

@ -0,0 +1,7 @@
import sys
import os
src_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src')
sys.path.insert(0,src_path)
from TestTokenStreamRewriter import TestTokenStreamRewriter
import unittest
unittest.main()

View File

@ -113,7 +113,7 @@ class ParserRuleContext(RuleContext):
def getChild(self, i:int, ttype:type = None):
if ttype is None:
return self.children[i] if len(self.children)>=i else None
return self.children[i] if len(self.children)>i else None
else:
for child in self.getChildren():
if not isinstance(child, ttype):

View File

@ -101,11 +101,11 @@ class TokenStreamRewriter(object):
return self.programs.setdefault(program_name, [])
def getDefaultText(self):
return self.getText(self.DEFAULT_PROGRAM_NAME, 0, len(self.tokens.tokens))
return self.getText(self.DEFAULT_PROGRAM_NAME, 0, len(self.tokens.tokens) - 1)
def getText(self, program_name, start:int, stop:int):
"""
:return:
:return: the text in tokens[start, stop](closed interval)
"""
rewrites = self.programs.get(program_name)
@ -156,13 +156,12 @@ class TokenStreamRewriter(object):
rewrites[prevRop.instructionIndex] = None
continue
isDisjoint = any((prevRop.last_index<rop.index, prevRop.index>rop.last_index))
isSame = all((prevRop.index == rop.index, prevRop.last_index == rop.last_index))
if all((prevRop.text is None, rop.text is None, not isDisjoint)):
rewrites[prevRop.instructionIndex] = None
rop.index = min(prevRop.index, rop.index)
rop.last_index = min(prevRop.last_index, rop.last_index)
print('New rop {}'.format(rop))
elif not all((isDisjoint, isSame)):
elif (not(isDisjoint)):
raise ValueError("replace op boundaries of {} overlap with previous {}".format(rop, prevRop))
# Walk inserts
@ -249,4 +248,4 @@ class TokenStreamRewriter(object):
def __str__(self):
if self.text:
return '<ReplaceOp@{}..{}:"{}">'.format(self.tokens.get(self.index), self.tokens.get(self.last_index),
self.text)
self.text)

View File

@ -0,0 +1,7 @@
import sys
import os
src_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src')
sys.path.insert(0,src_path)
from TestTokenStreamRewriter import TestTokenStreamRewriter
import unittest
unittest.main()

View File

@ -0,0 +1,129 @@
package org.antlr.v4.misc;
import org.antlr.runtime.Token;
import org.antlr.v4.tool.ast.GrammarAST;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
public class UtilsTest {
@Test
public void testStripFileExtension() {
Assert.assertNull(Utils.stripFileExtension(null));
Assert.assertEquals("foo", Utils.stripFileExtension("foo"));
Assert.assertEquals("foo", Utils.stripFileExtension("foo.txt"));
}
@Test
public void testJoin() {
Assert.assertEquals("foobbar",
Utils.join(new String[]{"foo", "bar"}, "b"));
Assert.assertEquals("foo,bar",
Utils.join(new String[]{"foo", "bar"}, ","));
}
@Test
public void testSortLinesInString() {
Assert.assertEquals("bar\nbaz\nfoo\n",
Utils.sortLinesInString("foo\nbar\nbaz"));
}
@Test
public void testNodesToStrings() {
ArrayList<GrammarAST> values = new ArrayList<>();
values.add(new GrammarAST(Token.EOR_TOKEN_TYPE));
values.add(new GrammarAST(Token.DOWN));
values.add(new GrammarAST(Token.UP));
Assert.assertNull(Utils.nodesToStrings(null));
Assert.assertNotNull(Utils.nodesToStrings(values));
}
@Test
public void testCapitalize() {
Assert.assertEquals("Foo", Utils.capitalize("foo"));
}
@Test
public void testDecapitalize() {
Assert.assertEquals("fOO", Utils.decapitalize("FOO"));
}
@Test
public void testSelect() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
Utils.Func1<String, String> func1 = new Utils.Func1() {
@Override
public Object exec(Object arg1) {
return "baz";
}
};
ArrayList<String> retval = new ArrayList<>();
retval.add("baz");
retval.add("baz");
Assert.assertEquals(retval, Utils.select(strings, func1));
Assert.assertNull(Utils.select(null, null));
}
@Test
public void testFind() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
Assert.assertEquals("foo", Utils.find(strings, String.class));
Assert.assertNull(Utils.find(new ArrayList<>(), String.class));
}
@Test
public void testIndexOf() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
Utils.Filter filter = new Utils.Filter() {
@Override
public boolean select(Object o) {
return true;
}
};
Assert.assertEquals(0, Utils.indexOf(strings, filter));
Assert.assertEquals(-1, Utils.indexOf(new ArrayList<>(), null));
}
@Test
public void testLastIndexOf() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
Utils.Filter filter = new Utils.Filter() {
@Override
public boolean select(Object o) {
return true;
}
};
Assert.assertEquals(1, Utils.lastIndexOf(strings, filter));
Assert.assertEquals(-1, Utils.lastIndexOf(new ArrayList<>(), null));
}
@Test
public void testSetSize() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
strings.add("baz");
Assert.assertEquals(3, strings.size());
Utils.setSize(strings, 2);
Assert.assertEquals(2, strings.size());
Utils.setSize(strings, 4);
Assert.assertEquals(4, strings.size());
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.tool;
import org.antlr.v4.misc.CharSupport;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.junit.Assert;
import org.junit.Test;
public class CharSupportTest {
@Test
public void testGetANTLRCharLiteralForChar() {
Assert.assertEquals("'<INVALID>'",
CharSupport.getANTLRCharLiteralForChar(-1));
Assert.assertEquals("'\\n'",
CharSupport.getANTLRCharLiteralForChar('\n'));
Assert.assertEquals("'\\\\'",
CharSupport.getANTLRCharLiteralForChar('\\'));
Assert.assertEquals("'\\''",
CharSupport.getANTLRCharLiteralForChar('\''));
Assert.assertEquals("'b'",
CharSupport.getANTLRCharLiteralForChar('b'));
Assert.assertEquals("'\\uFFFF'",
CharSupport.getANTLRCharLiteralForChar(0xFFFF));
Assert.assertEquals("'\\u{10FFFF}'",
CharSupport.getANTLRCharLiteralForChar(0x10FFFF));
}
@Test
public void testGetCharValueFromGrammarCharLiteral() {
Assert.assertEquals(-1,
CharSupport.getCharValueFromGrammarCharLiteral(null));
Assert.assertEquals(-1,
CharSupport.getCharValueFromGrammarCharLiteral(""));
Assert.assertEquals(-1,
CharSupport.getCharValueFromGrammarCharLiteral("b"));
Assert.assertEquals(111,
CharSupport.getCharValueFromGrammarCharLiteral("foo"));
}
@Test
public void testGetStringFromGrammarStringLiteral() {
Assert.assertNull(CharSupport
.getStringFromGrammarStringLiteral("foo\\u{bbb"));
Assert.assertNull(CharSupport
.getStringFromGrammarStringLiteral("foo\\u{[]bb"));
Assert.assertNull(CharSupport
.getStringFromGrammarStringLiteral("foo\\u[]bb"));
Assert.assertNull(CharSupport
.getStringFromGrammarStringLiteral("foo\\ubb"));
Assert.assertEquals("oo»b", CharSupport
.getStringFromGrammarStringLiteral("foo\\u{bb}bb"));
}
@Test
public void testGetCharValueFromCharInGrammarLiteral() {
Assert.assertEquals(102,
CharSupport.getCharValueFromCharInGrammarLiteral("f"));
Assert.assertEquals(-1,
CharSupport.getCharValueFromCharInGrammarLiteral("\' "));
Assert.assertEquals(-1,
CharSupport.getCharValueFromCharInGrammarLiteral("\\ "));
Assert.assertEquals(39,
CharSupport.getCharValueFromCharInGrammarLiteral("\\\'"));
Assert.assertEquals(10,
CharSupport.getCharValueFromCharInGrammarLiteral("\\n"));
Assert.assertEquals(-1,
CharSupport.getCharValueFromCharInGrammarLiteral("foobar"));
Assert.assertEquals(4660,
CharSupport.getCharValueFromCharInGrammarLiteral("\\u1234"));
Assert.assertEquals(18,
CharSupport.getCharValueFromCharInGrammarLiteral("\\u{12}"));
Assert.assertEquals(-1,
CharSupport.getCharValueFromCharInGrammarLiteral("\\u{"));
Assert.assertEquals(-1,
CharSupport.getCharValueFromCharInGrammarLiteral("foo"));
}
@Test
public void testParseHexValue() {
Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", -1, 3));
Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", 1, -1));
Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", 1, 3));
Assert.assertEquals(35, CharSupport.parseHexValue("123456", 1, 3));
}
@Test
public void testCapitalize() {
Assert.assertEquals("Foo", CharSupport.capitalize("foo"));
}
@Test
public void testGetIntervalSetEscapedString() {
Assert.assertEquals("",
CharSupport.getIntervalSetEscapedString(new IntervalSet()));
Assert.assertEquals("'\\u0000'",
CharSupport.getIntervalSetEscapedString(new IntervalSet(0)));
Assert.assertEquals("'\\u0001'..'\\u0003'",
CharSupport.getIntervalSetEscapedString(new IntervalSet(3, 1, 2)));
}
@Test
public void testGetRangeEscapedString() {
Assert.assertEquals("'\\u0002'..'\\u0004'",
CharSupport.getRangeEscapedString(2, 4));
Assert.assertEquals("'\\u0002'",
CharSupport.getRangeEscapedString(2, 2));
}
}

View File

@ -110,7 +110,10 @@ Parser(parser, funcs, atn, sempredFuncs, superClass) ::= <<
Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= <<
<if(superClass)>
from .<superClass> import <superClass>
if __name__ is not None and "." in __name__:
from .<superClass> import <superClass>
else:
from <superClass> import <superClass>
<endif>
<atn>
@ -750,7 +753,10 @@ import sys
Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass) ::= <<
<if(superClass)>
from .<superClass> import <superClass>
if __name__ is not None and "." in __name__:
from .<superClass> import <superClass>
else:
from <superClass> import <superClass>
<endif>

View File

@ -82,6 +82,7 @@ def exit<lname; format="cap">(self, ctx:<file.parserName>.<lname; format="cap">C
}; separator="\n">
del <file.parserName>
>>