Merge branch 'master-upstream'
This commit is contained in:
commit
8651498f41
|
@ -97,3 +97,4 @@ xcuserdata
|
|||
# VSCode Java plugin temporary files
|
||||
javac-services.0.log
|
||||
javac-services.0.log.lck
|
||||
test/
|
||||
|
|
24
.travis.yml
24
.travis.yml
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -3,3 +3,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python2.* test
|
||||
|
||||
cd ../runtime/Python2/tests
|
||||
|
||||
python run.py
|
|
@ -3,3 +3,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python3.* test
|
||||
|
||||
cd ../runtime/Python3/test
|
||||
|
||||
python3.6 run.py
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ def exit<lname; format="cap">(self, ctx:<file.parserName>.<lname; format="cap">C
|
|||
|
||||
}; separator="\n">
|
||||
|
||||
del <file.parserName>
|
||||
>>
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue