Add a specialized token factory
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / antlr / CompactTokenFactory.java
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/antlr/CompactTokenFactory.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/antlr/CompactTokenFactory.java
new file mode 100644 (file)
index 0000000..598be06
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.antlr;
+
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CommonTokenFactory;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenFactory;
+import org.antlr.v4.runtime.TokenSource;
+import org.antlr.v4.runtime.misc.Pair;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A token factory which is more memory-efficient than {@link CommonTokenFactory}. We try to mimic behavior of common
+ * tokens, but do so at lower memory overheads, potentially sacrificing some performance.
+ */
+final class CompactTokenFactory implements TokenFactory<Token> {
+    static final @NonNull CompactTokenFactory INSTANCE = new CompactTokenFactory();
+
+    private CompactTokenFactory() {
+        // Hidden on purpose
+    }
+
+    @Override
+    public Token create(final Pair<TokenSource, CharStream> source, final int type, final String text,
+            final int channel, final int start, final int stop, final int line, final int charPositionInLine) {
+        if (channel != Token.DEFAULT_CHANNEL || text != null) {
+            // Non-default channel or text present, defer to common token factory
+            return CommonTokenFactory.DEFAULT.create(source, type, text, channel, start, stop, line,
+                charPositionInLine);
+        }
+
+        // Can we fit token type into a single byte? This should always be true
+        if (type >= Byte.MIN_VALUE && type <= Byte.MAX_VALUE) {
+            // Can we fit line in an unsigned short? This is usually be true
+            if (line >= 0 && line <= 65535) {
+                // Can we fit position in line into an unsigned byte? This is usually true
+                if (charPositionInLine >= 0 && charPositionInLine <= 255) {
+                    // Can we fit start/stop into an an unsigned short?
+                    if (start >= 0 && start <= 65535 && stop >= 0 && stop <= 65535) {
+                        return new Token12122(source, type, line, charPositionInLine, start, stop);
+                    }
+                    return new Token12144(source, type, line, charPositionInLine, start, stop);
+                }
+            }
+        }
+
+        return new Token44444(source, type, line, charPositionInLine, start, stop);
+    }
+
+    @Override
+    public Token create(final int type, final String text) {
+        return new ExplicitTextToken(type, text);
+    }
+}