Skip to content

Adding start and stop offsets to CQLNodes objects #19

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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
17 changes: 16 additions & 1 deletion src/main/java/org/z3950/zing/cql/CQLNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
*
*/
public abstract class CQLNode {


private int start = -1, stop = -1;

public abstract void traverse(CQLNodeVisitor visitor);

/**
Expand All @@ -25,6 +27,19 @@ public String getResultSetName() {
return null;
}

public int getStart() {
return start;
}

public int getStop() {
return stop;
}

protected void setStartStop(int start, int stop) {
this.start = start;
this.stop = stop;
}

/**
* Translates a parse-tree into an XCQL document.
* @return
Expand Down
40 changes: 37 additions & 3 deletions src/main/java/org/z3950/zing/cql/CQLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,20 +134,27 @@ private CQLNode parseTopLevelPrefixes(String index, CQLRelation relation)
CQLNode node = parseQuery(index, relation);
if ((compat == V1POINT2 || compat == V1POINT1SORT) &&
lexer.what() == CQLTokenizer.TT_SORTBY) {
int start = lexer.pos() - lexer.value().length(), stop = -1;
match(lexer.what());
debug("sortspec");

CQLSortNode sortnode = new CQLSortNode(node);
while (lexer.what() != CQLTokenizer.TT_EOF) {
stop = lexer.pos();
String sortindex = matchSymbol("sort index");
ModifierSet ms = gatherModifiers(sortindex);
if (ms.getModifiers().size() > 0) {
stop = ms.getModifiers().get(ms.getModifiers().size() -1).getStop();
}
sortnode.addSortIndex(ms);
}

if (sortnode.keys.size() == 0) {
throw new CQLParseException("no sort keys", lexer.pos());
}

sortnode.setStartStop(start, stop);

node = sortnode;
}

Expand All @@ -171,10 +178,13 @@ private CQLNode parseQuery(String index, CQLRelation relation)
match(type);
ModifierSet ms = gatherModifiers(val);
CQLNode term2 = parseTerm(index, relation);
int start = term.getStart();
int stop = term2.getStop();
term = ((type == CQLTokenizer.TT_AND) ? new CQLAndNode(term, term2, ms) :
(type == CQLTokenizer.TT_OR) ? new CQLOrNode (term, term2, ms) :
(type == CQLTokenizer.TT_NOT) ? new CQLNotNode(term, term2, ms) :
new CQLProxNode(term, term2, ms));
term.setStartStop(start, stop);
} else {
throw new CQLParseException("expected boolean, got " +
lexer.render(), lexer.pos());
Expand All @@ -191,7 +201,9 @@ private ModifierSet gatherModifiers(String base)

ModifierSet ms = new ModifierSet(base);
while (lexer.what() == '/') {
int start = lexer.pos() - 1;
match('/');
int stop = lexer.pos();
if (lexer.what() != CQLTokenizer.TT_WORD)
throw new CQLParseException("expected modifier, "
+ "got " + lexer.render(),
Expand All @@ -200,13 +212,14 @@ private ModifierSet gatherModifiers(String base)
match(lexer.what());
if (!isSymbolicRelation()) {
// It's a simple modifier consisting of type only
ms.addModifier(type);
ms.addModifier(type).setStartStop(start, stop);
} else {
// It's a complex modifier of the form type=value
String comparision = lexer.render(lexer.what(), false);
match(lexer.what());
stop = lexer.pos();
String value = matchSymbol("modifier value");
ms.addModifier(type, comparision, value);
ms.addModifier(type, comparision, value).setStartStop(start, stop);
}
}

Expand All @@ -217,27 +230,34 @@ private CQLNode parseTerm(String index, CQLRelation relation)
throws CQLParseException, IOException {
debug("in parseTerm()");

int termStart = lexer.pos() - ((lexer.value() != null) ? lexer.value().length() : 0) - ((lexer.what() == CQLTokenizer.TT_STRING) ? 2 : 0);
int termStop = lexer.pos();
String first;
StringBuilder all;
while (true) {
if (lexer.what() == '(') {
debug("parenthesised term");
int wrapStart = lexer.pos() - 1;
match('(');
CQLNode expr = parseQuery(index, relation);
int wrapStop = lexer.pos();
match(')');
expr.setStartStop(wrapStart, wrapStop);
return expr;
} else if (lexer.what() == '>') {
return parsePrefix(index, relation, false);
}

debug("non-parenthesised term");
termStop = lexer.pos() - ((lexer.value() != null) ? lexer.value().length() : 0);
first = matchSymbol("index or term");
all = new StringBuilder(first);
//match relation only on second postion
while (isWordOrString() && (all.length() > first.length() || !isRelation())) {
all.append(" ").append(lexer.value());
match(lexer.what());
}
termStop += all.length();

if (!isRelation())
break; //we're done if no relation
Expand All @@ -252,13 +272,20 @@ private CQLNode parseTerm(String index, CQLRelation relation)
}
index = first;
relation = new CQLRelation(relstr);
int start = lexer.pos() - ((isSymbolicRelation()) ? ((lexer.what() == CQLTokenizer.TT_LE || lexer.what() == CQLTokenizer.TT_GE || lexer.what() == CQLTokenizer.TT_NE || lexer.what() == CQLTokenizer.TT_EQEQ) ? 2 : 1) : lexer.value().length());
int stop = lexer.pos();
match(lexer.what());
ModifierSet ms = gatherModifiers(relstr);
relation.ms = ms;
if (ms.getModifiers().size() > 0) {
stop = ms.getModifiers().get(ms.getModifiers().size() - 1).getStop();
}
relation.setStartStop(start, stop);
debug("index='" + index + ", " +
"relation='" + relation.toCQL() + "'");
}
CQLTermNode node = new CQLTermNode(index, relation, all.toString());
node.setStartStop(termStart, termStop);
debug("made term node " + node.toCQL());
return node;
}
Expand All @@ -268,19 +295,26 @@ private CQLNode parsePrefix(String index, CQLRelation relation,
throws CQLParseException, IOException {
debug("prefix mapping");

int start = lexer.pos() - 1;
int stop = -1;
match('>');

String name = null;
stop = lexer.pos();
String identifier = matchSymbol("prefix-name");
if (lexer.what() == '=') {
match('=');
name = identifier;
stop = lexer.pos();
identifier = matchSymbol("prefix-identifer");
}
CQLNode node = topLevel ?
parseTopLevelPrefixes(index, relation) :
parseQuery(index, relation);

return new CQLPrefixNode(name, identifier, node);
CQLPrefixNode prefixNode = new CQLPrefixNode(name, identifier, node);
prefixNode.setStartStop(start, stop);
return prefixNode;
}

private boolean isWordOrString() {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/z3950/zing/cql/Modifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class Modifier {
String comparison;
String value;

private int start, stop;

/**
* Creates a new Modifier with the specified type, comparison
* and value.
Expand Down Expand Up @@ -55,6 +57,19 @@ public String getValue() {
return value;
}

public int getStart() {
return start;
}

public int getStop() {
return stop;
}

protected void setStartStop(int start, int stop) {
this.start = start;
this.stop = stop;
}

void toXCQLInternal(XCQLBuilder b, int level, String relationElement) {
b.indent(level).append("<modifier>\n");
b.indent(level + 1).append("<type>");
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/z3950/zing/cql/ModifierSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,20 @@ public String getBase() {
* Adds a modifier of the specified <code>type</code>,
* <code>comparison</code> and <code>value</code> to a ModifierSet.
*/
public void addModifier(String type, String comparison, String value) {
public Modifier addModifier(String type, String comparison, String value) {
Modifier modifier = new Modifier(type, comparison, value);
modifiers.add(modifier);
return modifier;
}

/**
* Adds a modifier of the specified <code>type</code>, but with no
* <code>comparison</code> and <code>value</code>, to a ModifierSet.
*/
public void addModifier(String type) {
public Modifier addModifier(String type) {
Modifier modifier = new Modifier(type);
modifiers.add(modifier);
return modifier;
}

/**
Expand Down
Loading