package net.sourceforge.texlipse.auxparser;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import net.sourceforge.texlipse.TexlipsePlugin;
import net.sourceforge.texlipse.model.ReferenceEntry;
import net.sourceforge.texlipse.properties.TexlipseProperties;
import net.sourceforge.texlipse.texparser.LatexLexer;
import net.sourceforge.texlipse.texparser.node.EOF;
import net.sourceforge.texlipse.texparser.node.TArgument;
import net.sourceforge.texlipse.texparser.node.TCcite;
import net.sourceforge.texlipse.texparser.node.TCsymbol;
import net.sourceforge.texlipse.texparser.node.TCword;
import net.sourceforge.texlipse.texparser.node.TWord;
import net.sourceforge.texlipse.texparser.node.Token;
/**
* Extracts information from the .aux file which is created by a latex run.
* If \include is used, several .aux-files exist. They are parsed recursively.
*
* At the moment, this information is used to
*
* 1) decide if bibtex needs to be invoked
*
* 2) to extract all labels for the whole document (some of them might be
* declared in self-defined latex commands, so the normal texlipse-parser
* does not find them
*
* further use cases are possible ...
*
* @author Frank Lehrieder
*
*/
public class AuxFileParser {
/**
* The corresponding project
*/
private IProject project;
/**
* The .aux-file of the main document
*/
private String rootAuxfile;
public AuxFileParser(IProject project, String auxFile) {
this.project = project;
this.rootAuxfile = auxFile;
}
public IProject getProject() {
return project;
}
public String getRootAuxFile() {
return rootAuxfile;
}
public List<String> getCitations() {
return doParse(rootAuxfile, "\\citation");
}
/**
* @return a list of all labels in the aux-file as
* <code>ReferenceEntry</code>
*/
public List<ReferenceEntry> getLabels() {
List<String> labels = doParse(rootAuxfile, "\\newlabel");
List<ReferenceEntry> result = new LinkedList<ReferenceEntry>();
for (String key : labels) {
result.add(new ReferenceEntry(key, "No info available"));
}
return result;
}
/**
* Parses <code>input</code> and collects all tokens which follow the given
* <code>command</code>. Used to extract e.g., labels, citations, bibcites
*
* @param filename name of the file to be parsed
* @param command
* @return list of Strings following the given command
*/
private List<String> doParse(String filename, String command) {
IResource auxFile = project.getFile(filename);
String input = null;
try {
input = TexlipseProperties.getFileContents(auxFile);
} catch (IOException e) {
TexlipsePlugin.log("Could not parse .aux-file " + auxFile, e);
return new LinkedList<String>();
}
LatexLexer lexer = new LatexLexer(new PushbackReader(new StringReader(input), 4096));
Token prevCommand = null;
Token prevSymbol = null;
Token prevText = null;
List<String> results = new LinkedList<String>();
try {
for (Token t = lexer.next(); !(t instanceof EOF); t = lexer.next()) {
// extract the strings following <code>command</code>
if (prevCommand == null) {
if ((t instanceof TCword || t instanceof TCcite)
&& t.getText().equalsIgnoreCase(command)) {
prevCommand = t;
}
} else {
if (t instanceof TWord || t instanceof TArgument) {
if (command.equalsIgnoreCase(prevCommand.getText())) {
results.add(t.getText());
prevCommand = null;
}
}
}
// look for additional .aux-files and parse them
if (prevText != null) {
if (prevText.getText().equalsIgnoreCase("input") &&
t instanceof TWord) {
prevText = null;
String newAuxFileName = t.getText();
results.addAll(doParse(newAuxFileName, command));
}
}
if (prevSymbol == null) {
if (t instanceof TCsymbol) {
prevSymbol = t;
}
} else {
if (prevSymbol.getText().equals("\\@")) {
prevText = t;
}
prevSymbol = null;
}
}
} catch (Exception e) {
// do nothing
}
return results;
}
}