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  }