query_parser.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. lunr.QueryParser = function (str, query) {
  2. this.lexer = new lunr.QueryLexer (str)
  3. this.query = query
  4. this.currentClause = {}
  5. this.lexemeIdx = 0
  6. }
  7. lunr.QueryParser.prototype.parse = function () {
  8. this.lexer.run()
  9. this.lexemes = this.lexer.lexemes
  10. var state = lunr.QueryParser.parseClause
  11. while (state) {
  12. state = state(this)
  13. }
  14. return this.query
  15. }
  16. lunr.QueryParser.prototype.peekLexeme = function () {
  17. return this.lexemes[this.lexemeIdx]
  18. }
  19. lunr.QueryParser.prototype.consumeLexeme = function () {
  20. var lexeme = this.peekLexeme()
  21. this.lexemeIdx += 1
  22. return lexeme
  23. }
  24. lunr.QueryParser.prototype.nextClause = function () {
  25. var completedClause = this.currentClause
  26. this.query.clause(completedClause)
  27. this.currentClause = {}
  28. }
  29. lunr.QueryParser.parseClause = function (parser) {
  30. var lexeme = parser.peekLexeme()
  31. if (lexeme == undefined) {
  32. return
  33. }
  34. switch (lexeme.type) {
  35. case lunr.QueryLexer.PRESENCE:
  36. return lunr.QueryParser.parsePresence
  37. case lunr.QueryLexer.FIELD:
  38. return lunr.QueryParser.parseField
  39. case lunr.QueryLexer.TERM:
  40. return lunr.QueryParser.parseTerm
  41. default:
  42. var errorMessage = "expected either a field or a term, found " + lexeme.type
  43. if (lexeme.str.length >= 1) {
  44. errorMessage += " with value '" + lexeme.str + "'"
  45. }
  46. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  47. }
  48. }
  49. lunr.QueryParser.parsePresence = function (parser) {
  50. var lexeme = parser.consumeLexeme()
  51. if (lexeme == undefined) {
  52. return
  53. }
  54. switch (lexeme.str) {
  55. case "-":
  56. parser.currentClause.presence = lunr.Query.presence.PROHIBITED
  57. break
  58. case "+":
  59. parser.currentClause.presence = lunr.Query.presence.REQUIRED
  60. break
  61. default:
  62. var errorMessage = "unrecognised presence operator'" + lexeme.str + "'"
  63. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  64. }
  65. var nextLexeme = parser.peekLexeme()
  66. if (nextLexeme == undefined) {
  67. var errorMessage = "expecting term or field, found nothing"
  68. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  69. }
  70. switch (nextLexeme.type) {
  71. case lunr.QueryLexer.FIELD:
  72. return lunr.QueryParser.parseField
  73. case lunr.QueryLexer.TERM:
  74. return lunr.QueryParser.parseTerm
  75. default:
  76. var errorMessage = "expecting term or field, found '" + nextLexeme.type + "'"
  77. throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
  78. }
  79. }
  80. lunr.QueryParser.parseField = function (parser) {
  81. var lexeme = parser.consumeLexeme()
  82. if (lexeme == undefined) {
  83. return
  84. }
  85. if (parser.query.allFields.indexOf(lexeme.str) == -1) {
  86. var possibleFields = parser.query.allFields.map(function (f) { return "'" + f + "'" }).join(', '),
  87. errorMessage = "unrecognised field '" + lexeme.str + "', possible fields: " + possibleFields
  88. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  89. }
  90. parser.currentClause.fields = [lexeme.str]
  91. var nextLexeme = parser.peekLexeme()
  92. if (nextLexeme == undefined) {
  93. var errorMessage = "expecting term, found nothing"
  94. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  95. }
  96. switch (nextLexeme.type) {
  97. case lunr.QueryLexer.TERM:
  98. return lunr.QueryParser.parseTerm
  99. default:
  100. var errorMessage = "expecting term, found '" + nextLexeme.type + "'"
  101. throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
  102. }
  103. }
  104. lunr.QueryParser.parseTerm = function (parser) {
  105. var lexeme = parser.consumeLexeme()
  106. if (lexeme == undefined) {
  107. return
  108. }
  109. parser.currentClause.term = lexeme.str.toLowerCase()
  110. if (lexeme.str.indexOf("*") != -1) {
  111. parser.currentClause.usePipeline = false
  112. }
  113. var nextLexeme = parser.peekLexeme()
  114. if (nextLexeme == undefined) {
  115. parser.nextClause()
  116. return
  117. }
  118. switch (nextLexeme.type) {
  119. case lunr.QueryLexer.TERM:
  120. parser.nextClause()
  121. return lunr.QueryParser.parseTerm
  122. case lunr.QueryLexer.FIELD:
  123. parser.nextClause()
  124. return lunr.QueryParser.parseField
  125. case lunr.QueryLexer.EDIT_DISTANCE:
  126. return lunr.QueryParser.parseEditDistance
  127. case lunr.QueryLexer.BOOST:
  128. return lunr.QueryParser.parseBoost
  129. case lunr.QueryLexer.PRESENCE:
  130. parser.nextClause()
  131. return lunr.QueryParser.parsePresence
  132. default:
  133. var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
  134. throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
  135. }
  136. }
  137. lunr.QueryParser.parseEditDistance = function (parser) {
  138. var lexeme = parser.consumeLexeme()
  139. if (lexeme == undefined) {
  140. return
  141. }
  142. var editDistance = parseInt(lexeme.str, 10)
  143. if (isNaN(editDistance)) {
  144. var errorMessage = "edit distance must be numeric"
  145. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  146. }
  147. parser.currentClause.editDistance = editDistance
  148. var nextLexeme = parser.peekLexeme()
  149. if (nextLexeme == undefined) {
  150. parser.nextClause()
  151. return
  152. }
  153. switch (nextLexeme.type) {
  154. case lunr.QueryLexer.TERM:
  155. parser.nextClause()
  156. return lunr.QueryParser.parseTerm
  157. case lunr.QueryLexer.FIELD:
  158. parser.nextClause()
  159. return lunr.QueryParser.parseField
  160. case lunr.QueryLexer.EDIT_DISTANCE:
  161. return lunr.QueryParser.parseEditDistance
  162. case lunr.QueryLexer.BOOST:
  163. return lunr.QueryParser.parseBoost
  164. case lunr.QueryLexer.PRESENCE:
  165. parser.nextClause()
  166. return lunr.QueryParser.parsePresence
  167. default:
  168. var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
  169. throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
  170. }
  171. }
  172. lunr.QueryParser.parseBoost = function (parser) {
  173. var lexeme = parser.consumeLexeme()
  174. if (lexeme == undefined) {
  175. return
  176. }
  177. var boost = parseInt(lexeme.str, 10)
  178. if (isNaN(boost)) {
  179. var errorMessage = "boost must be numeric"
  180. throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
  181. }
  182. parser.currentClause.boost = boost
  183. var nextLexeme = parser.peekLexeme()
  184. if (nextLexeme == undefined) {
  185. parser.nextClause()
  186. return
  187. }
  188. switch (nextLexeme.type) {
  189. case lunr.QueryLexer.TERM:
  190. parser.nextClause()
  191. return lunr.QueryParser.parseTerm
  192. case lunr.QueryLexer.FIELD:
  193. parser.nextClause()
  194. return lunr.QueryParser.parseField
  195. case lunr.QueryLexer.EDIT_DISTANCE:
  196. return lunr.QueryParser.parseEditDistance
  197. case lunr.QueryLexer.BOOST:
  198. return lunr.QueryParser.parseBoost
  199. case lunr.QueryLexer.PRESENCE:
  200. parser.nextClause()
  201. return lunr.QueryParser.parsePresence
  202. default:
  203. var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
  204. throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
  205. }
  206. }