You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

query_string.y 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. %{
  2. package query
  3. import (
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9. func logDebugGrammar(format string, v ...interface{}) {
  10. if debugParser {
  11. logger.Printf(format, v...)
  12. }
  13. }
  14. %}
  15. %union {
  16. s string
  17. n int
  18. f float64
  19. q Query
  20. pf *float64}
  21. %token tSTRING tPHRASE tPLUS tMINUS tCOLON tBOOST tNUMBER tSTRING tGREATER tLESS
  22. tEQUAL tTILDE
  23. %type <s> tSTRING
  24. %type <s> tPHRASE
  25. %type <s> tNUMBER
  26. %type <s> posOrNegNumber
  27. %type <s> tTILDE
  28. %type <s> tBOOST
  29. %type <q> searchBase
  30. %type <pf> searchSuffix
  31. %type <n> searchPrefix
  32. %%
  33. input:
  34. searchParts {
  35. logDebugGrammar("INPUT")
  36. };
  37. searchParts:
  38. searchPart searchParts {
  39. logDebugGrammar("SEARCH PARTS")
  40. }
  41. |
  42. searchPart {
  43. logDebugGrammar("SEARCH PART")
  44. };
  45. searchPart:
  46. searchPrefix searchBase searchSuffix {
  47. query := $2
  48. if $3 != nil {
  49. if query, ok := query.(BoostableQuery); ok {
  50. query.SetBoost(*$3)
  51. }
  52. }
  53. switch($1) {
  54. case queryShould:
  55. yylex.(*lexerWrapper).query.AddShould(query)
  56. case queryMust:
  57. yylex.(*lexerWrapper).query.AddMust(query)
  58. case queryMustNot:
  59. yylex.(*lexerWrapper).query.AddMustNot(query)
  60. }
  61. };
  62. searchPrefix:
  63. /* empty */ {
  64. $$ = queryShould
  65. }
  66. |
  67. tPLUS {
  68. logDebugGrammar("PLUS")
  69. $$ = queryMust
  70. }
  71. |
  72. tMINUS {
  73. logDebugGrammar("MINUS")
  74. $$ = queryMustNot
  75. };
  76. searchBase:
  77. tSTRING {
  78. str := $1
  79. logDebugGrammar("STRING - %s", str)
  80. var q FieldableQuery
  81. if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
  82. q = NewRegexpQuery(str[1:len(str)-1])
  83. } else if strings.ContainsAny(str, "*?"){
  84. q = NewWildcardQuery(str)
  85. } else {
  86. q = NewMatchQuery(str)
  87. }
  88. $$ = q
  89. }
  90. |
  91. tSTRING tTILDE {
  92. str := $1
  93. fuzziness, err := strconv.ParseFloat($2, 64)
  94. if err != nil {
  95. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid fuzziness value: %v", err))
  96. }
  97. logDebugGrammar("FUZZY STRING - %s %f", str, fuzziness)
  98. q := NewMatchQuery(str)
  99. q.SetFuzziness(int(fuzziness))
  100. $$ = q
  101. }
  102. |
  103. tSTRING tCOLON tSTRING tTILDE {
  104. field := $1
  105. str := $3
  106. fuzziness, err := strconv.ParseFloat($4, 64)
  107. if err != nil {
  108. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid fuzziness value: %v", err))
  109. }
  110. logDebugGrammar("FIELD - %s FUZZY STRING - %s %f", field, str, fuzziness)
  111. q := NewMatchQuery(str)
  112. q.SetFuzziness(int(fuzziness))
  113. q.SetField(field)
  114. $$ = q
  115. }
  116. |
  117. tNUMBER {
  118. str := $1
  119. logDebugGrammar("STRING - %s", str)
  120. q1 := NewMatchQuery(str)
  121. val, err := strconv.ParseFloat($1, 64)
  122. if err != nil {
  123. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  124. }
  125. inclusive := true
  126. q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
  127. q := NewDisjunctionQuery([]Query{q1,q2})
  128. q.queryStringMode = true
  129. $$ = q
  130. }
  131. |
  132. tPHRASE {
  133. phrase := $1
  134. logDebugGrammar("PHRASE - %s", phrase)
  135. q := NewMatchPhraseQuery(phrase)
  136. $$ = q
  137. }
  138. |
  139. tSTRING tCOLON tSTRING {
  140. field := $1
  141. str := $3
  142. logDebugGrammar("FIELD - %s STRING - %s", field, str)
  143. var q FieldableQuery
  144. if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
  145. q = NewRegexpQuery(str[1:len(str)-1])
  146. } else if strings.ContainsAny(str, "*?"){
  147. q = NewWildcardQuery(str)
  148. } else {
  149. q = NewMatchQuery(str)
  150. }
  151. q.SetField(field)
  152. $$ = q
  153. }
  154. |
  155. tSTRING tCOLON posOrNegNumber {
  156. field := $1
  157. str := $3
  158. logDebugGrammar("FIELD - %s STRING - %s", field, str)
  159. q1 := NewMatchQuery(str)
  160. q1.SetField(field)
  161. val, err := strconv.ParseFloat($3, 64)
  162. if err != nil {
  163. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  164. }
  165. inclusive := true
  166. q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
  167. q2.SetField(field)
  168. q := NewDisjunctionQuery([]Query{q1,q2})
  169. q.queryStringMode = true
  170. $$ = q
  171. }
  172. |
  173. tSTRING tCOLON tPHRASE {
  174. field := $1
  175. phrase := $3
  176. logDebugGrammar("FIELD - %s PHRASE - %s", field, phrase)
  177. q := NewMatchPhraseQuery(phrase)
  178. q.SetField(field)
  179. $$ = q
  180. }
  181. |
  182. tSTRING tCOLON tGREATER posOrNegNumber {
  183. field := $1
  184. min, err := strconv.ParseFloat($4, 64)
  185. if err != nil {
  186. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  187. }
  188. minInclusive := false
  189. logDebugGrammar("FIELD - GREATER THAN %f", min)
  190. q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
  191. q.SetField(field)
  192. $$ = q
  193. }
  194. |
  195. tSTRING tCOLON tGREATER tEQUAL posOrNegNumber {
  196. field := $1
  197. min, err := strconv.ParseFloat($5, 64)
  198. if err != nil {
  199. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  200. }
  201. minInclusive := true
  202. logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min)
  203. q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
  204. q.SetField(field)
  205. $$ = q
  206. }
  207. |
  208. tSTRING tCOLON tLESS posOrNegNumber {
  209. field := $1
  210. max, err := strconv.ParseFloat($4, 64)
  211. if err != nil {
  212. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  213. }
  214. maxInclusive := false
  215. logDebugGrammar("FIELD - LESS THAN %f", max)
  216. q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
  217. q.SetField(field)
  218. $$ = q
  219. }
  220. |
  221. tSTRING tCOLON tLESS tEQUAL posOrNegNumber {
  222. field := $1
  223. max, err := strconv.ParseFloat($5, 64)
  224. if err != nil {
  225. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
  226. }
  227. maxInclusive := true
  228. logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max)
  229. q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
  230. q.SetField(field)
  231. $$ = q
  232. }
  233. |
  234. tSTRING tCOLON tGREATER tPHRASE {
  235. field := $1
  236. minInclusive := false
  237. phrase := $4
  238. logDebugGrammar("FIELD - GREATER THAN DATE %s", phrase)
  239. minTime, err := queryTimeFromString(phrase)
  240. if err != nil {
  241. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err))
  242. }
  243. q := NewDateRangeInclusiveQuery(minTime, time.Time{}, &minInclusive, nil)
  244. q.SetField(field)
  245. $$ = q
  246. }
  247. |
  248. tSTRING tCOLON tGREATER tEQUAL tPHRASE {
  249. field := $1
  250. minInclusive := true
  251. phrase := $5
  252. logDebugGrammar("FIELD - GREATER THAN OR EQUAL DATE %s", phrase)
  253. minTime, err := queryTimeFromString(phrase)
  254. if err != nil {
  255. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err))
  256. }
  257. q := NewDateRangeInclusiveQuery(minTime, time.Time{}, &minInclusive, nil)
  258. q.SetField(field)
  259. $$ = q
  260. }
  261. |
  262. tSTRING tCOLON tLESS tPHRASE {
  263. field := $1
  264. maxInclusive := false
  265. phrase := $4
  266. logDebugGrammar("FIELD - LESS THAN DATE %s", phrase)
  267. maxTime, err := queryTimeFromString(phrase)
  268. if err != nil {
  269. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err))
  270. }
  271. q := NewDateRangeInclusiveQuery(time.Time{}, maxTime, nil, &maxInclusive)
  272. q.SetField(field)
  273. $$ = q
  274. }
  275. |
  276. tSTRING tCOLON tLESS tEQUAL tPHRASE {
  277. field := $1
  278. maxInclusive := true
  279. phrase := $5
  280. logDebugGrammar("FIELD - LESS THAN OR EQUAL DATE %s", phrase)
  281. maxTime, err := queryTimeFromString(phrase)
  282. if err != nil {
  283. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err))
  284. }
  285. q := NewDateRangeInclusiveQuery(time.Time{}, maxTime, nil, &maxInclusive)
  286. q.SetField(field)
  287. $$ = q
  288. };
  289. searchSuffix:
  290. /* empty */ {
  291. $$ = nil
  292. }
  293. |
  294. tBOOST {
  295. $$ = nil
  296. boost, err := strconv.ParseFloat($1, 64)
  297. if err != nil {
  298. yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid boost value: %v", err))
  299. } else {
  300. $$ = &boost
  301. }
  302. logDebugGrammar("BOOST %f", boost)
  303. };
  304. posOrNegNumber:
  305. tNUMBER {
  306. $$ = $1
  307. }
  308. |
  309. tMINUS tNUMBER {
  310. $$ = "-" + $2
  311. };