blob: f23fa2989fa7412e13ac12ef248545adc8b88986 [file] [log] [blame]
Nils Diewalda31a5152015-04-17 21:05:23 +00001% layout 'main', title => 'KorAP: Poliqarp+';
2
Akron9490e3b2019-10-17 12:26:29 +02003%= page_title
Nils Diewalda31a5152015-04-17 21:05:23 +00004
Marc Kupietz06243732026-09-11 15:41:19 +02005<p>The following documentation introduces all features provided by our version of the Poliqarp Query Language and some KorAP specific extensions.
6 For a more comprehensive description of Poliqarp+, please refer to the <%= ext_link_to 'detailed Poliqarp+ documentation (PDF, in German)', "https://corpora.ids-mannheim.de/doc/Poliqarp_Plus-Dokumentation.pdf" %>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +00007
Nils Diewaldfccfbcb2015-04-29 20:48:19 +00008<section id="segments">
Nils Diewalda31a5152015-04-17 21:05:23 +00009 <h3>Simple Segments</h3>
10
Akronae24e162018-02-13 18:48:44 +010011 <p>The atomic elements of Poliqarp queries are segments. Most of the time segments represent words and can be simple queried:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000012 %# footnote: In the polish national corpus, Poliqarp can join multiple segments when identifying a single word.
13
Akronbee660d2018-02-14 15:57:02 +010014 %= doc_query poliqarp => loc('Q_poliqarp_simple', '** Tree')
Nils Diewalda31a5152015-04-17 21:05:23 +000015
16 <p>Sequences of simple segments are expressed using a space delimiter:</p>
17
Akronbee660d2018-02-14 15:57:02 +010018 %= doc_query poliqarp => loc('Q_poliqarp_simpleseq', '** the Tree')
Nils Diewalda31a5152015-04-17 21:05:23 +000019
20 <p>Simple segments always refer to the surface form of a word. To search for surface forms without case sensitivity, you can use the <code>/i</code> flag.</p>
21
Akronbee660d2018-02-14 15:57:02 +010022 %= doc_query poliqarp => loc('Q_poliqarp_simpleci', '** run/i')
Nils Diewalda31a5152015-04-17 21:05:23 +000023
Akrona7cfd902017-12-21 19:28:36 +010024 <p>The query above will find all occurrences of the term irrespective of the capitalization of letters.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000025
Nils Diewaldfccfbcb2015-04-29 20:48:19 +000026 <h4 id="regexp">Regular Expressions</h4>
Nils Diewalda31a5152015-04-17 21:05:23 +000027
Akron3cfa26d2019-10-24 15:17:34 +020028 <p>Segments can also be queried using <%= embedded_link_to 'doc', 'regular expressions', 'ql', 'regexp' %> - by surrounding the segment with double quotes.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000029
Akronbee660d2018-02-14 15:57:02 +010030 %= doc_query poliqarp => loc('Q_poliqarp_re', '** "r(u|a)n"'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +000031
Akronae24e162018-02-13 18:48:44 +010032 <p>Regular expression segments will always match the whole segment, meaning the above query will find words starting with the first letter of the regular expression and ending with the last letter. To support subqueries, you can use the <code>/x</code> flag.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000033
Akronbee660d2018-02-14 15:57:02 +010034 %= doc_query poliqarp => loc('Q_poliqarp_rex', '** "r(u|a)n"/x'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +000035
36 <p>The <code>/x</code> will search for all segments that contain a sequence of characters the regular expression matches. That means the above query is equivalent to:</p>
37
Akronbee660d2018-02-14 15:57:02 +010038 %= doc_query poliqarp => loc('Q_poliqarp_recontext', '** ".*?r(u|a)n.*?"'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +000039
Akronae24e162018-02-13 18:48:44 +010040 <p>The <code>/x</code> flag can also be used in conjunction with strict expressions to search for substrings:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000041
Akronbee660d2018-02-14 15:57:02 +010042 %= doc_query poliqarp => loc('Q_poliqarp_simplex', '** part/xi'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +000043
Akronae24e162018-02-13 18:48:44 +010044 <p>The above query will find all occurrences of segments including the defined substring regardless of upper and lower case.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000045
46 <blockquote class="warning">
Akronae24e162018-02-13 18:48:44 +010047 <p>Beware: Queries with prepended <code>.*</code> expressions can become extremely slow!</p>
Akron148cbfd2025-04-30 11:18:54 +020048 <p>In the original Poliqarp specification, regular expressions can be marked both by double quotes and single quotes. In Poliqarp+ only double quotes are used for regular expressions.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000049 </blockquote>
50
Akronae24e162018-02-13 18:48:44 +010051 <p>You can again apply the <code>/i</code> flag to regular expressions to search case insensitive.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000052
Akronbee660d2018-02-14 15:57:02 +010053 %= doc_query poliqarp => loc('Q_poliqarp_rexi', '** "r(u|a)n"/xi'), cutoff => 1
Akron852fb8a2023-07-21 07:48:13 +020054
55 <h4 id="reserved">Reserved terms</h4>
56
57 <p>The following terms are <em>reserved words</em> in Poliqarp+ and can therefore not be used in short notation of simple segments.
58 Use the notation for <%= embedded_link_to 'doc', 'complex segments', 'ql', 'poliqarp-plus#complex'%> to query them (e.g. <code>[orth='contains']</code>):</p>
59
60 <ul>
61 <li><code>contains</code></li>
62 <li><code>dependency</code></li>
63 <li><code>dominates</code></li>
64 <li><code>endswith</code></li>
65 <li><code>endsWith</code></li>
66 <li><code>focus</code></li>
67 <li><code>i</code> and <code>I</code></li>
68 <li><code>meta</code></li>
69 <li><code>matches</code></li>
70 <li><code>overlaps</code></li>
71 <li><code>relatesTo</code></li>
72 <li><code>split</code></li>
73 <li><code>startswith</code> and <code>startsWith</code></li>
74 <li><code>submatch</code></li>
75 <li><code>within</code></li>
76 <li><code>x</code> and <code>X</code></li>
77 </ul>
78
Nils Diewalda31a5152015-04-17 21:05:23 +000079</section>
80
Nils Diewaldfccfbcb2015-04-29 20:48:19 +000081<section id="complex">
Nils Diewalda31a5152015-04-17 21:05:23 +000082 <h3>Complex Segments</h3>
83
84 <p>Complex segments are expressed in square brackets and contain additional information on the resource of the term under scrutiny by providing key/value pairs, separated by an equal-sign.</p>
85
Akronae24e162018-02-13 18:48:44 +010086 <p>The KorAP implementation of Poliqarp provides three special segment keys: <code>orth</code> for surface forms, <code>base</code> for lemmata, and <code>pos</code> for Part-of-Speech. The following complex query finds all surface forms of the defined word.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +000087 %# There are more special keys in Poliqarp, but KorAP doesn't provide them.
88
Akronbee660d2018-02-14 15:57:02 +010089 %= doc_query poliqarp => loc('Q_poliqarp_complexorth', '** [orth=Tree]')
Nils Diewalda31a5152015-04-17 21:05:23 +000090
91 <p>The query is thus equivalent to:</p>
92
Akronbee660d2018-02-14 15:57:02 +010093 %= doc_query poliqarp => loc('Q_poliqarp_simple', '** Tree')
Nils Diewalda31a5152015-04-17 21:05:23 +000094
95 <p>Complex segments expect simple expressions as values, meaning that the following expression is valid as well:</p>
96
Akronbee660d2018-02-14 15:57:02 +010097 %= doc_query poliqarp => loc('Q_poliqarp_complexre', '** [orth="r(u|a)n"/xi]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +000098
Akron3cfa26d2019-10-24 15:17:34 +020099 <p>Another special key is <code>base</code>, refering to the lemma annotation of the <%= embedded_link_to 'doc', 'default foundry', 'data', 'annotation' %>.
Akronae24e162018-02-13 18:48:44 +0100100 The following query finds all occurrences of segments annotated as a specified lemma by the default foundry.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000101
Akronbee660d2018-02-14 15:57:02 +0100102 %= doc_query poliqarp => loc('Q_poliqarp_complexlemma', '** [base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000103
Akron3cfa26d2019-10-24 15:17:34 +0200104 <p>The third special key is <code>pos</code>, refering to the part-of-speech annotation of the <%= embedded_link_to 'doc', 'default foundry', 'data', 'annotation' %>.
Nils Diewalda31a5152015-04-17 21:05:23 +0000105 The following query finds all attributive adjectives:</p>
106
Akronbee660d2018-02-14 15:57:02 +0100107 %= doc_query poliqarp => loc('Q_poliqarp_complexpos', '** [pos=ADJA]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000108
109 <p>Complex segments requesting further token annotations can have keys following the <code>foundry/layer</code> notation.
Akronae24e162018-02-13 18:48:44 +0100110 For example to find all occurrences of plural words in a supporting foundry, you can search using the following query:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000111
Akronbee660d2018-02-14 15:57:02 +0100112 %= doc_query poliqarp => loc('Q_poliqarp_complexplural', '** [mate/m=number:pl]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000113
Akron81afd282018-07-24 11:39:55 +0200114 <p>In case an annotation contains special non-alphabetic and non-numeric characters, the annotation part can be surrounded by single quotes to ensure a verbatim interpretation:</p>
115
116 %= doc_query poliqarp => loc('Q_poliqarp_complexverbatim', '** [mate/o=\'This is an annotation with space characters\']'), cutoff => 1
117
Nils Diewalda31a5152015-04-17 21:05:23 +0000118 <h4>Negation</h4>
Akron54740182017-06-17 14:17:23 +0200119 <p>Negation of terms in complex expressions can be expressed by prepending the equal sign or the whole expression with an exclamation mark.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000120
Akronbee660d2018-02-14 15:57:02 +0100121 %= doc_query poliqarp => loc('Q_poliqarp_neg1', '** [pos!=ADJA]'), cutoff => 1
122 %= doc_query poliqarp => loc('Q_poliqarp_neg2', '** [!pos=ADJA]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000123
124 <blockquote class="warning">
Akronae24e162018-02-13 18:48:44 +0100125 <p>Beware: Negated complex segments can't be searched as a single statement.
Akron3cfa26d2019-10-24 15:17:34 +0200126 However, they work in case they are part of a <%= embedded_link_to 'doc', 'sequence', 'ql', 'poliqarp-plus#syntagmatic-operators-sequence' %>.</p>
Akron742f1792026-07-31 17:15:13 +0200127
128 <p>If the negation refers to an annotation rather than to the surface form of a term, it may be advantageous to specify the annotation layer in the virtual corpus as a constraint (meta data field <tt>foundries</tt>) so that not all occurrences that do not have this annotation layer are found.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000129 </blockquote>
130
131 <h4 id="empty-segments">Empty Segments</h4>
132
133 <p>A special segment is the empty segment, that matches every word in the index.</p>
134
Akronbee660d2018-02-14 15:57:02 +0100135 %= doc_query poliqarp => '[]', cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000136
Akron3cfa26d2019-10-24 15:17:34 +0200137 <p>Empty segments are useful to express distances of words by using <%= embedded_link_to 'doc', 'repetitions', 'ql', 'poliqarp-plus#syntagmatic-operators-repetitions' %>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000138
139 <blockquote class="warning">
Akronae24e162018-02-13 18:48:44 +0100140 <p>Beware: Empty segments can't be searched as a single statement.
Akron3cfa26d2019-10-24 15:17:34 +0200141 However, they work in case they are part of a <%= embedded_link_to 'doc', 'sequence', 'ql', 'poliqarp-plus#syntagmatic-operators-sequence' %>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000142 </blockquote>
143</section>
144
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000145<section id="spans">
Nils Diewalda31a5152015-04-17 21:05:23 +0000146 <h3>Span Segments</h3>
147
148 <p>Not all segments are bound to words - some are bound to concepts spanning multiple words, for example noun phrases, sentences, or paragraphs.
149Span segments can be searched for using angular brackets instead of square brackets.</p>
150
Akronbee660d2018-02-14 15:57:02 +0100151 %= doc_query poliqarp => loc('Q_poliqarp_span', '** <corenlp/c=NP>'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000152
153 <p>Otherwise they can be treated in exactly the same way as simple or complex segments.</p>
154</section>
155
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000156<section id="paradigmatic-operators">
Nils Diewalda31a5152015-04-17 21:05:23 +0000157 <h3>Paradigmatic Operators</h3>
158
Akronae24e162018-02-13 18:48:44 +0100159 <p>A complex segment can have multiple properties a token requires. For example to search for all words with a certain surface form of a particular lemma (no matter if capitalized or not), you can search for:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000160
Akronbee660d2018-02-14 15:57:02 +0100161 %= doc_query poliqarp => loc('Q_poliqarp_and', '** [orth=run/i & base=Run]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000162
163 <p>The ampersand combines multiple properties with a logical AND.
164Terms of the complex segment can be negated as introduced before.</p>
165
Akronbee660d2018-02-14 15:57:02 +0100166 %= doc_query poliqarp => loc('Q_poliqarp_andneg1', '** [orth=run/i & base!=Run]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000167
168 <p>The following query is therefore equivalent:</p>
169
Akronbee660d2018-02-14 15:57:02 +0100170 %= doc_query poliqarp => loc('Q_poliqarp_andneg2', '** [orth=run/i & !base=Run]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000171
172 <p>Alternatives can be expressed by using the pipe symbol:</p>
173
Akronbee660d2018-02-14 15:57:02 +0100174 %= doc_query poliqarp => loc('Q_poliqarp_or', '** [base=run | base=go]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000175
176 <p>All these sub expressions can be grouped using round brackets to form complex boolean expressions:</p>
177
Akronbee660d2018-02-14 15:57:02 +0100178 %= doc_query poliqarp => loc('Q_poliqarp_group', '** [(base=run | base=go) & tt/pos=VVFIN]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000179</section>
180
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000181<section id="syntagmatic-operators">
Nils Diewalda31a5152015-04-17 21:05:23 +0000182 <h3>Syntagmatic Operators</h3>
183
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000184 <h4 id="syntagmatic-operators-sequence">Sequences</h4>
Nils Diewalda31a5152015-04-17 21:05:23 +0000185
Akronae24e162018-02-13 18:48:44 +0100186 <p>Sequences can be used to search for segments in order. For this, simple expressions are separated by whitespaces.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000187
Akronbee660d2018-02-14 15:57:02 +0100188 %= doc_query poliqarp => loc('Q_poliqarp_seq', '** the old man'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000189
190 <p>However, you can obviously search using complex segments as well:</p>
191
Akronbee660d2018-02-14 15:57:02 +0100192 %= doc_query poliqarp => loc('Q_poliqarp_seqcomplex', '** [orth=the][orth=old][orth=man]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000193
194 <p>Now you may see the benefit of the empty segment to search for words you don't know:</p>
195
Akronbee660d2018-02-14 15:57:02 +0100196 %= doc_query poliqarp => loc('Q_poliqarp_seqcomplexempty', '** [orth=the][][orth=man]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000197
Akronae24e162018-02-13 18:48:44 +0100198 <p>You are also able to mix segments and spans in sequences, for example to search for a word at the beginning of a sentence (which can be interpreted as the first word after the end of a sentence).</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000199
Akronbee660d2018-02-14 15:57:02 +0100200 %= doc_query poliqarp => loc('Q_poliqarp_seqspan', '** <base/s=s>[orth=The]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000201
202 <h4>Groups</h4>
203
204 ...
205
206 <h4>Alternation</h4>
207
Akronae24e162018-02-13 18:48:44 +0100208 <p>Alternations allow for searching alternative segments or sequences of segments, similar to the paradigmatic operator. You already have seen that you can search for a sequence with an alternative adjective in between by typing in:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000209
Akronbee660d2018-02-14 15:57:02 +0100210 %= doc_query poliqarp => loc('Q_poliqarp_seqor', '** the [orth=old | orth=young] man'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000211
Akronae24e162018-02-13 18:48:44 +0100212 <p>However, this formulation has problems in case you want to search for alternations of sequences rather than terms. In this case you can use syntagmatic alternations and groups:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000213
Akronbee660d2018-02-14 15:57:02 +0100214 %= doc_query poliqarp => loc('Q_poliqarp_seqorgroup1', '** the (young man | old woman)'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000215
Akronae24e162018-02-13 18:48:44 +0100216 <p>The pipe symbol works the same way as with the paradigmatic alternation, but supports sequences of different length as operands. The above query with an alternative adjective in a sequence can therefore be reformulated as:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000217
Akronbee660d2018-02-14 15:57:02 +0100218 %= doc_query poliqarp => loc('Q_poliqarp_seqorgroup2', '** the (old | young) man'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000219
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000220 <h4 id="syntagmatic-operators-repetitions">Repetition</h4>
Nils Diewalda31a5152015-04-17 21:05:23 +0000221
Akron3cfa26d2019-10-24 15:17:34 +0200222 <p>Repetitions in Poliqarp are realized as in <%= embedded_link_to 'doc', 'regular expressions', 'ql', 'regexp' %>, by giving quantifieres in curly brackets.</p>
Akronae24e162018-02-13 18:48:44 +0100223 <p>To search for a sequence of three occurrences of a defined string, you can formulate your query in any of the following ways - they will have the same results:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000224
Akronbee660d2018-02-14 15:57:02 +0100225 %= doc_query poliqarp => loc('Q_poliqarp_repmanual', '** the the the'), cutoff => 1
226 %= doc_query poliqarp => loc('Q_poliqarp_repsimple', '** the{3}'), cutoff => 1
227 %= doc_query poliqarp => loc('Q_poliqarp_repcomplex', '** [orth=the]{3}'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000228
Akronae24e162018-02-13 18:48:44 +0100229 <p>In difference to regular expressions, the repetition operation won't refer to the match but to the pattern given. So the following query will give you a sequence of three words with a defined substring - but the words don't have to be identical.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000230
Akronbee660d2018-02-14 15:57:02 +0100231 %= doc_query poliqarp => loc('Q_poliqarp_repre', '** "ru.*?"/i{3}'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000232
Akronae24e162018-02-13 18:48:44 +0100233 <p>The same is true for annotations. The following query will find a sequence of 3 to 4 adjectives in a defined context. The adjectives do not have to be identical though.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000234
Akronbee660d2018-02-14 15:57:02 +0100235 %= doc_query poliqarp => loc('Q_poliqarp_repanno', '** [base=the][tt/p=ADJA]{3,4}[tt/p=NOUN]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000236
Akronae24e162018-02-13 18:48:44 +0100237 <p>In addition to numbered quantities, it is also possible to pass repetition information as Kleene operators <code>?</code>, <code>*</code>, and <code>+</code>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000238
Akronae24e162018-02-13 18:48:44 +0100239 <p>To search for a sequence with an optional segment, you can search for:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000240
Akronbee660d2018-02-14 15:57:02 +0100241 %= doc_query poliqarp => loc('Q_poliqarp_seqopt1', '** [base=the][tt/pos=ADJA]?[base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000242
243 <p>This query is identical to the numbered quantification of:</p>
244
Akronbee660d2018-02-14 15:57:02 +0100245 %= doc_query poliqarp => loc('Q_poliqarp_seqopt2', '** [base=the][tt/pos=ADJA]{,1}[base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000246
Akronae24e162018-02-13 18:48:44 +0100247 <p>To search for the same sequences but with unlimited adjectives in between, you can use the Kleene Star:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000248
Akronbee660d2018-02-14 15:57:02 +0100249 %= doc_query poliqarp => loc('Q_poliqarp_seqstar', '** [base=the][tt/pos=ADJA]*[base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000250
251 <p>And to search for this sequence but with at least one adjective in between, you can use the Kleene Plus (all queries are identical):</p>
252
Akronbee660d2018-02-14 15:57:02 +0100253 %= doc_query poliqarp => loc('Q_poliqarp_seqplus1', '** [base=the][tt/pos=ADJA]+[base=Tree]'), cutoff => 1
254 %= doc_query poliqarp => loc('Q_poliqarp_seqplus2', '** [base=the][tt/pos=ADJA]{1,}[base=Tree]'), cutoff => 1
255 %= doc_query poliqarp => loc('Q_poliqarp_seqplus3', '** [base=the][tt/pos=ADJA][tt/pos=ADJA]*[base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000256
257 <blockquote class="warning">
Akronae24e162018-02-13 18:48:44 +0100258 <p>Repetition operators like <code>{,n}</code>, <code>?</code>, and <code>*</code> make segments or groups of segments optional. In case these queries are used separated and not as part of a sequence (and there are no mandatory segments in the query), you will be warned by the system that your query won't be treated as optional.</p>
259 <p>Keep in mind that optionality may be somehow <i>inherited</i>, for example an entire query becomes optional as soon as one segment of an alternation is optional.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000260 </blockquote>
261
Akron3cfa26d2019-10-24 15:17:34 +0200262 <p>Repetition can also be used to express distances between segments by using <%= embedded_link_to 'doc', 'empty segments', 'ql', 'poliqarp-plus#empty-segments' %>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000263
Akronbee660d2018-02-14 15:57:02 +0100264 %= doc_query poliqarp => loc('Q_poliqarp_seqdistance1', '** [base=the][][base=Tree]'), cutoff => 1
265 %= doc_query poliqarp => loc('Q_poliqarp_seqdistance2', '** [base=the][]{2}[base=Tree]'), cutoff => 1
266 %= doc_query poliqarp => loc('Q_poliqarp_seqdistance3', '** [base=the][]{2,}[base=Tree]'), cutoff => 1
267 %= doc_query poliqarp => loc('Q_poliqarp_seqdistance4', '** [base=the][]{,3}[base=Tree]'), cutoff => 1
268
Nils Diewalda31a5152015-04-17 21:05:23 +0000269 <p>Of course, Kleene operators can be used with empty segments as well.</p>
270
Akronbee660d2018-02-14 15:57:02 +0100271 %= doc_query poliqarp => loc('Q_poliqarp_seqdistanceopt', '** [base=the][]?[base=Tree]'), cutoff => 1
272 %= doc_query poliqarp => loc('Q_poliqarp_seqdistancestar', '** [base=the][]*[base=Tree]'), cutoff => 1
273 %= doc_query poliqarp => loc('Q_poliqarp_seqdistanceplus', '** [base=the][]+[base=Tree]'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000274
275 <h4>Position</h4>
276
Akron3cfa26d2019-10-24 15:17:34 +0200277 <p>Sequences as shown above can all be nested in further complex queries and treated as subqueries (see <%= embedded_link_to 'doc', 'class operators', 'ql', 'poliqarp-plus#class-operators' %> on how to later access these subqueries directly).</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000278 <p>Positional operators compare two matches of subqueries and will match, in case a certain condition regarding the position of both is true.</p>
279 <p>The <code>contains()</code> operation will match, when a second subquery matches inside the span of a first subquery.</p>
280
Akronbee660d2018-02-14 15:57:02 +0100281 %= doc_query poliqarp => loc('Q_poliqarp_poscontains', '** contains(<base/s=s>, [tt/p=KOUS])'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000282
283 <p>The <code>startsWith()</code> operation will match, when a second subquery matches at the beginning of the span of a first subquery.</p>
284
Akronbee660d2018-02-14 15:57:02 +0100285 %= doc_query poliqarp => loc('Q_poliqarp_posstartswith', '** startsWith(<base/s=s>, [tt/p=KOUS])'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000286
287 <p>The <code>endsWith()</code> operation will match, when a second subquery matches at the end of the span of a first subquery.</p>
288
Akronbee660d2018-02-14 15:57:02 +0100289 %= doc_query poliqarp => loc('Q_poliqarp_posendswith', '** endsWith(<base/s=s>, [opennlp/p=NN])'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000290
Akronae24e162018-02-13 18:48:44 +0100291 <p>The <code>matches()</code> operation will match, when a second subquery has the exact same span as a first subquery.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000292
Akronbee660d2018-02-14 15:57:02 +0100293 %= doc_query poliqarp => loc('Q_poliqarp_posmatches', '** matches(<base/s=s>,[tt/p=CARD][tt/p="N.*"])'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000294
295 <p>The <code>overlaps()</code> operation will match, when a second subquery has an overlapping span with the first subquery.</p>
296
Akronbee660d2018-02-14 15:57:02 +0100297 %= doc_query poliqarp => loc('Q_poliqarp_posoverlaps', '** overlaps([][tt/p=ADJA],{1:[tt/p=ADJA]}[])'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000298
299 <blockquote class="warning">
300 <p>Positional operators are still experimental and may change in certain aspects in the future (although the behaviour defined is intended to be stable). There is also known incorrect behaviour which will be corrected in future versions.</p>
Akronae24e162018-02-13 18:48:44 +0100301 <p>Optional operands in position operators have to be mandatory at the moment and will be reformulated to occur at least once.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000302 <p>This behaviour may change in the future.</p>
303 </blockquote>
304
305 <!--
306 <blockquote>
307 <p>The KorAP implementation of Poliqarp also supports the postfix <code>within</code> operator, that works similar to the <code>contains()</code> operator, but is not nestable.</p>
308 </blockquote>
309 -->
310
311</section>
312
Nils Diewaldfccfbcb2015-04-29 20:48:19 +0000313<section id="class-operators">
Nils Diewalda31a5152015-04-17 21:05:23 +0000314 <h3>Class Operators</h3>
315
Akronae24e162018-02-13 18:48:44 +0100316 <p>Classes are used to group submatches by surrounding curly brackets and a class number <code>{1:...}</code>. Classes can be used to refer to submatches in a query, similar to captures in regular expressions. In Poliqarp+ classes have multiple purposes, with highlighting being the most intuitive one:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000317
Akronbee660d2018-02-14 15:57:02 +0100318 %= doc_query poliqarp => loc('Q_poliqarp_classes', '** the {1:{2:[]} man}'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000319
Akronae24e162018-02-13 18:48:44 +0100320 <p>In KorAP classes can be defined from 1 to 128. In case a class number is missing, the class defaults to the class number 1: <code>{...}</code> is equal to <code>{1:...}</code>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000321
322 <h4>Match Modification</h4>
323
324 <p>Based on classes, matches may be modified. The <code>focus()</code> operator restricts the span of a match to the boundary of a certain class.</p>
325
Akronbee660d2018-02-14 15:57:02 +0100326 %= doc_query poliqarp => loc('Q_poliqarp_focus', '** focus(the {Tree})'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000327
Akronae24e162018-02-13 18:48:44 +0100328 <p>The query above will search for a sequence but the match will be limited to the second segment. You can think of the first segment in this query as a <i>positive look-behind zero-length assertion</i> in regular expressions.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000329
Akronae24e162018-02-13 18:48:44 +0100330 <p>But focus is way more useful if you are searching for matches without knowing the surface form. For example, to find all terms between defined words you can search:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000331
Akronbee660d2018-02-14 15:57:02 +0100332 %= doc_query poliqarp => loc('Q_poliqarp_focusempty', '** focus(the {[]} Tree)'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000333
Akronae24e162018-02-13 18:48:44 +0100334 <p>Or you may want to search for all words following a known sequence immediately:</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000335
Akronbee660d2018-02-14 15:57:02 +0100336 %= doc_query poliqarp => loc('Q_poliqarp_focusextension', '** focus(the old and {[]})'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000337
Akronbee660d2018-02-14 15:57:02 +0100338 <p><code>focus()</code> is especially useful if you are searching for matches in certain areas,
339 for example in quotes using positional operators.
340 While not being interested in the whole quote as a match, you can focus on what's really relevant to you.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000341
Akronbee660d2018-02-14 15:57:02 +0100342 %= doc_query poliqarp => loc('Q_poliqarp_focusrelevance', '** focus(contains(she []{,10} said, {Tree}))'), cutoff => 1
Nils Diewalda31a5152015-04-17 21:05:23 +0000343
Akronae24e162018-02-13 18:48:44 +0100344 <p>In case a class number is missing, the focus operator defaults to the class number 1: <code>focus(...)</code> is equal to <code>focus(1: ...)</code>.</p>
Nils Diewalda31a5152015-04-17 21:05:23 +0000345
346 <blockquote class="warning">
347 <p>As numbers in curly brackets can be ambiguous in certain circumstances, for example <code>[]{3}</code> can be read as either &quot;any word repeated three times&quot; or &quot;any word followed by the number 3 highlighted as class number 1&quot;, numbers should always be expressed as <code>[orth=3]</code> for the latter case.</p>
348 </blockquote>
349</section>