- bugfix: only two operands for position groups
- correct handling of beg/end #BEG options (see javadoc of method CosmasTree.processPositionCondition())
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
index 920cf2c..7666dda 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
@@ -320,6 +320,15 @@
return group;
}
+ protected LinkedHashMap<String, Object> makeSpanReference(Integer[] spanRef, String operation) {
+ LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
+ group.put("@type", "korap:reference");
+ group.put("operation", "operation:"+operation);
+ group.put("spanRef", Arrays.asList(spanRef));
+ group.put("operands", new ArrayList<Object>());
+ return group;
+ }
+
protected void addOperandsToGroup(LinkedHashMap<String, Object> group) {
ArrayList<Object> operands = new ArrayList<Object>();
group.put("operands", operands);
@@ -356,71 +365,6 @@
return number;
}
- /**
- * Returns the category (or 'label') of the root of a (sub-) ParseTree (ANTLR 3).
- *
- * @param node
- * @return
- */
- public static String getNodeCat(Tree node) {
- String nodeCat = node.toStringTree();
- Pattern p = Pattern.compile("\\((.*?)\\s"); // from opening parenthesis to 1st whitespace
- Matcher m = p.matcher(node.toStringTree());
- if (m.find()) {
- nodeCat = m.group(1);
- }
- return nodeCat;
- }
-
-
- /**
- * Tests whether a certain node has a child by a certain name
- *
- * @param node The parent node.
- * @param childCat The category of the potential child.
- * @return true iff one or more children belong to the specified category
- */
- public static boolean hasChild(Tree node, String childCat) {
- for (int i = 0; i < node.getChildCount(); i++) {
- if (getNodeCat(node.getChild(i)).equals(childCat)) {
- return true;
- }
- }
- return false;
- }
-
-
-
- public static List<Tree> getChildrenWithCat(Tree node, String nodeCat) {
- ArrayList<Tree> children = new ArrayList<Tree>();
- for (int i = 0; i < node.getChildCount(); i++) {
- if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
- children.add(node.getChild(i));
- }
- }
- return children;
- }
-
-
- public static List<ParseTree> getChildren(ParseTree node) {
- ArrayList<ParseTree> children = new ArrayList<ParseTree>();
- for (int i = 0; i < node.getChildCount(); i++) {
- children.add(node.getChild(i));
- }
- return children;
- }
-
- public static Tree getFirstChildWithCat(Tree node, String nodeCat) {
- for (int i = 0; i < node.getChildCount(); i++) {
- if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
- return node.getChild(i);
- }
- }
- return null;
- }
-
-
-
public static void checkUnbalancedPars(String q) throws QueryException {
int openingPars = StringUtils.countMatches(q, "(");
int closingPars = StringUtils.countMatches(q, ")");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractSyntaxTree.java
index a9d1054..f07fd5c 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr3AbstractSyntaxTree.java
@@ -44,6 +44,14 @@
return false;
}
+ public static List<Tree> getChildren(Tree node) {
+ ArrayList<Tree> children = new ArrayList<Tree>();
+ for (int i = 0; i < node.getChildCount(); i++) {
+ children.add(node.getChild(i));
+ }
+ return children;
+ }
+
public static List<Tree> getChildrenWithCat(Tree node, String nodeCat) {
ArrayList<Tree> children = new ArrayList<Tree>();
for (int i = 0; i < node.getChildCount(); i++) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
index 670b50e..054d526 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
@@ -5,6 +5,7 @@
import de.ids_mannheim.korap.query.serialize.util.CosmasCondition;
import de.ids_mannheim.korap.query.serialize.util.ResourceMapper;
import de.ids_mannheim.korap.util.QueryException;
+
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.Tree;
@@ -75,7 +76,7 @@
/**
* A list of node categories that can be sequenced (i.e. which can be in a sequence with any number of other nodes in this list)
*/
- private final List<String> sequentiableCats = Arrays.asList(new String[]{"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED"});
+ private final List<String> sequentiableCats = Arrays.asList(new String[]{"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED", "OPELEM"});
/**
* Keeps track of sequenced nodes, i.e. nodes that implicitly govern a sequence, as in (C2PQ (OPWF der) (OPWF Mann)).
* This is necessary in order to know when to take the sequence off the object stack, as the sequence is introduced by the
@@ -160,17 +161,17 @@
if (nodeHasSequentiableSiblings) {
// Step I: create sequence
LinkedHashMap<String, Object> sequence = new LinkedHashMap<String, Object>();
- sequence.put("@type", "korap:group");
- sequence.put("operation", "operation:sequence");
- sequence.put("operands", new ArrayList<Object>());
- // push sequence on object stack but don't increment stackedObjects counter since
- // we've got to wait until the parent node is processed - therefore, add the parent
- // to the sequencedNodes list and remove the sequence from the stack when the parent
- // has been processed
- objectStack.push(sequence);
- sequencedNodes.push(parent);
- // Step II: decide where to put sequence
- putIntoSuperObject(sequence, 1);
+ sequence.put("@type", "korap:group");
+ sequence.put("operation", "operation:sequence");
+ sequence.put("operands", new ArrayList<Object>());
+ // push sequence on object stack but don't increment stackedObjects counter since
+ // we've got to wait until the parent node is processed - therefore, add the parent
+ // to the sequencedNodes list and remove the sequence from the stack when the parent
+ // has been processed
+ objectStack.push(sequence);
+ sequencedNodes.push(parent);
+ // Step II: decide where to put sequence
+ putIntoSuperObject(sequence, 1);
}
}
}
@@ -237,7 +238,7 @@
attrval[0] = attrval[0].replace("!", "");
}
String[] foundrylayer = attrval[0].split("/");
-
+
fieldMap.put("@type", "korap:term");
// fieldMap.put("key", "morph:"+node.getChild(0).toString().replace(" ", "_"));
fieldMap.put("key", attrval[1]);
@@ -248,8 +249,8 @@
fieldMap.put("layer", foundrylayer[1]);
}
}
-
-
+
+
// make category-specific fieldMap entry
// negate field (see above)
if (negate) {
@@ -600,85 +601,63 @@
putIntoSuperObject(beggroup, 1);
}
- if (nodeCat.equals("OPBED")) {
+ if (nodeCat.equals("OPBED")) {
+ // Node structure is (OPBED X+ (OPTS (TPBEG tpos*) (TPEND tpos*)))
+ // X is some segment, TPBEG or TPEND must be present (inclusive OR)
+ // tpos is a three-char string of the form "[+-]?[spt][ae]". s/p/t indicates span, a/e beginning/end, - means negation
+ // See C-II QL documentation for more detail:
+ // http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/textpositionen.html
+
// Step I: create group
int optsChild = node.getChildCount() - 1;
- Tree conditions = node.getChild(optsChild).getChild(0);
+ Tree begConditions = getFirstChildWithCat(node.getChild(optsChild), "TPBEG");
+ Tree endConditions = getFirstChildWithCat(node.getChild(optsChild), "TPEND");
- // create a containing group expressing the submatch constraint on the first argument
- ArrayList<Integer> spanRef = new ArrayList<Integer>();
- spanRef.add(1);
LinkedHashMap<String, Object> submatchgroup = makeReference(128+classCounter);
- ArrayList<Object> submatchoperands = new ArrayList<Object>();
- submatchgroup.put("operands", submatchoperands);
+ ArrayList<Object> submatchOperands = new ArrayList<Object>();
+ submatchgroup.put("operands", submatchOperands);
putIntoSuperObject(submatchgroup);
- // Distinguish two cases. Normal case: query has just one condition, like #BED(X, sa) ...
- if (conditions.getChildCount() == 1) {
- CosmasCondition c = new CosmasCondition(conditions.getChild(0));
-
- // create the group expressing the position constraint
- String[] frames = new String[]{c.position};
- String[] sharedClasses = new String[]{}; // OPBED only defines frame constraint, neglects intersection type
- LinkedHashMap<String,Object> posgroup = makePosition(frames, sharedClasses);
- // LinkedHashMap<String, Object> posgroup = makePosition(c.position);
- ArrayList<Object> operands = (ArrayList<Object>) posgroup.get("operands");
- if (c.negated) posgroup.put("exclude", true);
-
- // create span representing the element expressed in the condition
- LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
- bedElem.put("@type", "korap:span");
- bedElem.put("key", c.elem);
-
- // create a class group containing the argument, in order to submatch the arg.
- LinkedHashMap<String, Object> classGroup = makeSpanClass(classCounter++);
- objectStack.push(classGroup);
- stackedObjects++;
- operands.add(bedElem);
- operands.add(classGroup);
- // Step II: decide where to put
- submatchoperands.add(posgroup);
-
- // ... or the query has several conditions specified, like #BED(XY, sa,-pa). In that case,
- // use 'focus' operations to create nested conditions
- } else {
- // node has several conditions (like 'sa, -pa')
- // -> create identity position group and embed all position groups there
- LinkedHashMap<String, Object> conjunct = makePosition(new String[]{"frames:matches"}, new String[]{"classRefCheck:equals"});
- // ArrayList<Object> distances = new ArrayList<Object>();
- // distances.add(makeDistance("w", 0,0));
- // conjunct.put("distances", distances);
- ArrayList<Object> operands = new ArrayList<Object>();
- conjunct.put("operands", operands);
- ArrayList<Object> distributedOperands = new ArrayList<Object>();
-
- for (int i = 0; i < conditions.getChildCount(); i++) {
- // for each condition, create a position group containing a class group.
- // make position group
- CosmasCondition c = new CosmasCondition(conditions.getChild(i));
- String[] frames = new String[]{c.position};
- String[] sharedClasses = new String[]{}; // OPBED only defines frame constraint, neglects intersection type
- LinkedHashMap<String,Object> posGroup = makePosition(frames, sharedClasses);
- operands.add(posGroup);
- if (c.negated) posGroup.put("exclude", "true");
- ArrayList<Object> posOperands = new ArrayList<Object>();
-
- // make class group
- LinkedHashMap<String, Object> classGroup = makeSpanClass(classCounter++);
- classGroup.put("operands", distributedOperands);
-
- // put the span and the class group into the position group
- posGroup.put("operands", posOperands);
- LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
- posOperands.add(span);
- posOperands.add(classGroup);
- span.put("@type", "korap:span");
- span.put("key", c.elem);
- objectStack.push(classGroup);
+ // Step II: collect all conditions, create groups for them in processPositionCondition()
+ ArrayList<Object> distributedOperands = new ArrayList<Object>();
+ ArrayList<LinkedHashMap<String, Object>> conditionGroups = new ArrayList<LinkedHashMap<String, Object>>();
+ if (begConditions != null) {
+ for (Tree condition : getChildren(begConditions)) {
+ conditionGroups.add(processPositionCondition(condition, distributedOperands, "beg"));
}
- submatchoperands.add(conjunct);
}
-
+ if (endConditions != null) {
+ for (Tree condition : getChildren(endConditions)) {
+ conditionGroups.add(processPositionCondition(condition, distributedOperands, "end"));
+ }
+ }
+ // Step III: insert conditions. need to stack matches-groups because position groups may only have two operands
+ ArrayList<Object> currentLowestOperands = submatchOperands; // indicates where to insert next condition group
+ int conditionCount = 0;
+ for (LinkedHashMap<String,Object> conditionGroup : conditionGroups) {
+ conditionCount++;
+ if (conditionGroups.size()==1) {
+ submatchOperands.add(conditionGroup);
+ } else if (conditionCount < conditionGroups.size()) {
+ LinkedHashMap<String,Object> matchesGroup = makePosition(new String[]{"frames:matches"}, new String[0]);
+ ArrayList<Object> matchesOperands = (ArrayList<Object>) matchesGroup.get("operands");
+ matchesOperands.add(conditionGroup);
+ // matches groups that are embedded at the second or lower level receive an additional
+ // focus to grep out only the query term to which the constraint applies
+ if (conditionCount > 1) {
+ LinkedHashMap<String,Object> focus = makeReference(128+classCounter-2);
+ ArrayList<Object> focusOperands = new ArrayList<Object>();
+ focus.put("operands", focusOperands);
+ focusOperands.add(matchesGroup);
+ currentLowestOperands.add(focus);
+ } else {
+ currentLowestOperands.add(matchesGroup);
+ }
+ currentLowestOperands = matchesOperands;
+ } else {
+ currentLowestOperands.add(conditionGroup);
+ }
+ }
}
objectsToPop.push(stackedObjects);
toWrapsToPop.push(stackedToWrap);
@@ -733,7 +712,8 @@
}
private void processSpanDistance(String meas, int min, int max) {
- // TODO Do stuff here in case we'll decide one day to treat span distances in a special way.
+ // Do stuff here in case we'll decide one day to treat span distances in a special way.
+ // (see GDoc Special Distances Serialization)
}
/**
@@ -760,13 +740,7 @@
}
private Object translateMorph(String layer) {
- // todo: not very nicely solved! Does this require extension somehow? if not, why not use simple string comparison?!
- // LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
- // map.put("ANA", "pos");
- // if (map.containsKey(layer))
- // return map.get(layer);
- // else
- // return layer;
+ // might be extended...
if (layer.equals("ANA"))
return ResourceMapper.descriptor2policy("ANA");
else
@@ -775,6 +749,83 @@
}
@SuppressWarnings("unchecked")
+ /**
+ * Processes individual position conditions as provided in the OPTS node under the OPBEG node.
+ * #BEG allows to specify position constrains that apply to the beginning or the end of the subquery X.
+ * E.g., in #BEG(X, tpos/tpos), the 'tpos' constraints before the slash indicate conditions that apply
+ * to the beginning of X, those after the slash are conditions that apply to the end of X.
+ * See the official C-II documentation for more details. <br/><br/>
+ * What's important here is what follows: <br/>
+ * Assume the query #BED(der Mann, sa/pa). This means that <b>the beginning<b/> of "der Mann" stands at
+ * the beginning of a sentence and that <b>the end</b> (because this constraint comes after the slash) stands at the
+ * beginning of a paragraph. The "end" means the last item, here "Mann", so this token comes at the beginning
+ * of a paragraph. To capture this, we choose spanRefs: The last item of X matches the first item of the span (here: P).
+ * @param cond
+ * @param distributedOperands
+ * @param mode
+ * @return
+ */
+ private LinkedHashMap<String, Object> processPositionCondition(Tree cond, ArrayList<Object> distributedOperands, String mode) {
+ boolean negated = false;
+ String elem;
+ String position = "frames:matches";
+ Integer[] elemSpanRef = null;
+ Integer[] hitSpanRef = null;
+
+ String nodeString = cond.toStringTree();
+ if (nodeString.startsWith("-")) {
+ negated = true;
+ nodeString = nodeString.substring(1);
+ } else if (nodeString.startsWith("+")) {
+ nodeString = nodeString.substring(1);
+ }
+
+ elem = nodeString.substring(0, 1);
+ nodeString = nodeString.substring(1);
+
+ if (mode.equals("beg")) {
+ if (nodeString.equals("a")) {
+ position = "frames:startswith";
+ } else if (nodeString.equals("e")) {
+ hitSpanRef = new Integer[]{0,1};
+ elemSpanRef = new Integer[]{-1,1};
+ }
+ } else if (mode.equals("end")) {
+ if (nodeString.equals("e")) {
+ position = "frames:endswith";
+ } else if (nodeString.equals("a")) {
+ hitSpanRef = new Integer[]{0,1};
+ elemSpanRef = new Integer[]{-1,1};
+ }
+ }
+
+ LinkedHashMap<String, Object> positionGroup = makePosition(new String[]{position}, new String[0]);
+ if (negated) positionGroup.put("exclude", true);
+ ArrayList<Object> posOperands = new ArrayList<Object>();
+ LinkedHashMap<String, Object> classGroup = makeSpanClass(classCounter++);
+ classGroup.put("operands", distributedOperands);
+ positionGroup.put("operands", posOperands);
+ LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
+ span.put("@type", "korap:span");
+ span.put("key", elem);
+ objectStack.push(classGroup);
+ if (hitSpanRef != null) {
+ LinkedHashMap<String, Object> spanRefAroundHit = makeSpanReference(hitSpanRef, "focus");
+ ((ArrayList<Object>) spanRefAroundHit.get("operands")).add(classGroup);
+ classGroup = spanRefAroundHit; //re-assign after wrapping classGroup in spanRef
+ }
+ if (elemSpanRef != null) {
+ LinkedHashMap<String, Object> spanRefAroundSpan = makeSpanReference(elemSpanRef, "focus");
+ ((ArrayList<Object>) spanRefAroundSpan.get("operands")).add(span);
+ span = spanRefAroundSpan; //re-assign after wrapping span in spanRef
+ }
+ posOperands.add(span);
+ posOperands.add(classGroup);
+
+
+ return positionGroup;
+ }
+
private LinkedHashMap<String, Object> parseOPINOptions(Tree node) {
Tree posnode = getFirstChildWithCat(node, "POS");
Tree rangenode = getFirstChildWithCat(node, "RANGE");
@@ -955,78 +1006,6 @@
return wrapCascade[i];
}
- private LinkedHashMap<String,Object> processPositionOption(String posOption) {
- LinkedHashMap<String,Object> posgroup = null;
-
- if (posOption.equals("F") || posOption.equals("FI")) {
- posgroup = makePosition("startswith");
- LinkedHashMap<String, Object> endsWithPosition = makePosition("endswith");
- ((ArrayList<Object>) endsWithPosition.get("operands")).add(makeReference(classCounter+1));
- LinkedHashMap<String,Object> innerFocus = makeReference(classCounter);
- innerFocus.put("operands", new ArrayList<Object>());
- LinkedHashMap<String,Object> outerFocus = makeReference(classCounter);
- outerFocus.put("operands", new ArrayList<Object>());
- LinkedHashMap[] toWrap = new LinkedHashMap[]{posgroup, innerFocus, endsWithPosition, outerFocus};
- if (posOption.equals("FI")) {
- LinkedHashMap<String, Object> noMatchPosition = makePosition("matches");
- ((ArrayList<Object>) noMatchPosition.get("operands")).add(makeReference(classCounter+1));
- noMatchPosition.put("exclude", true);
- LinkedHashMap<String,Object> outermostFocus = makeReference(classCounter);
- outermostFocus.put("operands", new ArrayList<Object>());
- toWrap = new LinkedHashMap[]{posgroup, innerFocus, endsWithPosition, outerFocus, noMatchPosition, outermostFocus};
- }
-
- toWrapStack.push(toWrap);
- stackedToWrap++;
- // wrapOperandInClass(node,1,classCounter+1);
- // wrapOperandInClass(node,2,classCounter);
- // wrapFirstOpInClass = classCounter+1;
- // wrapSecondOpInClass = classCounter;
- }
-
- return posgroup;
- }
-
- // /**
- // * Translates the text area specifications (position option arguments) to terms used in serialisation.
- // * For the allowed argument types and their values for OPIN and OPOV, see
- // * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_I.html or
- // * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_O.html, respectively.
- // *
- // * @param argument
- // * @param mode
- // * @return
- // */
- // private ArrayList<String> translateTextAreaArgument(String argument, String mode) {
- // ArrayList<String> positions = new ArrayList<String>();
- // // POSTYP : 'L'|'l'|'R'|'r'|'F'|'f'|'FE'|'fe'|'FI'|'fi'|'N'|'n'|'X'|'x' ;
- // argument = argument.toUpperCase();
- // switch (argument) {
- // case "L":
- // if (mode.equals("in")) positions.add("startswith");
- // break;
- // case "R":
- // positions = mode.equals("in") ? "endswith" : "overlapsRight";
- // break;
- // case "F":
- // positions = "startswith";
- // break;
- // case "FE":
- // positions = "matches";
- // break;
- // case "FI":
- // positions = "startswith";
- // break;
- // case "N": // for OPIN only - exclusion constraint formulated in parseOPINOptions
- // positions = "leftrightmatch";
- // break;
- // case "X": // for OPOV only
- // positions = "residual";
- // break;
- // }
- // return positions;
- // }
-
LinkedList<ArrayList<Object>> nestedDistOperands = new LinkedList<ArrayList<Object>>();
@SuppressWarnings("unchecked")
@@ -1104,35 +1083,8 @@
*/
String[] queries = new String[]{
/* COSMAS 2 */
- // "wegen #OV(x) <s>",
- // "wegen #IN(L) <s>",
- // "#NHIT(gehen /w1:10 voran)",
- // "wegen #OV(FI) <s>",
- // "Sonne /+w4 Mond",
- // "#BEG(der /w3:5 Mann) /+w10 kommt",
- // "Sonne /s0 Mond"
- // "Sonne /+w4 Mond",
- // "#BED(der Mann , sa,-pa)",
- // "Sonne /+w1:4 Mond /-w1:7 Sterne",
- // "wegen #IN('FE,ALL,%,MIN') <s>",
- // "#NHIT(gehen /w1:10 voran)"
- // "MORPH(V PRES IND)",
- // "wegen #OV(F) <s>"
- // "Sonne /s0 Mond",
-// "Sonne /+w1:4 Mond /-w1:7 Sterne",
-// "Der:ta",
-// "&mond-",
-// "gehen /+w10 voran %w10 Beispiel",
-// "(gehen /+w10 voran) %w10 Beispiel",
-// "#BED(der Mann , sa,-pa)",
-// "MORPH(foundry/layer=key)",
-// "MORPH(f/l!=k &f/l!=k)",
-// "MORPH(p=aV)",
- "MORPH(APPR)",
-// "MORPH(APPR) ODER MORPH(APPRART)",
- "#ELEM(cnx/c=np)"
};
- CosmasTree.verbose=true;
+// CosmasTree.verbose=true;
for (String q : queries) {
try {
System.out.println(q);
@@ -1153,4 +1105,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/CosmasTreeTest.java b/src/test/java/CosmasTreeTest.java
index 9f3a958..1074086 100644
--- a/src/test/java/CosmasTreeTest.java
+++ b/src/test/java/CosmasTreeTest.java
@@ -118,6 +118,26 @@
ct = new CosmasTree(query);
map = ct.getRequestMap().get("query").toString();
assertEquals(seq3.replaceAll(" ", ""), map.replaceAll(" ", ""));
+
+ query="der #ELEM(S)";
+ expected =
+ "{@type=korap:group, operation=operation:sequence, operands=[" +
+ "{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+ "{@type=korap:span, key=s}" +
+ "]}";
+ ct = new CosmasTree(query);
+ map = ct.getRequestMap().get("query").toString();
+ assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+
+ query="der MORPH(mate/p=ADJA)";
+ expected =
+ "{@type=korap:group, operation=operation:sequence, operands=[" +
+ "{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+ "{@type=korap:token, wrap={@type=korap:term, key=ADJA, foundry=mate, layer=p, match=match:eq}}" +
+ "]}";
+ ct = new CosmasTree(query);
+ map = ct.getRequestMap().get("query").toString();
+ assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
}
@Test
@@ -1276,15 +1296,19 @@
query = "#BED(der Mann , +pe)";
String bed2 =
"{@type=korap:reference, operation=operation:focus, classRef=[129], operands= [" +
- "{@type=korap:group, operation=operation:position, frames=[frames:endswith], operands=[" +
- "{@type=korap:span, key=p}," +
- "{@type=korap:group, operation=operation:class, class=129, classOut=129, operands=[" +
- "{@type=korap:group, operation=operation:sequence, operands=[" +
- "{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
- "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+ "{@type=korap:group, operation=operation:position, frames=[frames:matches], operands=[" +
+ "{@type=korap:reference, operation=operation:focus, spanRef=[-1,1], operands=[" +
+ "{@type=korap:span, key=p}" +
+ "]}," +
+ "{@type=korap:reference, operation=operation:focus, spanRef=[0,1], operands=[" +
+ "{@type=korap:group, operation=operation:class, class=129, classOut=129, operands=[" +
+ "{@type=korap:group, operation=operation:sequence, operands=[" +
+ "{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+ "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+ "]}" +
"]}" +
"]}" +
- "], frame=frame:endswith}" +
+ "], frame=frame:matches}" +
"]}";
ct = new CosmasTree(query);
map = ct.getRequestMap().get("query").toString();
@@ -1346,18 +1370,26 @@
"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
"]}" +
"], frame=frame:startswith}," +
- "{@type=korap:group, operation=operation:position, frames=[frames:startswith], operands=[" +
- "{@type=korap:span, key=p}," +
- "{@type=korap:group, operation=operation:class, class=130, classOut=130, operands=[" +
- "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
- "]}" +
- "], frame=frame:startswith, exclude=true}," +
- "{@type=korap:group, operation=operation:position, frames=[frames:endswith], operands=[" +
- "{@type=korap:span, key=t}," +
- "{@type=korap:group, operation=operation:class, class=131, classOut=131, operands=[" +
- "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
- "]}" +
- "], frame=frame:endswith}" +
+ "{@type=korap:reference, operation=operation:focus, classRef=[130], operands=[" +
+ "{@type=korap:group, operation=operation:position, frames=[frames:matches], operands=[" +
+ "{@type=korap:group, operation=operation:position, frames=[frames:startswith], operands=[" +
+ "{@type=korap:span, key=p}," +
+ "{@type=korap:group, operation=operation:class, class=130, classOut=130, operands=[" +
+ "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+ "]}" +
+ "], frame=frame:startswith, exclude=true}," +
+ "{@type=korap:group, operation=operation:position, frames=[frames:matches], operands=[" +
+ "{@type=korap:reference, operation=operation:focus, spanRef=[-1,1], operands=[" +
+ "{@type=korap:span, key=t}" +
+ "]}," +
+ "{@type=korap:reference, operation=operation:focus, spanRef=[0,1], operands=[" +
+ "{@type=korap:group, operation=operation:class, class=131, classOut=131, operands=[" +
+ "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+ "]}" +
+ "]}" +
+ "], frame=frame:matches}" +
+ "], frame=frame:matches}" +
+ "]}" +
"], frame=frame:matches}" +
"]}";
ct = new CosmasTree(query);