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

Fix BibTeX VM for IEEE (and some micro other fixes) #5839

Merged
merged 1 commit into from
Jan 18, 2020
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# no generated files in version control
src/main/gen/
src/main/generated/

# private data
/buildres/jabref-cert-2016.p12
Expand Down
6 changes: 6 additions & 0 deletions external-libraries.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ In case you add a library, please use these identifiers.
For instance, "BSD" is not exact enough, there are numerous variants out there: BSD-2-Clause, BSD-3-Clause-No-Nuclear-Warranty, ...
Note that the SPDX license identifiers are different from the ones used by debian. See https://wiki.debian.org/Proposals/CopyrightFormat for more information.

# bst files

Project: IEEEtran
Path: src/main/resources/bst/IEEEtran.bst
URL: https://www.ctan.org/tex-archive/macros/latex/contrib/IEEEtran/bibtex
License: LPPL-1.3

# Fonts and Icons

Expand Down
2 changes: 1 addition & 1 deletion src/main/antlr3/org/jabref/bst/Bst.g
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ QUOTED
: '\'' IDENTIFIER;

IDENTIFIER
: LETTER (LETTER|NUMERAL)* ;
: LETTER (LETTER|NUMERAL|'_')* ;

fragment LETTER
: ('a'..'z'|'A'..'Z'|'.'|'$');
Expand Down
193 changes: 94 additions & 99 deletions src/main/java/org/jabref/logic/bst/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -31,15 +32,12 @@
import org.slf4j.LoggerFactory;

/**
*
* A Bibtex Virtual machine that can execute .bst files.
*
* A BibTeX Virtual machine that can execute .bst files.
* <p>
* Documentation can be found in the original bibtex distribution:
*
* <p>
* https://www.ctan.org/pkg/bibtex
*
*/

public class VM implements Warn {

public static final Integer FALSE = 0;
Expand Down Expand Up @@ -74,7 +72,6 @@ public static class Identifier {

public final String name;


public Identifier(String name) {
this.name = name;
}
Expand All @@ -88,7 +85,6 @@ public static class Variable {

public final String name;


public Variable(String name) {
this.name = name;
}
Expand All @@ -103,7 +99,6 @@ public interface BstFunction {
void execute(BstEntry context);
}


public VM(File f) throws RecognitionException, IOException {
this(new ANTLRFileStream(f.getPath()));
this.file = f;
Expand Down Expand Up @@ -225,7 +220,16 @@ private VM(CommonTree tree) {
Object o2 = stack.pop();
Object o1 = stack.pop();

if (o1 == null) {
o1 = "";
}
if (o2 == null) {
o2 = "";
}

if (!((o1 instanceof String) && (o2 instanceof String))) {
LOGGER.error("o1: {} ({})", o1, o1.getClass());
LOGGER.error("o2: {} ({})", o2, o2.getClass());
throw new VMException("Can only concatenate two String with *");
}

Expand Down Expand Up @@ -493,7 +497,7 @@ private VM(CommonTree tree) {
* Is a no-op.
*/
buildInFunctions.put("skip$", context -> {
// Nothing to do! Yeah!
// Nothing to do! Yeah!
});

/*
Expand Down Expand Up @@ -613,7 +617,6 @@ public void execute(BstEntry context) {
String s = (String) stack.pop();
VM.this.bbl.append(s);
});

}

private void textLengthFunction() {
Expand Down Expand Up @@ -816,7 +819,6 @@ private boolean assign(BstEntry context, Object o1, Object o2) {
return true;
}
return false;

}

if ((context != null) && context.localIntegers.containsKey(name)) {
Expand All @@ -837,6 +839,15 @@ public String run(BibDatabase db) {
}

public String run(Collection<BibEntry> bibtex) {
return this.run(bibtex, null);
}

/**
* @param bibtex list of entries to convert
* @param bibDatabase (may be null) the bibDatabase used for resolving strings / crossref
*/
public String run(Collection<BibEntry> bibtex, BibDatabase bibDatabase) {
Objects.requireNonNull(bibtex);

// Reset
bbl = new StringBuilder();
Expand All @@ -862,59 +873,58 @@ public String run(Collection<BibEntry> bibtex) {
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();
break;
case BstParser.MACRO:
macro(child);
break;
default:
LOGGER.info("Unknown type: " + child.getType());
break;
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;
}
}

return bbl.toString();
}

/**
* Dredges up from the database file the field values for each entry in the
* list. It has no arguments. If a database entry doesn't have a value for a
* field (and probably no database entry will have a value for every field),
* that field variable is marked as missing for the entry.
*
* Dredges up from the database file the field values for each entry in the list. It has no arguments. If a database
* entry doesn't have a value for a field (and probably no database entry will have a value for every field), that
* field variable is marked as missing for the entry.
* <p>
* We use null for the missing entry designator.
* @param bibDatabase
*/
private void read() {
private void read(BibDatabase bibDatabase) {
for (BstEntry e : entries) {
for (Map.Entry<String, String> mEntry : e.getFields().entrySet()) {
Field field = FieldFactory.parseField(mEntry.getKey());
String fieldValue = e.getBibtexEntry().getField(field).orElse(null);

String fieldValue = e.getBibtexEntry().getResolvedFieldOrAlias(field, bibDatabase).orElse(null);
mEntry.setValue(fieldValue);
}
}
Expand All @@ -927,14 +937,11 @@ private void read() {
}

/**
* Defines a string macro. It has two arguments; the first is the macro's
* name, which is treated like any other variable or function name, and the
* second is its definition, which must be double-quote-delimited. You must
* have one for each three-letter month abbreviation; in addition, you
* should have one for common journal names. The user's database may
* override any definition you define using this command. If you want to
* define a string the user can't touch, use the FUNCTION command, which has
* a compatible syntax.
* Defines a string macro. It has two arguments; the first is the macro's name, which is treated like any other
* variable or function name, and the second is its definition, which must be double-quote-delimited. You must have
* one for each three-letter month abbreviation; in addition, you should have one for common journal names. The
* user's database may override any definition you define using this command. If you want to define a string the
* user can't touch, use the FUNCTION command, which has a compatible syntax.
*/
private void macro(Tree child) {
String name = child.getChild(0).getText();
Expand All @@ -946,7 +953,6 @@ public class MacroFunction implements BstFunction {

private final String replacement;


public MacroFunction(String replacement) {
this.replacement = replacement;
}
Expand All @@ -958,13 +964,11 @@ public void execute(BstEntry context) {
}

/**
* Declares the fields and entry variables. It has three arguments, each a
* (possibly empty) list of variable names. The three lists are of: fields,
* integer entry variables, and string entry variables. There is an
* additional field that BibTEX automatically declares, crossref, used for
* cross referencing. And there is an additional string entry variable
* automatically declared, sort.key$, used by the SORT command. Each of
* these variables has a value for each entry on the list.
* Declares the fields and entry variables. It has three arguments, each a (possibly empty) list of variable names.
* The three lists are of: fields, integer entry variables, and string entry variables. There is an additional field
* that BibTEX automatically declares, crossref, used for cross referencing. And there is an additional string entry
* variable automatically declared, sort.key$, used by the SORT command. Each of these variables has a value for
* each entry on the list.
*/
private void entry(Tree child) {
// Fields first
Expand Down Expand Up @@ -1044,7 +1048,6 @@ public class StackFunction implements BstFunction {

private final Tree localTree;


public StackFunction(Tree stack) {
localTree = stack;
}
Expand All @@ -1062,22 +1065,22 @@ public void execute(BstEntry context) {
try {

switch (c.getType()) {
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.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;
}
} catch (VMException e) {
if (file == null) {
Expand All @@ -1089,7 +1092,6 @@ public void execute(BstEntry context) {
throw e;
}
}

}
}

Expand Down Expand Up @@ -1136,16 +1138,12 @@ private void function(Tree child) {
String name = child.getChild(0).getText();
Tree localStack = child.getChild(1);
functions.put(name, new StackFunction(localStack));

}

/**
* Declares global integer variables. It has one argument, a list of
* variable names. There are two such automatically-declared variables,
* entry.max$ and global.max$, used for limiting the lengths of string vari-
* ables. You may have any number of these commands, but a variable's
* declaration must precede its use.
*
* Declares global integer variables. It has one argument, a list of variable names. There are two such
* automatically-declared variables, entry.max$ and global.max$, used for limiting the lengths of string vari-
* ables. You may have any number of these commands, but a variable's declaration must precede its use.
*/
private void integers(Tree child) {
Tree t = child.getChild(0);
Expand All @@ -1157,9 +1155,8 @@ 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.
* 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
*/
Expand All @@ -1182,7 +1179,6 @@ public static class BstEntry {

private final Map<String, Integer> localIntegers = new HashMap<>();


public BstEntry(BibEntry e) {
this.entry = e;
}
Expand Down Expand Up @@ -1232,5 +1228,4 @@ public Stack<Object> getStack() {
public void warn(String string) {
LOGGER.warn(string);
}

}
Loading