Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ATN serialization improvements (Java only for demo) #3505

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ mode names:
DEFAULT_MODE

atn:
[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 13, 61, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 6, 9, 41, 10, 9, 13, 9, 14, 9, 42, 3, 10, 6, 10, 46, 10, 10, 13, 10, 14, 10, 47, 3, 11, 5, 11, 51, 10, 11, 3, 11, 3, 11, 3, 12, 6, 12, 56, 10, 12, 13, 12, 14, 12, 57, 3, 12, 3, 12, 2, 2, 13, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 3, 2, 5, 4, 2, 67, 92, 99, 124, 3, 2, 50, 59, 4, 2, 11, 11, 34, 34, 2, 64, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 3, 25, 3, 2, 2, 2, 5, 27, 3, 2, 2, 2, 7, 29, 3, 2, 2, 2, 9, 31, 3, 2, 2, 2, 11, 33, 3, 2, 2, 2, 13, 35, 3, 2, 2, 2, 15, 37, 3, 2, 2, 2, 17, 40, 3, 2, 2, 2, 19, 45, 3, 2, 2, 2, 21, 50, 3, 2, 2, 2, 23, 55, 3, 2, 2, 2, 25, 26, 7, 63, 2, 2, 26, 4, 3, 2, 2, 2, 27, 28, 7, 44, 2, 2, 28, 6, 3, 2, 2, 2, 29, 30, 7, 49, 2, 2, 30, 8, 3, 2, 2, 2, 31, 32, 7, 45, 2, 2, 32, 10, 3, 2, 2, 2, 33, 34, 7, 47, 2, 2, 34, 12, 3, 2, 2, 2, 35, 36, 7, 42, 2, 2, 36, 14, 3, 2, 2, 2, 37, 38, 7, 43, 2, 2, 38, 16, 3, 2, 2, 2, 39, 41, 9, 2, 2, 2, 40, 39, 3, 2, 2, 2, 41, 42, 3, 2, 2, 2, 42, 40, 3, 2, 2, 2, 42, 43, 3, 2, 2, 2, 43, 18, 3, 2, 2, 2, 44, 46, 9, 3, 2, 2, 45, 44, 3, 2, 2, 2, 46, 47, 3, 2, 2, 2, 47, 45, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 20, 3, 2, 2, 2, 49, 51, 7, 15, 2, 2, 50, 49, 3, 2, 2, 2, 50, 51, 3, 2, 2, 2, 51, 52, 3, 2, 2, 2, 52, 53, 7, 12, 2, 2, 53, 22, 3, 2, 2, 2, 54, 56, 9, 4, 2, 2, 55, 54, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 55, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 60, 8, 12, 2, 2, 60, 24, 3, 2, 2, 2, 7, 2, 42, 47, 50, 57, 3, 8, 2, 2]
3, 0, -119, 96, 40, -89, 49, -127, -21, -71, 122, 65, -27, 59, -124, 119, 98, 89, 1, 6, 19, 2, 0, 7, 0, 1, 0, 1, 0, 1, 0, 3, 0, 6, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 14, 8, 0, 10, 0, 12, 0, 17, 9, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 20, 0, 5, 1, 0, 0, 0, 2, 3, 6, 0, -32, 0, 3, 6, 5, 3, 0, 0, 4, 6, 5, 4, 0, 0, 5, 2, 1, 0, 0, 0, 5, 4, 1, 0, 0, 0, 6, 15, 1, 0, 0, 0, 7, 8, 10, 4, 0, 0, 8, 9, 5, 1, 0, 0, 9, 14, 3, 0, 0, 5, 10, 11, 10, 3, 0, 0, 11, 12, 5, 2, 0, 0, 12, 14, 3, 0, 0, 4, 13, 7, 1, 0, 0, 0, 13, 10, 1, 0, 0, 0, 14, 17, 1, 0, 0, 0, 15, 13, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 1, 1, 0, 0, 0, 17, 15, 1, 0, 0, 0, 3, 5, 13, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,10 @@ public static RuntimeTestDescriptor[] getRuntimeTestDescriptors(String group, St
}

if (group.equals("LexerExec")) {
descriptors.add(GeneratedLexerDescriptors.getLineSeparatorLfTest(targetName));
descriptors.add(GeneratedLexerDescriptors.getLineSeparatorCrLfTest(targetName));
descriptors.add(GeneratedLexerDescriptors.getLineSeparatorLfDescriptor(targetName));
descriptors.add(GeneratedLexerDescriptors.getLineSeparatorCrLfDescriptor(targetName));
descriptors.add(GeneratedLexerDescriptors.getLargeLexerDescriptor(targetName));
descriptors.add(GeneratedLexerDescriptors.getAtnStatesSizeMoreThan65535Descriptor(targetName));
}

return descriptors.toArray(new RuntimeTestDescriptor[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ protected ATN createATN(Grammar g, boolean useSerializer) {

ATN atn = g.atn;
if ( useSerializer ) {
char[] serialized = ATNSerializer.getSerializedAsChars(atn);
return new ATNDeserializer().deserialize(serialized);
return ATNSerializer.clone(atn);
}

return atn;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.antlr.v4.test.runtime;

import java.util.Collections;

public class GeneratedLexerDescriptors {
static RuntimeTestDescriptor getLineSeparatorLfTest(String targetName) {
static RuntimeTestDescriptor getLineSeparatorLfDescriptor(String targetName) {
UniversalRuntimeTestDescriptor result = new UniversalRuntimeTestDescriptor();
result.name = "LineSeparatorLf";
result.targetName = targetName;
Expand All @@ -20,7 +22,7 @@ static RuntimeTestDescriptor getLineSeparatorLfTest(String targetName) {
return result;
}

static RuntimeTestDescriptor getLineSeparatorCrLfTest(String targetName) {
static RuntimeTestDescriptor getLineSeparatorCrLfDescriptor(String targetName) {
UniversalRuntimeTestDescriptor result = new UniversalRuntimeTestDescriptor();
result.name = "LineSeparatorCrLf";
result.targetName = targetName;
Expand Down Expand Up @@ -65,4 +67,50 @@ static RuntimeTestDescriptor getLargeLexerDescriptor(String targetName) {
"[@1,5:4='<EOF>',<-1>,1:5]\n";
return result;
}

static RuntimeTestDescriptor getAtnStatesSizeMoreThan65535Descriptor(String targetName) {
UniversalRuntimeTestDescriptor result = new UniversalRuntimeTestDescriptor();
result.name = "AtnStatesSizeMoreThan65535";
result.notes = "Regression for https://github.com/antlr/antlr4/issues/1863";
result.targetName = targetName;
result.testType = "Lexer";

final int tokensCount = 1024;
final String suffix = String.join("", Collections.nCopies(70, "_"));

String grammarName = "L";
StringBuilder grammar = new StringBuilder();
grammar.append("lexer grammar ").append(grammarName).append(";\n");
grammar.append('\n');
StringBuilder input = new StringBuilder();
StringBuilder output = new StringBuilder();
int startOffset;
int stopOffset = -2;
for (int i = 0; i < tokensCount; i++) {
String value = "T_" + i + suffix;
grammar.append(value).append(": '").append(value).append("';\n");
input.append(value).append('\n');

startOffset = stopOffset + 2;
stopOffset += value.length() + 1;

output.append("[@").append(i).append(',').append(startOffset).append(':').append(stopOffset)
.append("='").append(value).append("',<").append(i + 1).append(">,").append(i + 1)
.append(":0]\n");
}

grammar.append("\n");
grammar.append("WS: [ \\t\\r\\n]+ -> skip;\n");

startOffset = stopOffset + 2;
stopOffset = startOffset - 1;
output.append("[@").append(tokensCount).append(',').append(startOffset).append(':').append(stopOffset)
.append("='<EOF>',<-1>,").append(tokensCount + 1).append(":0]\n");

result.grammar = grammar.toString();
result.grammarName = grammarName;
result.input = input.toString();
result.output = output.toString();
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ public void testActions(String templates, String actionName, String action, Stri
anal.process();

CodeGenerator gen = CodeGenerator.create(g);
ST outputFileST = gen.generateParser(false);
ST outputFileST = gen.generateParser(false, null);
String output = outputFileST.render();
//System.out.println(output);
String b = "#" + actionName + "#";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.antlr.v4.runtime.Vocabulary;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNSerializer;
import org.antlr.v4.runtime.misc.InterpreterDataReader;
import org.junit.Assert;
import org.junit.Test;
Expand Down Expand Up @@ -40,8 +39,6 @@ public void testParseFile() throws NoSuchFieldException, IllegalAccessException
List<String> channels = castList(channelsField.get(interpreterData), String.class);
List<String> modes = castList(modesField.get(interpreterData), String.class);

char[] atnChars = ATNSerializer.getSerializedAsChars(atn);
Assert.assertTrue(atnChars.length > 0);
Assert.assertNotNull(vocabulary);
Assert.assertEquals(11, ruleNames.size());
Assert.assertEquals(2, channels.size());
Expand All @@ -51,7 +48,7 @@ public void testParseFile() throws NoSuchFieldException, IllegalAccessException
@Test
public void testParseFileError() {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final URL stuff = loader.getResource("org/antlr/v4/test/runtime/InterpDataReaderTest2.interp");
final URL stuff = loader.getResource("org/antlr/v4/test/runtime/InterpDataReaderTest.interp");
Assert.assertNotNull(stuff);

try {
Expand Down
9 changes: 3 additions & 6 deletions runtime/Java/src/org/antlr/v4/runtime/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.nio.ByteBuffer;
import java.util.*;

/** This is all the parsing support code essentially; most of it is error recovery stuff. */
public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
Expand Down Expand Up @@ -450,7 +447,7 @@ public ATN getATNWithBypassAlts() {
if (result == null) {
ATNDeserializationOptions deserializationOptions = new ATNDeserializationOptions();
deserializationOptions.setGenerateRuleBypassTransitions(true);
result = new ATNDeserializer(deserializationOptions).deserialize(serializedAtn.toCharArray());
result = new ATNDeserializer(deserializationOptions).deserialize(serializedAtn);
bypassAltsAtnCache.put(serializedAtn, result);
}

Expand Down
42 changes: 42 additions & 0 deletions runtime/Java/src/org/antlr/v4/runtime/atn/ATNDataReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.antlr.v4.runtime.atn;

import java.util.UUID;

public abstract class ATNDataReader {
protected abstract byte readByte();

public int read() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a standard base64 decoder somewhere?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh i see base64 below now. Hmm...adding general comment outside.

Copy link
Member Author

@KvanTTT KvanTTT Jan 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the binary reader that uses abstract readByte calls. It reads mostly integers from compact format (described below). readByte is implemented in ATNDataReaderBase64 (that reads from base64 string) and in ATNDataReaderByteBuffer.

int value = readByte();
if ((value & 0b1000_0000) == 0) {
return value;
}

int mask = value & 0b111_00000;
if (mask == ATNDataWriter.MinusOneMask) {
return -1;
}
else {
return mask == ATNDataWriter.OneByteMask
? value
: mask == ATNDataWriter.TwoByteMask
? (value & ATNDataWriter.ValueMask) << 8 | readByte() & 0xFF
: mask == ATNDataWriter.ThreeByteMask
? (value & ATNDataWriter.ValueMask) << 16 | readByte() << 8 & 0xFF00 | readByte() & 0xFF
: (readByte() << 24 & 0xFF000000) | (readByte() << 16 & 0xFF0000) | (readByte() << 8 & 0xFF00) | readByte() & 0xFF;
}
}

public UUID readUUID() {
long leastSigBits = ((long) readInt32() & 0x00000000FFFFFFFFL) | ((long) readInt32() << 32);
long mostSigBits = ((long) readInt32() & 0x00000000FFFFFFFFL) | ((long) readInt32() << 32);
return new UUID(mostSigBits, leastSigBits);
}

public int readInt32() {
return readUInt16() | (readUInt16() << 16);
}

public int readUInt16() {
return readByte() & 0xFF | readByte() << 8 & 0xFF00;
}
}
54 changes: 54 additions & 0 deletions runtime/Java/src/org/antlr/v4/runtime/atn/ATNDataReaderBase64.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.antlr.v4.runtime.atn;

import java.util.Arrays;

public class ATNDataReaderBase64 extends ATNDataReader {
private static final char[] toBase64 = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};

private static final int[] fromBase64 = new int[256];
static {
Arrays.fill(fromBase64, -1);
for (int i = 0; i < toBase64.length; i++)
fromBase64[toBase64[i]] = i;
fromBase64['='] = -2;
}

private final String string;
private int charPos;
private int rest;
private int restBitsCount;

public ATNDataReaderBase64(String string) {
this.string = string;
}

@Override
public byte readByte() {
int result = 0;
if (restBitsCount == 0) {
int b1 = fromBase64[string.charAt(charPos++)];
int b2 = fromBase64[string.charAt(charPos++)];
result = b1 << 2 & 0b1111_1100 | b2 >> 4 & 0b0000_0011;
rest = b2 & 0b0000_1111;
restBitsCount = 4;
}
else if (restBitsCount == 4) {
int b = fromBase64[string.charAt(charPos++)];
result = rest << 4 & 0b1111_0000 | b >> 2 & 0b0000_1111;
rest = b & 0b0000_0011;
restBitsCount = 2;
}
else if (restBitsCount == 2) {
int b = fromBase64[string.charAt(charPos++)];
result = rest << 6 & 0b1100_0000 | b & 0b0011_1111;
restBitsCount = 0;
}
return (byte)result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.antlr.v4.runtime.atn;

import java.nio.ByteBuffer;

public class ATNDataReaderByteBuffer extends ATNDataReader {
private final ByteBuffer byteBuffer;

public ATNDataReaderByteBuffer(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
if (byteBuffer.position() != 0) {
byteBuffer.flip();
}
}

@Override
public byte readByte() {
return byteBuffer.get();
}
}
Loading