From 07a9ccb4f1affb15766e5c88410799d31dc059de Mon Sep 17 00:00:00 2001
From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Date: Thu, 26 May 2022 01:26:47 +0200
Subject: [PATCH 01/39] migrate to antlr4
---
build.gradle | 14 +--
src/main/antlr3/org/jabref/bst/Bst.g | 96 -------------------
src/main/antlr4/org/jabref/bst/Bst.g4 | 87 +++++++++++++++++
src/main/java/module-info.java | 1 -
.../jabref/logic/bst/BstPreviewLayout.java | 2 +-
src/main/java/org/jabref/logic/bst/VM.java | 73 ++++++++------
.../java/org/jabref/logic/bst/TestVM.java | 8 +-
7 files changed, 143 insertions(+), 138 deletions(-)
delete mode 100644 src/main/antlr3/org/jabref/bst/Bst.g
create mode 100644 src/main/antlr4/org/jabref/bst/Bst.g4
diff --git a/build.gradle b/build.gradle
index 5c364f6717d..a7d15588eb3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -85,7 +85,6 @@ repositories {
}
configurations {
- antlr3
antlr4
// TODO: Remove the following workaround for split error messages such as
// error: module java.xml.bind reads package javax.annotation from both jsr305 and java.annotation
@@ -136,9 +135,6 @@ dependencies {
implementation 'io.github.java-diff-utils:java-diff-utils:4.11'
implementation 'info.debatty:java-string-similarity:2.0.0'
- antlr3 'org.antlr:antlr:3.5.3'
- implementation 'org.antlr:antlr-runtime:3.5.2'
-
antlr4 'org.antlr:antlr4:4.9.3'
implementation 'org.antlr:antlr4-runtime:4.9.3'
@@ -271,14 +267,14 @@ task generateSource(dependsOn: ["generateBstGrammarSource",
}
tasks.register("generateBstGrammarSource", JavaExec) {
- main = "org.antlr.Tool"
- classpath = configurations.antlr3
+ main = "org.antlr.v4.Tool"
+ classpath = configurations.antlr4
group = "JabRef"
- description = 'Generates BstLexer.java and BstParser.java from the Bst.g grammar file using antlr3.'
+ description = 'Generates BstLexer.java and BstParser.java from the Bst.g grammar file using antlr4.'
- inputs.dir('src/main/antlr3/org/jabref/bst/')
+ inputs.dir('src/main/antlr4/org/jabref/bst/')
outputs.dir("src-gen/main/java/org/jabref/logic/bst/")
- args = ["-o", "src-gen/main/java/org/jabref/logic/bst/" , "$projectDir/src/main/antlr3/org/jabref/bst/Bst.g" ]
+ args = ["-o", "src-gen/main/java/org/jabref/logic/bst/", "-listener", "-package", "org.jabref.logic.bst", "$projectDir/src/main/antlr4/org/jabref/bst/Bst.g4"]
}
tasks.register("generateSearchGrammarSource", JavaExec) {
diff --git a/src/main/antlr3/org/jabref/bst/Bst.g b/src/main/antlr3/org/jabref/bst/Bst.g
deleted file mode 100644
index 498621ad1a1..00000000000
--- a/src/main/antlr3/org/jabref/bst/Bst.g
+++ /dev/null
@@ -1,96 +0,0 @@
-grammar Bst;
-
-options {
- output=AST;
-}
-
-tokens {
- IDLIST;
- STACK;
- ENTRY;
- COMMANDS;
-}
-
-// applies only to the parser:
-@header {// Generated by ANTLR
-package org.jabref.logic.bst;}
-
-// applies only to the lexer:
-@lexer::header {// Generated by ANTLR
-package org.jabref.logic.bst;}
-
-program : commands+ -> ^(COMMANDS commands+);
-
-commands
- : STRINGS^ idList
- | INTEGERS^ idList
- | FUNCTION^ id stack
- | MACRO^ id '{'! STRING '}'!
- | READ^
- | EXECUTE^ '{'! function '}'!
- | ITERATE^ '{'! function '}'!
- | REVERSE^ '{'! function '}'!
- | ENTRY^ idList0 idList0 idList0
- | SORT^;
-
-identifier
- : IDENTIFIER;
-
-id
- : '{'! identifier '}'!;
-
-idList
- : '{' identifier+ '}' -> ^(IDLIST identifier+);
-
-idList0
- : '{' identifier* '}' -> ^(IDLIST identifier*);
-
-function
- : '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier;
-
-stack
- : '{' stackitem+ '}' -> ^(STACK stackitem+);
-
-stackitem
- : function
- | STRING
- | INTEGER
- | QUOTED
- | stack;
-
-STRINGS : 'STRINGS';
-INTEGERS : 'INTEGERS';
-FUNCTION : 'FUNCTION';
-EXECUTE : 'EXECUTE';
-SORT : 'SORT';
-ITERATE : 'ITERATE';
-REVERSE : 'REVERSE';
-ENTRY : 'ENTRY';
-READ : 'READ';
-MACRO : 'MACRO';
-
-QUOTED
- : '\'' IDENTIFIER;
-
-IDENTIFIER
- : LETTER (LETTER|NUMERAL|'_')* ;
-
-fragment LETTER
- : ('a'..'z'|'A'..'Z'|'.'|'$');
-
-STRING
- : '"' (~('"'))* '"';
-
-INTEGER
- : '#' ('+'|'-')? NUMERAL+ ;
-
-fragment NUMERAL
- : ('0'..'9');
-
-WS
- : (' '|'\t'|'\n'|'\r')+ {_channel=99;} ;
-
-LINE_COMMENT
- : '%' ~('\n'|'\r')* '\r'? '\n' {_channel=99;}
- ;
-
diff --git a/src/main/antlr4/org/jabref/bst/Bst.g4 b/src/main/antlr4/org/jabref/bst/Bst.g4
new file mode 100644
index 00000000000..c6faaa0727a
--- /dev/null
+++ b/src/main/antlr4/org/jabref/bst/Bst.g4
@@ -0,0 +1,87 @@
+grammar Bst;
+
+// Lexer
+
+STRINGS : 'STRINGS';
+INTEGERS : 'INTEGERS';
+FUNCTION : 'FUNCTION';
+EXECUTE : 'EXECUTE';
+SORT : 'SORT';
+ITERATE : 'ITERATE';
+REVERSE : 'REVERSE';
+ENTRY : 'ENTRY';
+READ : 'READ';
+MACRO : 'MACRO';
+
+LBRACE : '{';
+RBRACE : '}';
+GT : '>';
+LT : '<';
+EQUAL : '=';
+ASSIGN : ':=';
+ADD : '+';
+SUB : '-';
+MUL : '*';
+
+fragment LETTER : ('a'..'z'|'A'..'Z'|'.'|'$');
+fragment DIGIT : [0-9];
+
+IDENTIFIER : LETTER (LETTER|DIGIT|'_')*;
+INTEGER : '#' ('+'|'-')? DIGIT+;
+QUOTED : '\'' IDENTIFIER;
+STRING : '"' (~('"'))* '"';
+
+WS: [ \r\n\t]+ -> skip;
+LINE_COMMENT : '%' ~('\n'|'\r')* '\r'? '\n' -> skip;
+
+// Parser
+
+start
+ : commands+ EOF
+ ;
+
+commands
+ : STRINGS idList
+ | INTEGERS idList
+ | FUNCTION id stack
+ | MACRO id
+ | READ
+ | EXECUTE LBRACE function RBRACE
+ | ITERATE LBRACE function RBRACE
+ | REVERSE LBRACE function RBRACE
+ | ENTRY idList0 idList0 idList0
+ | SORT
+ ;
+
+
+identifier
+ : IDENTIFIER
+ ;
+
+id : LBRACE identifier RBRACE
+ ;
+
+idList
+ : LBRACE IDENTIFIER+ RBRACE
+ ;
+
+idList0
+ : LBRACE IDENTIFIER* RBRACE
+ ;
+
+function
+ : LT | GT | EQUAL | ADD | SUB | ASSIGN | MUL
+ | identifier
+ ;
+
+stack
+ : LBRACE stackitem+ RBRACE
+ ;
+
+stackitem
+ : function
+ | STRING
+ | INTEGER
+ | QUOTED
+ | stack
+ ;
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index ca408a86348..bdb7fc7bedd 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -85,7 +85,6 @@
requires org.mariadb.jdbc;
uses org.mariadb.jdbc.credential.CredentialPlugin;
requires org.apache.commons.lang3;
- requires antlr.runtime;
requires org.antlr.antlr4.runtime;
requires org.fxmisc.flowless;
requires org.apache.tika.core;
diff --git a/src/main/java/org/jabref/logic/bst/BstPreviewLayout.java b/src/main/java/org/jabref/logic/bst/BstPreviewLayout.java
index d0c040842fd..eb0c623f053 100644
--- a/src/main/java/org/jabref/logic/bst/BstPreviewLayout.java
+++ b/src/main/java/org/jabref/logic/bst/BstPreviewLayout.java
@@ -34,7 +34,7 @@ public BstPreviewLayout(Path path) {
return;
}
try {
- vm = new VM(path.toFile());
+ vm = new VM(path);
} catch (Exception e) {
LOGGER.error("Could not read {}.", path.toAbsolutePath(), e);
error = Localization.lang("Error opening file '%0'.", path.toString());
diff --git a/src/main/java/org/jabref/logic/bst/VM.java b/src/main/java/org/jabref/logic/bst/VM.java
index caaf9078f64..79fa8e63281 100644
--- a/src/main/java/org/jabref/logic/bst/VM.java
+++ b/src/main/java/org/jabref/logic/bst/VM.java
@@ -1,7 +1,7 @@
package org.jabref.logic.bst;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
@@ -26,13 +26,17 @@
import org.jabref.model.entry.field.FieldFactory;
import org.jabref.model.entry.field.StandardField;
-import org.antlr.runtime.ANTLRFileStream;
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CharStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.Tree;
+import org.antlr.v4.runtime.BailErrorStrategy;
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.Tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,7 +45,7 @@
*
* Documentation can be found in the original bibtex distribution:
*
- * https://www.ctan.org/pkg/bibtex
+ * https://www.ctan.org/pkg/bibtex
*/
public class VM implements Warn {
@@ -65,14 +69,26 @@ public class VM implements Warn {
private final Map buildInFunctions;
- private File file;
+ private Path path;
- private final CommonTree tree;
+ private final ParseTree tree;
private StringBuilder bbl;
private String preamble = "";
+ public static class ThrowingErrorListener extends BaseErrorListener {
+
+ public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();
+
+ @Override
+ public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol,
+ int line, int charPositionInLine, String msg, RecognitionException e)
+ throws ParseCancellationException {
+ throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg);
+ }
+ }
+
public static class Identifier {
public final String name;
@@ -104,20 +120,20 @@ public interface BstFunction {
void execute(BstEntry context);
}
- public VM(File f) throws RecognitionException, IOException {
- this(new ANTLRFileStream(f.getPath()));
- this.file = f;
+ public VM(Path path) throws RecognitionException, IOException {
+ this(CharStreams.fromPath(path));
+ this.path = path;
}
public VM(String s) throws RecognitionException {
- this(new ANTLRStringStream(s));
+ this(CharStreams.fromString(s));
}
private VM(CharStream bst) throws RecognitionException {
this(VM.charStream2CommonTree(bst));
}
- private VM(CommonTree tree) {
+ private VM(ParseTree tree) {
this.tree = tree;
this.buildInFunctions = new HashMap<>(37);
@@ -794,12 +810,15 @@ private void addPeriodFunction() {
}
}
- private static CommonTree charStream2CommonTree(CharStream bst) throws RecognitionException {
- BstLexer lex = new BstLexer(bst);
- CommonTokenStream tokens = new CommonTokenStream(lex);
- BstParser parser = new BstParser(tokens);
- BstParser.program_return r = parser.program();
- return (CommonTree) r.getTree();
+ private static ParseTree charStream2CommonTree(CharStream query) throws RecognitionException {
+ BstLexer lexer = new BstLexer(query);
+ lexer.removeErrorListeners(); // no infos on file system
+ lexer.addErrorListener(ThrowingErrorListener.INSTANCE);
+ BstParser parser = new BstParser(new CommonTokenStream(lexer));
+ parser.removeErrorListeners(); // no infos on file system
+ parser.addErrorListener(ThrowingErrorListener.INSTANCE);
+ parser.setErrorHandler(new BailErrorStrategy()); // ParseCancelationException on parse errors
+ return parser.start();
}
private boolean assign(BstEntry context, Object o1, Object o2) {
@@ -1106,10 +1125,10 @@ public void execute(BstEntry context) {
break;
}
} catch (VMException e) {
- if (file == null) {
+ if (path == null) {
LOGGER.error("ERROR " + e.getMessage() + " (" + c.getLine() + ")");
} else {
- LOGGER.error("ERROR " + e.getMessage() + " (" + file.getPath() + ":"
+ LOGGER.error("ERROR " + e.getMessage() + " (" + path + ":"
+ c.getLine() + ")");
}
throw e;
@@ -1156,7 +1175,7 @@ private void execute(String name, BstEntry context) {
}
private void function(Tree child) {
- String name = child.getChild(0).getText();
+ String name = ((Token) child.getChild(0).getPayload()).getText();
Tree localStack = child.getChild(1);
functions.put(name, new StackFunction(localStack));
}
@@ -1170,7 +1189,7 @@ private void integers(Tree child) {
Tree t = child.getChild(0);
for (int i = 0; i < t.getChildCount(); i++) {
- String name = t.getChild(i).getText();
+ String name = ((Token) t.getChild(i).getPayload()).getText();
integers.put(name, 0);
}
}
@@ -1185,7 +1204,7 @@ private void strings(Tree child) {
Tree t = child.getChild(0);
for (int i = 0; i < t.getChildCount(); i++) {
- String name = t.getChild(i).getText();
+ String name = ((Token) t.getChild(i).getPayload()).getText();
strings.put(name, null);
}
}
diff --git a/src/test/java/org/jabref/logic/bst/TestVM.java b/src/test/java/org/jabref/logic/bst/TestVM.java
index bb9fc8ad193..a0bf9c0f76b 100644
--- a/src/test/java/org/jabref/logic/bst/TestVM.java
+++ b/src/test/java/org/jabref/logic/bst/TestVM.java
@@ -1,8 +1,8 @@
package org.jabref.logic.bst;
-import java.io.File;
import java.io.IOException;
import java.io.StringReader;
+import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -16,7 +16,7 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.util.DummyFileUpdateMonitor;
-import org.antlr.runtime.RecognitionException;
+import org.antlr.v4.runtime.RecognitionException;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
@@ -29,7 +29,7 @@ public class TestVM {
@Test
public void testAbbrv() throws RecognitionException, IOException {
- VM vm = new VM(new File("src/test/resources/org/jabref/logic/bst/abbrv.bst"));
+ VM vm = new VM(Path.of("src/test/resources/org/jabref/logic/bst/abbrv.bst"));
List v = List.of(t1BibtexEntry());
String expected = "\\begin{thebibliography}{1}\\bibitem{canh05}K.~Crowston, H.~Annabi, J.~Howison, and C.~Masango.\\newblock Effective work practices for floss development: A model and propositions.\\newblock In {\\em Hawaii International Conference On System Sciences (HICSS)}, 2005.\\end{thebibliography}";
@@ -607,7 +607,7 @@ public void testVMSwap() throws RecognitionException {
@Test
public void testHypthenatedName() throws RecognitionException, IOException {
- VM vm = new VM(new File("src/test/resources/org/jabref/logic/bst/abbrv.bst"));
+ VM vm = new VM(Path.of("src/test/resources/org/jabref/logic/bst/abbrv.bst"));
List v = List.of(TestVM.bibtexString2BibtexEntry("@article{canh05, author = \"Jean-Paul Sartre\" }"));
assertTrue(vm.run(v).contains("J.-P. Sartre"));
}
From 08c6a77972b52aa459568caf672b87ba34b3ec02 Mon Sep 17 00:00:00 2001
From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Date: Thu, 26 May 2022 01:32:16 +0200
Subject: [PATCH 02/39] apply ide suggestions
---
src/main/java/org/jabref/logic/bst/VM.java | 118 +++++++-----------
.../java/org/jabref/logic/bst/TestVM.java | 16 ++-
2 files changed, 52 insertions(+), 82 deletions(-)
diff --git a/src/main/java/org/jabref/logic/bst/VM.java b/src/main/java/org/jabref/logic/bst/VM.java
index 79fa8e63281..350029d0dfb 100644
--- a/src/main/java/org/jabref/logic/bst/VM.java
+++ b/src/main/java/org/jabref/logic/bst/VM.java
@@ -307,12 +307,10 @@ private VM(ParseTree tree) {
}
Object o1 = stack.pop();
- if (!((o1 instanceof String) && (((String) o1).length() == 1))) {
+ if (!((o1 instanceof String s) && (((String) o1).length() == 1))) {
throw new VMException("Can only perform chr.to.int$ on string with length 1");
}
- String s = (String) o1;
-
stack.push((int) s.charAt(0));
});
@@ -356,12 +354,10 @@ private VM(ParseTree tree) {
return;
}
- if (!(o1 instanceof String)) {
+ if (!(o1 instanceof String s)) {
throw new VMException("Operand does not match function empty$");
}
- String s = (String) o1;
-
stack.push("".equals(s.trim()) ? VM.TRUE : VM.FALSE);
});
@@ -404,12 +400,10 @@ private VM(ParseTree tree) {
}
Object o1 = stack.pop();
- if (!(o1 instanceof Integer)) {
+ if (!(o1 instanceof Integer i)) {
throw new VMException("Can only perform operation int.to.chr$ on an Integer");
}
- Integer i = (Integer) o1;
-
stack.push(String.valueOf((char) i.intValue()));
});
@@ -475,10 +469,9 @@ private VM(ParseTree tree) {
}
Object o1 = stack.pop();
- if (!(o1 instanceof String)) {
+ if (!(o1 instanceof String s)) {
throw new VMException("Need a string at the top of the stack for num.names$");
}
- String s = (String) o1;
stack.push(AuthorList.parse(s).getNumberOfAuthors());
});
@@ -496,9 +489,7 @@ private VM(ParseTree tree) {
*
* @PREAMBLE strings read from the database files.
*/
- buildInFunctions.put("preamble$", context -> {
- stack.push(preamble);
- });
+ buildInFunctions.put("preamble$", context -> stack.push(preamble));
/*
* Pops the top (string) literal, removes nonalphanumeric characters
@@ -644,11 +635,10 @@ private void textLengthFunction() {
}
Object o1 = stack.pop();
- if (!(o1 instanceof String)) {
+ if (!(o1 instanceof String s)) {
throw new VMException("Can only perform operation on a string text.length$");
}
- String s = (String) o1;
char[] c = s.toCharArray();
int result = 0;
@@ -752,13 +742,10 @@ private void substringFunction() {
Object o2 = stack.pop();
Object o3 = stack.pop();
- if (!((o1 instanceof Integer) && (o2 instanceof Integer) && (o3 instanceof String))) {
+ if (!((o1 instanceof Integer len) && (o2 instanceof Integer start) && (o3 instanceof String s))) {
throw new VMException("Expecting two integers and a string for substring$");
}
- Integer len = (Integer) o1;
- Integer start = (Integer) o2;
-
int lenI = len;
int startI = start;
@@ -774,8 +761,6 @@ private void substringFunction() {
startI = -Integer.MIN_VALUE / 2;
}
- String s = (String) o3;
-
if (startI < 0) {
startI += s.length() + 1;
startI = Math.max(1, (startI + 1) - lenI);
@@ -789,11 +774,10 @@ private void addPeriodFunction() {
}
Object o1 = stack.pop();
- if (!(o1 instanceof String)) {
+ if (!(o1 instanceof String s)) {
throw new VMException("Can only add a period to a string for add.period$");
}
- String s = (String) o1;
Matcher m = ADD_PERIOD_PATTERN.matcher(s);
if (m.find()) {
@@ -896,39 +880,28 @@ public String run(Collection bibEntries, BibDatabase bibDatabase) {
for (int i = 0; i < tree.getChildCount(); i++) {
Tree child = tree.getChild(i);
switch (child.getType()) {
- case BstParser.STRINGS:
- strings(child);
- break;
- case BstParser.INTEGERS:
- integers(child);
- break;
- case BstParser.FUNCTION:
- function(child);
- break;
- case BstParser.EXECUTE:
- execute(child);
- break;
- case BstParser.SORT:
- sort();
- break;
- case BstParser.ITERATE:
- iterate(child);
- break;
- case BstParser.REVERSE:
- reverse(child);
- break;
- case BstParser.ENTRY:
- entry(child);
- break;
- case BstParser.READ:
- read(bibDatabase);
- break;
- case BstParser.MACRO:
- macro(child);
- break;
- default:
- LOGGER.info("Unknown type: {}", child.getType());
- break;
+ case BstParser.STRINGS ->
+ strings(child);
+ case BstParser.INTEGERS ->
+ integers(child);
+ case BstParser.FUNCTION ->
+ function(child);
+ case BstParser.EXECUTE ->
+ execute(child);
+ case BstParser.SORT ->
+ sort();
+ case BstParser.ITERATE ->
+ iterate(child);
+ case BstParser.REVERSE ->
+ reverse(child);
+ case BstParser.ENTRY ->
+ entry(child);
+ case BstParser.READ ->
+ read(bibDatabase);
+ case BstParser.MACRO ->
+ macro(child);
+ default ->
+ LOGGER.info("Unknown type: {}", child.getType());
}
}
@@ -960,7 +933,7 @@ private void read(BibDatabase bibDatabase) {
// We nevertheless want to have the full month name.
// Thus, we lookup the full month name here.
return Month.parse(result)
- .map(month -> month.getFullName())
+ .map(Month::getFullName)
.orElse(result);
}
return result;
@@ -1076,8 +1049,7 @@ private void sort() {
}
private void executeInContext(Object o, BstEntry context) {
- if (o instanceof Tree) {
- Tree t = (Tree) o;
+ if (o instanceof Tree t) {
new StackFunction(t).execute(context);
} else if (o instanceof Identifier) {
execute(((Identifier) o).getName(), context);
@@ -1107,22 +1079,18 @@ public void execute(BstEntry context) {
try {
switch (c.getType()) {
- case BstParser.STRING:
+ case BstParser.STRING -> {
String s = c.getText();
push(s.substring(1, s.length() - 1));
- break;
- case BstParser.INTEGER:
- push(Integer.parseInt(c.getText().substring(1)));
- break;
- case BstParser.QUOTED:
- push(new Identifier(c.getText().substring(1)));
- break;
- case BstParser.STACK:
- push(c);
- break;
- default:
- VM.this.execute(c.getText(), context);
- break;
+ }
+ case BstParser.INTEGER ->
+ push(Integer.parseInt(c.getText().substring(1)));
+ case BstParser.QUOTED ->
+ push(new Identifier(c.getText().substring(1)));
+ case BstParser.STACK ->
+ push(c);
+ default ->
+ VM.this.execute(c.getText(), context);
}
} catch (VMException e) {
if (path == null) {
@@ -1197,8 +1165,6 @@ private void integers(Tree child) {
/**
* Declares global string variables. It has one argument, a list of variable names. You may have any number of these
* commands, but a variable's declaration must precede its use.
- *
- * @param child
*/
private void strings(Tree child) {
Tree t = child.getChild(0);
diff --git a/src/test/java/org/jabref/logic/bst/TestVM.java b/src/test/java/org/jabref/logic/bst/TestVM.java
index a0bf9c0f76b..97dc0c9bb25 100644
--- a/src/test/java/org/jabref/logic/bst/TestVM.java
+++ b/src/test/java/org/jabref/logic/bst/TestVM.java
@@ -620,12 +620,16 @@ private static BibEntry bibtexString2BibtexEntry(String s) throws IOException {
}
private static String t1BibtexString() {
- return "@inproceedings{canh05,\n"
- + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},\n"
- + " title = {Effective work practices for floss development: A model and propositions},\n"
- + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},\n"
- + " year = {2005},\n" + " owner = {oezbek},\n" + " timestamp = {2006.05.29},\n"
- + " url = {http://james.howison.name/publications.html}}\n";
+ return """
+ @inproceedings{canh05,
+ author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},
+ title = {Effective work practices for floss development: A model and propositions},
+ booktitle = {Hawaii International Conference On System Sciences (HICSS)},
+ year = {2005},
+ owner = {oezbek},
+ timestamp = {2006.05.29},
+ url = {http://james.howison.name/publications.html}}
+ """;
}
private static BibEntry t1BibtexEntry() throws IOException {
From 7a33e9f0366530e0bbed2a7b7e7b1f2f08fecba6 Mon Sep 17 00:00:00 2001
From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Date: Thu, 26 May 2022 22:30:04 +0200
Subject: [PATCH 03/39] Refactor
---
build.gradle | 2 +-
src/main/antlr4/org/jabref/bst/Bst.g4 | 44 +-
.../java/org/jabref/logic/bst/BstEntry.java | 22 +
.../jabref/logic/bst/ChangeCaseFunction.java | 65 -
.../jabref/logic/bst/FormatNameFunction.java | 67 -
.../org/jabref/logic/bst/PurifyFunction.java | 43 -
.../jabref/logic/bst/TextPrefixFunction.java | 54 -
src/main/java/org/jabref/logic/bst/VM.java | 1316 +++++++++--------
src/main/java/org/jabref/logic/bst/Warn.java | 7 -
.../org/jabref/logic/bst/WidthFunction.java | 43 -
.../bst/{ => util}/BibtexCaseChanger.java | 43 +-
.../bst/{ => util}/BibtexNameFormatter.java | 77 +-
.../logic/bst/{ => util}/BibtexPurify.java | 21 +-
.../bst/{ => util}/BibtexTextPrefix.java | 17 +-
.../logic/bst/{ => util}/BibtexWidth.java | 2 +-
.../logic/layout/format/NameFormatter.java | 6 +-
.../logic/bst/BibtexCaseChangersTest.java | 3 +-
.../logic/bst/BibtexNameFormatterTest.java | 41 +-
.../jabref/logic/bst/BibtexPurifyTest.java | 5 +-
.../org/jabref/logic/bst/BibtexWidthTest.java | 2 +
.../java/org/jabref/logic/bst/TestVM.java | 1 -
.../logic/bst/TextPrefixFunctionTest.java | 5 +-
22 files changed, 859 insertions(+), 1027 deletions(-)
create mode 100644 src/main/java/org/jabref/logic/bst/BstEntry.java
delete mode 100644 src/main/java/org/jabref/logic/bst/ChangeCaseFunction.java
delete mode 100644 src/main/java/org/jabref/logic/bst/FormatNameFunction.java
delete mode 100644 src/main/java/org/jabref/logic/bst/PurifyFunction.java
delete mode 100644 src/main/java/org/jabref/logic/bst/TextPrefixFunction.java
delete mode 100644 src/main/java/org/jabref/logic/bst/Warn.java
delete mode 100644 src/main/java/org/jabref/logic/bst/WidthFunction.java
rename src/main/java/org/jabref/logic/bst/{ => util}/BibtexCaseChanger.java (91%)
rename src/main/java/org/jabref/logic/bst/{ => util}/BibtexNameFormatter.java (81%)
rename src/main/java/org/jabref/logic/bst/{ => util}/BibtexPurify.java (82%)
rename src/main/java/org/jabref/logic/bst/{ => util}/BibtexTextPrefix.java (87%)
rename src/main/java/org/jabref/logic/bst/{ => util}/BibtexWidth.java (99%)
diff --git a/build.gradle b/build.gradle
index a7d15588eb3..98cf03c87d6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -274,7 +274,7 @@ tasks.register("generateBstGrammarSource", JavaExec) {
inputs.dir('src/main/antlr4/org/jabref/bst/')
outputs.dir("src-gen/main/java/org/jabref/logic/bst/")
- args = ["-o", "src-gen/main/java/org/jabref/logic/bst/", "-listener", "-package", "org.jabref.logic.bst", "$projectDir/src/main/antlr4/org/jabref/bst/Bst.g4"]
+ args = ["-o", "src-gen/main/java/org/jabref/logic/bst/", "-visitor", "-no-listener", "-package", "org.jabref.logic.bst", "$projectDir/src/main/antlr4/org/jabref/bst/Bst.g4"]
}
tasks.register("generateSearchGrammarSource", JavaExec) {
diff --git a/src/main/antlr4/org/jabref/bst/Bst.g4 b/src/main/antlr4/org/jabref/bst/Bst.g4
index c6faaa0727a..683c60a1e94 100644
--- a/src/main/antlr4/org/jabref/bst/Bst.g4
+++ b/src/main/antlr4/org/jabref/bst/Bst.g4
@@ -21,7 +21,7 @@ EQUAL : '=';
ASSIGN : ':=';
ADD : '+';
SUB : '-';
-MUL : '*';
+CONCAT : '*';
fragment LETTER : ('a'..'z'|'A'..'Z'|'.'|'$');
fragment DIGIT : [0-9];
@@ -41,37 +41,35 @@ start
;
commands
- : STRINGS idList
- | INTEGERS idList
- | FUNCTION id stack
- | MACRO id
- | READ
- | EXECUTE LBRACE function RBRACE
- | ITERATE LBRACE function RBRACE
- | REVERSE LBRACE function RBRACE
- | ENTRY idList0 idList0 idList0
- | SORT
+ : list=(STRINGS|INTEGERS) id=idListObl #variablesCommand
+ | FUNCTION LBRACE id=identifier RBRACE exp=stack #functionCommand
+ | list=MACRO LBRACE id=identifier RBRACE LBRACE exp=STRING RBRACE #variablesCommand
+ | READ #readCommand
+ | EXECUTE LBRACE id=function RBRACE #executeCommand
+ | ITERATE LBRACE id=function RBRACE #iterateCommand
+ | REVERSE LBRACE id=function RBRACE #reverseCommand
+ | ENTRY first=idListOpt second=idListOpt third=idListOpt #entryCommand
+ | SORT #sortCommand
;
-
identifier
- : IDENTIFIER
- ;
-
-id : LBRACE identifier RBRACE
- ;
+ : IDENTIFIER
+ ;
-idList
- : LBRACE IDENTIFIER+ RBRACE
+idListObl
+ : LBRACE identifier+ RBRACE
;
-idList0
- : LBRACE IDENTIFIER* RBRACE
+idListOpt
+ : LBRACE identifier* RBRACE
;
function
- : LT | GT | EQUAL | ADD | SUB | ASSIGN | MUL
- | identifier
+ : operator=(LT | GT | EQUAL) #comparisonFunction
+ | operator=(ADD | SUB) #arithmeticFunction
+ | ASSIGN #assignmentFunction
+ | CONCAT #concatFunction
+ | identifier #userFunction
;
stack
diff --git a/src/main/java/org/jabref/logic/bst/BstEntry.java b/src/main/java/org/jabref/logic/bst/BstEntry.java
new file mode 100644
index 00000000000..0edf00515ab
--- /dev/null
+++ b/src/main/java/org/jabref/logic/bst/BstEntry.java
@@ -0,0 +1,22 @@
+package org.jabref.logic.bst;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jabref.model.entry.BibEntry;
+
+public class BstEntry {
+
+ public final BibEntry entry;
+
+ public final Map localStrings = new HashMap<>();
+
+ // keys filled by org.jabref.logic.bst.VM.entry based on the contents of the bst file
+ public final Map fields = new HashMap<>();
+
+ public final Map localIntegers = new HashMap<>();
+
+ public BstEntry(BibEntry e) {
+ this.entry = e;
+ }
+}
diff --git a/src/main/java/org/jabref/logic/bst/ChangeCaseFunction.java b/src/main/java/org/jabref/logic/bst/ChangeCaseFunction.java
deleted file mode 100644
index 65f4f64c619..00000000000
--- a/src/main/java/org/jabref/logic/bst/ChangeCaseFunction.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.jabref.logic.bst;
-
-import java.util.Locale;
-import java.util.Stack;
-
-import org.jabref.logic.bst.BibtexCaseChanger.FORMAT_MODE;
-import org.jabref.logic.bst.VM.BstEntry;
-import org.jabref.logic.bst.VM.BstFunction;
-
-/**
- * From the Bibtex manual:
- *
- * Pops the top two (string) literals; it changes the case of the second
- * according to the specifications of the first, as follows. (Note: The word
- * `letters' in the next sentence refers only to those at brace-level 0, the
- * top-most brace level; no other characters are changed, except perhaps for
- * \special characters", described in Section 4.) If the first literal is the
- * string `t', it converts to lower case all letters except the very first
- * character in the string, which it leaves alone, and except the first
- * character following any colon and then nonnull white space, which it also
- * leaves alone; if it's the string `l', it converts all letters to lower case;
- * and if it's the string `u', it converts all letters to upper case. It then
- * pushes this resulting string. If either type is incorrect, it complains and
- * pushes the null string; however, if both types are correct but the
- * specification string (i.e., the first string) isn't one of the legal ones, it
- * merely pushes the second back onto the stack, after complaining. (Another
- * note: It ignores case differences in the specification string; for example,
- * the strings t and T are equivalent for the purposes of this built-in
- * function.)
- *
- * Christopher: I think this should be another grammar! This parser is horrible.
- *
- */
-public class ChangeCaseFunction implements BstFunction {
-
- private final VM vm;
-
- public ChangeCaseFunction(VM vm) {
- this.vm = vm;
- }
-
- @Override
- public void execute(BstEntry context) {
- Stack