github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/queryparser/classic/queryParser.go (about) 1 package classic 2 3 import ( 4 "errors" 5 // "fmt" 6 "github.com/balzaczyy/golucene/core/analysis" 7 "github.com/balzaczyy/golucene/core/search" 8 "github.com/balzaczyy/golucene/core/util" 9 "strings" 10 ) 11 12 type Operator int 13 14 var ( 15 OP_OR = Operator(1) 16 OP_AND = Operator(2) 17 ) 18 19 type QueryParser struct { 20 *QueryParserBase 21 22 token_source *TokenManager 23 token *Token // current token 24 jj_nt *Token // next token 25 jj_ntk int 26 jj_scanpos, jj_lastpos *Token 27 jj_la int 28 jj_gen int 29 jj_la1 []int 30 31 jj_2_rtns []*JJCalls 32 jj_rescan bool 33 jj_gc int 34 } 35 36 func NewQueryParser(matchVersion util.Version, f string, a analysis.Analyzer) *QueryParser { 37 qp := &QueryParser{ 38 token_source: newTokenManager(newFastCharStream(strings.NewReader(""))), 39 jj_la1: make([]int, 21), 40 jj_2_rtns: make([]*JJCalls, 1), 41 } 42 qp.QueryParserBase = newQueryParserBase(qp) 43 qp.ReInit(newFastCharStream(strings.NewReader(""))) 44 // base 45 qp.analyzer = a 46 qp.field = f 47 qp.autoGeneratePhraseQueries = !matchVersion.OnOrAfter(util.VERSION_31) 48 return qp 49 } 50 51 func (qp *QueryParser) conjunction() (int, error) { 52 ret := CONJ_NONE 53 if qp.jj_ntk == -1 { 54 qp.get_jj_ntk() 55 } 56 switch qp.jj_ntk { 57 case AND, OR: 58 panic("niy") 59 default: 60 qp.jj_la1[1] = qp.jj_gen 61 } 62 return ret, nil 63 } 64 65 func (qp *QueryParser) modifiers() (ret int, err error) { 66 ret = MOD_NONE 67 if qp.jj_ntk == -1 { 68 qp.get_jj_ntk() 69 } 70 switch qp.jj_ntk { 71 case NOT, PLUS, MINUS: 72 panic("not implemented yet") 73 default: 74 qp.jj_la1[3] = qp.jj_gen 75 } 76 return 77 } 78 79 func (qp *QueryParser) TopLevelQuery(field string) (q search.Query, err error) { 80 if q, err = qp.Query(field); err != nil { 81 return nil, err 82 } 83 _, err = qp.jj_consume_token(0) 84 return q, err 85 } 86 87 func (qp *QueryParser) Query(field string) (q search.Query, err error) { 88 var clauses []*search.BooleanClause 89 var conj, mods int 90 if mods, err = qp.modifiers(); err != nil { 91 return nil, err 92 } 93 if q, err = qp.clause(field); err != nil { 94 return nil, err 95 } 96 clauses = qp.addClause(clauses, CONJ_NONE, mods, q) 97 var firstQuery search.Query 98 if mods == MOD_NONE { 99 firstQuery = q 100 } 101 for { 102 if qp.jj_ntk == -1 { 103 qp.get_jj_ntk() 104 } 105 var found = false 106 switch qp.jj_ntk { 107 case AND, OR, NOT, PLUS, MINUS, BAREOPER, LPAREN, STAR, QUOTED, 108 TERM, PREFIXTERM, WILDTERM, REGEXPTERM, RANGEIN_START, 109 RANGEEX_START, NUMBER: 110 default: 111 qp.jj_la1[4] = qp.jj_gen 112 found = true 113 } 114 if found { 115 break 116 } 117 if conj, err = qp.conjunction(); err != nil { 118 return nil, err 119 } 120 if mods, err = qp.modifiers(); err != nil { 121 return nil, err 122 } 123 if q, err = qp.clause(field); err != nil { 124 return nil, err 125 } 126 clauses = qp.addClause(clauses, conj, mods, q) 127 } 128 if len(clauses) == 1 && firstQuery != nil { 129 return firstQuery, nil 130 } else { 131 return qp.booleanQuery(clauses) 132 } 133 } 134 135 func (qp *QueryParser) clause(field string) (q search.Query, err error) { 136 if qp.jj_2_1(2) { 137 panic("not implemented yet") 138 } 139 if qp.jj_ntk == -1 { 140 qp.get_jj_ntk() 141 } 142 var boost *Token 143 switch qp.jj_ntk { 144 case BAREOPER, STAR, QUOTED, TERM, PREFIXTERM, WILDTERM, 145 REGEXPTERM, RANGEIN_START, RANGEEX_START, NUMBER: 146 if q, err = qp.term(field); err != nil { 147 return nil, err 148 } 149 case LPAREN: 150 panic("not implemented yet") 151 default: 152 qp.jj_la1[7] = qp.jj_gen 153 if _, err = qp.jj_consume_token(-1); err != nil { 154 return nil, err 155 } 156 return nil, errors.New("parse error") 157 } 158 return qp.handleBoost(q, boost), nil 159 } 160 161 func (qp *QueryParser) term(field string) (q search.Query, err error) { 162 var term, boost, fuzzySlop /*, goop1, goop2*/ *Token 163 var prefix, wildcard, fuzzy, regexp /*, startInc, endInc*/ bool 164 if qp.jj_ntk == -1 { 165 qp.get_jj_ntk() 166 } 167 switch qp.jj_ntk { 168 case BAREOPER, STAR, TERM, PREFIXTERM, WILDTERM, REGEXPTERM, NUMBER: 169 if qp.jj_ntk == -1 { 170 qp.get_jj_ntk() 171 } 172 switch qp.jj_ntk { 173 case TERM: 174 if term, err = qp.jj_consume_token(TERM); err != nil { 175 return nil, err 176 } 177 case STAR: 178 panic("not implemented yet") 179 case PREFIXTERM: 180 panic("not implemented yet") 181 case WILDTERM: 182 panic("not implemented yet") 183 case REGEXPTERM: 184 panic("not implemented yet") 185 case NUMBER: 186 panic("not implemented yet") 187 case BAREOPER: 188 panic("not implemented yet") 189 default: 190 panic("not implemented yet") 191 } 192 if qp.jj_ntk == -1 { 193 qp.get_jj_ntk() 194 } 195 switch qp.jj_ntk { 196 case FUZZY_SLOP: 197 panic("not implemented yet") 198 default: 199 qp.jj_la1[9] = qp.jj_gen 200 } 201 if qp.jj_ntk == -1 { 202 qp.get_jj_ntk() 203 } 204 switch qp.jj_ntk { 205 case CARAT: 206 panic("not implemented yet") 207 default: 208 qp.jj_la1[11] = qp.jj_gen 209 } 210 if q, err = qp.handleBareTokenQuery(field, term, fuzzySlop, prefix, wildcard, fuzzy, regexp); err != nil { 211 return nil, err 212 } 213 214 case RANGEIN_START, RANGEEX_START: 215 panic("not implemented yet") 216 case QUOTED: 217 panic("not implemented yet") 218 default: 219 panic("not implemented yet") 220 } 221 return qp.handleBoost(q, boost), nil 222 } 223 224 // L473 225 func (qp *QueryParser) jj_2_1(xla int) (ok bool) { 226 qp.jj_la = xla 227 qp.jj_lastpos = qp.token 228 qp.jj_scanpos = qp.token 229 defer func() { 230 // Disable following recover() to deal with dev panic 231 if err := recover(); err == lookAheadSuccess { 232 ok = true 233 } 234 qp.jj_save(0, xla) 235 }() 236 return !qp.jj_3_1() 237 } 238 239 func (qp *QueryParser) jj_3R_2() bool { 240 return qp.jj_scan_token(TERM) || 241 qp.jj_scan_token(COLON) 242 } 243 244 func (qp *QueryParser) jj_3_1() bool { 245 xsp := qp.jj_scanpos 246 if qp.jj_3R_2() { 247 qp.jj_scanpos = xsp 248 if qp.jj_3R_3() { 249 return true 250 } 251 } 252 return false 253 } 254 255 func (qp *QueryParser) jj_3R_3() bool { 256 return qp.jj_scan_token(STAR) || 257 qp.jj_scan_token(COLON) 258 } 259 260 // L540 261 func (qp *QueryParser) ReInit(stream CharStream) { 262 qp.token_source.ReInit(stream) 263 qp.token = new(Token) 264 qp.jj_ntk = -1 265 qp.jj_gen = 0 266 for i, _ := range qp.jj_la1 { 267 qp.jj_la1[i] = -1 268 } 269 for i, _ := range qp.jj_2_rtns { 270 qp.jj_2_rtns[i] = new(JJCalls) 271 } 272 } 273 274 // L569 275 func (qp *QueryParser) jj_consume_token(kind int) (*Token, error) { 276 oldToken := qp.token 277 if qp.token.next != nil { 278 qp.token = qp.token.next 279 } else { 280 qp.token.next = qp.token_source.nextToken() 281 qp.token = qp.token.next 282 } 283 qp.jj_ntk = -1 284 if qp.token.kind == kind { 285 qp.jj_gen++ 286 if qp.jj_gc++; qp.jj_gc > 100 { 287 qp.jj_gc = 0 288 panic("not implemented yet") 289 } 290 return qp.token, nil 291 } 292 qp.token = oldToken 293 panic("not implemented yet") 294 } 295 296 type LookAheadSuccess bool 297 298 var lookAheadSuccess = LookAheadSuccess(true) 299 300 func (qp *QueryParser) jj_scan_token(kind int) bool { 301 if qp.jj_scanpos == qp.jj_lastpos { 302 qp.jj_la-- 303 if qp.jj_scanpos.next == nil { 304 nextToken := qp.token_source.nextToken() 305 qp.jj_scanpos.next = nextToken 306 qp.jj_scanpos = nextToken 307 qp.jj_lastpos = nextToken 308 } else { 309 qp.jj_scanpos = qp.jj_scanpos.next 310 qp.jj_lastpos = qp.jj_scanpos.next 311 } 312 } else { 313 qp.jj_scanpos = qp.jj_scanpos.next 314 } 315 if qp.jj_rescan { 316 panic("niy") 317 } 318 if qp.jj_scanpos.kind != kind { 319 return true 320 } 321 if qp.jj_la == 0 && qp.jj_scanpos == qp.jj_lastpos { 322 panic(lookAheadSuccess) 323 } 324 return false 325 } 326 327 // L636 328 func (qp *QueryParser) get_jj_ntk() int { 329 if qp.jj_nt = qp.token.next; qp.jj_nt == nil { 330 qp.token.next = qp.token_source.nextToken() 331 qp.jj_ntk = qp.token.next.kind 332 } else { 333 qp.jj_ntk = qp.jj_nt.kind 334 } 335 return qp.jj_ntk 336 } 337 338 // L738 339 340 func (qp *QueryParser) jj_save(index, xla int) { 341 p := qp.jj_2_rtns[index] 342 for p.gen > qp.jj_gen { 343 if p.next == nil { 344 p = new(JJCalls) 345 p.next = p 346 break 347 } 348 p = p.next 349 } 350 p.gen = qp.jj_gen + xla - qp.jj_la 351 p.first = qp.token 352 p.arg = xla 353 } 354 355 type JJCalls struct { 356 gen int 357 first *Token 358 arg int 359 next *JJCalls 360 }