@witchcraft/expressit 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +9 -5
  2. package/dist/Lexer.js +2 -2
  3. package/dist/Parser.d.ts +14 -29
  4. package/dist/Parser.d.ts.map +1 -1
  5. package/dist/Parser.js +120 -135
  6. package/dist/ast/builders/array.d.ts +1 -3
  7. package/dist/ast/builders/array.d.ts.map +1 -1
  8. package/dist/ast/builders/array.js +3 -5
  9. package/dist/ast/builders/condition.d.ts +5 -11
  10. package/dist/ast/builders/condition.d.ts.map +1 -1
  11. package/dist/ast/builders/condition.js +2 -3
  12. package/dist/ast/builders/delim.d.ts +1 -1
  13. package/dist/ast/builders/error.d.ts +3 -4
  14. package/dist/ast/builders/error.d.ts.map +1 -1
  15. package/dist/ast/builders/error.js +6 -2
  16. package/dist/ast/builders/expression.d.ts +3 -7
  17. package/dist/ast/builders/expression.d.ts.map +1 -1
  18. package/dist/ast/builders/expression.js +3 -5
  19. package/dist/ast/builders/group.d.ts +3 -8
  20. package/dist/ast/builders/group.d.ts.map +1 -1
  21. package/dist/ast/builders/group.js +3 -3
  22. package/dist/ast/builders/pos.d.ts +1 -2
  23. package/dist/ast/builders/pos.d.ts.map +1 -1
  24. package/dist/ast/builders/token.d.ts +3 -5
  25. package/dist/ast/builders/token.d.ts.map +1 -1
  26. package/dist/ast/builders/token.js +3 -4
  27. package/dist/ast/builders/type.d.ts +1 -1
  28. package/dist/ast/builders/variable.d.ts +3 -5
  29. package/dist/ast/builders/variable.d.ts.map +1 -1
  30. package/dist/ast/builders/variable.js +2 -3
  31. package/dist/ast/createArrayNode.d.ts +3 -0
  32. package/dist/ast/createArrayNode.d.ts.map +1 -0
  33. package/dist/ast/createArrayNode.js +12 -0
  34. package/dist/ast/createConditionNode.d.ts +11 -0
  35. package/dist/ast/createConditionNode.d.ts.map +1 -0
  36. package/dist/ast/createConditionNode.js +18 -0
  37. package/dist/ast/createExpressionNode.d.ts +3 -0
  38. package/dist/ast/createExpressionNode.d.ts.map +1 -0
  39. package/dist/ast/createExpressionNode.js +14 -0
  40. package/dist/ast/createGroupNode.d.ts +5 -0
  41. package/dist/ast/createGroupNode.d.ts.map +1 -0
  42. package/dist/ast/createGroupNode.js +14 -0
  43. package/dist/ast/createNormalizedCondition.d.ts +3 -0
  44. package/dist/ast/createNormalizedCondition.d.ts.map +1 -0
  45. package/dist/ast/createNormalizedCondition.js +10 -0
  46. package/dist/ast/createNormalizedExpression.d.ts +3 -0
  47. package/dist/ast/createNormalizedExpression.d.ts.map +1 -0
  48. package/dist/ast/createNormalizedExpression.js +10 -0
  49. package/dist/ast/createToken.d.ts +6 -0
  50. package/dist/ast/createToken.d.ts.map +1 -0
  51. package/dist/ast/createToken.js +15 -0
  52. package/dist/ast/createVariableNode.d.ts +3 -0
  53. package/dist/ast/createVariableNode.d.ts.map +1 -0
  54. package/dist/ast/createVariableNode.js +12 -0
  55. package/dist/ast/error.d.ts +3 -0
  56. package/dist/ast/error.d.ts.map +1 -0
  57. package/dist/ast/error.js +9 -0
  58. package/dist/ast/handlers.d.ts +5 -12
  59. package/dist/ast/handlers.d.ts.map +1 -1
  60. package/dist/ast/handlers.js +21 -29
  61. package/dist/ast/index.d.ts +9 -1
  62. package/dist/ast/index.d.ts.map +1 -1
  63. package/dist/ast/index.js +18 -2
  64. package/dist/defaults/defaultConditionNormalizer.d.ts +3 -0
  65. package/dist/defaults/defaultConditionNormalizer.d.ts.map +1 -0
  66. package/dist/defaults/defaultKeyParser.d.ts +3 -0
  67. package/dist/defaults/defaultKeyParser.d.ts.map +1 -0
  68. package/dist/defaults/defaultPrefixApplier.d.ts +3 -0
  69. package/dist/defaults/defaultPrefixApplier.d.ts.map +1 -0
  70. package/dist/defaults/defaultValueComparer.d.ts +3 -0
  71. package/dist/defaults/defaultValueComparer.d.ts.map +1 -0
  72. package/dist/{helpers/general → defaults}/index.d.ts +0 -2
  73. package/dist/defaults/index.d.ts.map +1 -0
  74. package/dist/{helpers/general → defaults}/index.js +0 -4
  75. package/dist/index.d.ts +2 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +3 -1
  78. package/dist/{helpers/errors.d.ts → internal/ExpressitError.d.ts} +3 -2
  79. package/dist/internal/ExpressitError.d.ts.map +1 -0
  80. package/dist/{helpers/errors.js → internal/ExpressitError.js} +2 -2
  81. package/dist/internal/applyBoolean.d.ts.map +1 -0
  82. package/dist/{helpers/general → internal}/applyPrefix.d.ts +1 -1
  83. package/dist/internal/applyPrefix.d.ts.map +1 -0
  84. package/dist/{helpers/parser → internal}/checkParserOpts.d.ts +2 -1
  85. package/dist/internal/checkParserOpts.d.ts.map +1 -0
  86. package/dist/{helpers/parser → internal}/checkParserOpts.js +14 -14
  87. package/dist/internal/escapeVariableOrPrefix.d.ts +2 -0
  88. package/dist/internal/escapeVariableOrPrefix.d.ts.map +1 -0
  89. package/dist/internal/escapeVariableOrPrefix.js +38 -0
  90. package/dist/internal/extractPosition.d.ts +5 -0
  91. package/dist/internal/extractPosition.d.ts.map +1 -0
  92. package/dist/internal/getUnclosedRightParenCount.d.ts +4 -0
  93. package/dist/internal/getUnclosedRightParenCount.d.ts.map +1 -0
  94. package/dist/{helpers/parser → internal}/getUnclosedRightParenCount.js +1 -1
  95. package/dist/{helpers/parser → internal}/parseParserOptions.d.ts +1 -1
  96. package/dist/internal/parseParserOptions.d.ts.map +1 -0
  97. package/dist/{helpers/parser → internal}/parseParserOptions.js +4 -4
  98. package/dist/internal/unescape.d.ts.map +1 -0
  99. package/dist/package.json.js +7 -7
  100. package/dist/types/ast.d.ts +195 -6
  101. package/dist/types/ast.d.ts.map +1 -1
  102. package/dist/types/ast.js +2 -0
  103. package/dist/types/autocomplete.d.ts +5 -6
  104. package/dist/types/autocomplete.d.ts.map +1 -1
  105. package/dist/types/parser.d.ts +17 -22
  106. package/dist/types/parser.d.ts.map +1 -1
  107. package/dist/utils/extractTokens.d.ts +2 -4
  108. package/dist/utils/extractTokens.d.ts.map +1 -1
  109. package/dist/utils/extractTokens.js +14 -18
  110. package/dist/utils/generateParentsMap.d.ts +10 -0
  111. package/dist/utils/generateParentsMap.d.ts.map +1 -0
  112. package/dist/utils/generateParentsMap.js +73 -0
  113. package/dist/utils/getCursorInfo.d.ts +1 -1
  114. package/dist/utils/getCursorInfo.d.ts.map +1 -1
  115. package/dist/utils/getCursorInfo.js +3 -5
  116. package/dist/utils/getOppositeDelimiter.d.ts +2 -1
  117. package/dist/utils/getOppositeDelimiter.d.ts.map +1 -1
  118. package/dist/utils/getOppositeDelimiter.js +6 -5
  119. package/dist/utils/getParent.d.ts +5 -0
  120. package/dist/utils/getParent.d.ts.map +1 -0
  121. package/dist/utils/getParent.js +6 -0
  122. package/dist/utils/getSurroundingErrors.d.ts +3 -4
  123. package/dist/utils/getSurroundingErrors.d.ts.map +1 -1
  124. package/dist/utils/getSurroundingErrors.js +3 -3
  125. package/dist/utils/index.d.ts +4 -0
  126. package/dist/utils/index.d.ts.map +1 -1
  127. package/dist/utils/index.js +8 -0
  128. package/dist/utils/isNode.d.ts +10 -0
  129. package/dist/utils/isNode.d.ts.map +1 -0
  130. package/dist/utils/isNode.js +6 -0
  131. package/dist/utils/isToken.d.ts +8 -0
  132. package/dist/utils/isToken.d.ts.map +1 -0
  133. package/dist/utils/isToken.js +6 -0
  134. package/dist/utils/prettyAst.d.ts +1 -2
  135. package/dist/utils/prettyAst.d.ts.map +1 -1
  136. package/dist/utils/prettyAst.js +19 -26
  137. package/package.json +7 -7
  138. package/src/Lexer.ts +2 -2
  139. package/src/Parser.ts +158 -165
  140. package/src/ast/builders/array.ts +4 -9
  141. package/src/ast/builders/condition.ts +10 -15
  142. package/src/ast/builders/delim.ts +1 -1
  143. package/src/ast/builders/error.ts +10 -6
  144. package/src/ast/builders/expression.ts +17 -23
  145. package/src/ast/builders/group.ts +7 -11
  146. package/src/ast/builders/pos.ts +2 -3
  147. package/src/ast/builders/token.ts +6 -7
  148. package/src/ast/builders/type.ts +1 -1
  149. package/src/ast/builders/variable.ts +6 -8
  150. package/src/ast/createArrayNode.ts +17 -0
  151. package/src/ast/createConditionNode.ts +58 -0
  152. package/src/ast/createExpressionNode.ts +21 -0
  153. package/src/ast/createGroupNode.ts +46 -0
  154. package/src/ast/createNormalizedCondition.ts +12 -0
  155. package/src/ast/createNormalizedExpression.ts +9 -0
  156. package/src/ast/createToken.ts +26 -0
  157. package/src/ast/createVariableNode.ts +18 -0
  158. package/src/ast/error.ts +9 -0
  159. package/src/ast/handlers.ts +26 -37
  160. package/src/ast/index.ts +9 -1
  161. package/src/{helpers/general → defaults}/defaultConditionNormalizer.ts +1 -1
  162. package/src/{helpers/general → defaults}/defaultKeyParser.ts +1 -1
  163. package/src/{helpers/general → defaults}/defaultPrefixApplier.ts +1 -1
  164. package/src/{helpers/general → defaults}/defaultValueComparer.ts +1 -1
  165. package/src/{helpers/general → defaults}/index.ts +0 -2
  166. package/src/index.ts +2 -1
  167. package/src/{helpers/errors.ts → internal/ExpressitError.ts} +2 -2
  168. package/src/{helpers/general → internal}/applyPrefix.ts +1 -1
  169. package/src/{helpers/parser → internal}/checkParserOpts.ts +16 -15
  170. package/src/internal/escapeVariableOrPrefix.ts +36 -0
  171. package/src/{helpers/parser → internal}/extractPosition.ts +2 -2
  172. package/src/{helpers/parser → internal}/getUnclosedRightParenCount.ts +1 -2
  173. package/src/{helpers/parser → internal}/parseParserOptions.ts +5 -5
  174. package/src/types/ast.ts +292 -7
  175. package/src/types/autocomplete.ts +5 -7
  176. package/src/types/parser.ts +17 -22
  177. package/src/utils/extractTokens.ts +16 -20
  178. package/src/utils/generateParentsMap.ts +60 -0
  179. package/src/utils/getCursorInfo.ts +4 -6
  180. package/src/utils/getOppositeDelimiter.ts +11 -10
  181. package/src/utils/getParent.ts +16 -0
  182. package/src/utils/getSurroundingErrors.ts +10 -9
  183. package/src/utils/index.ts +4 -0
  184. package/src/utils/isNode.ts +12 -0
  185. package/src/utils/isToken.ts +10 -0
  186. package/src/utils/prettyAst.ts +20 -17
  187. package/dist/ast/classes/ArrayNode.d.ts +0 -18
  188. package/dist/ast/classes/ArrayNode.d.ts.map +0 -1
  189. package/dist/ast/classes/ArrayNode.js +0 -55
  190. package/dist/ast/classes/Condition.d.ts +0 -13
  191. package/dist/ast/classes/Condition.d.ts.map +0 -1
  192. package/dist/ast/classes/Condition.js +0 -21
  193. package/dist/ast/classes/ConditionNode.d.ts +0 -73
  194. package/dist/ast/classes/ConditionNode.d.ts.map +0 -1
  195. package/dist/ast/classes/ConditionNode.js +0 -101
  196. package/dist/ast/classes/ErrorToken.d.ts +0 -27
  197. package/dist/ast/classes/ErrorToken.d.ts.map +0 -1
  198. package/dist/ast/classes/ErrorToken.js +0 -47
  199. package/dist/ast/classes/Expression.d.ts +0 -13
  200. package/dist/ast/classes/Expression.d.ts.map +0 -1
  201. package/dist/ast/classes/Expression.js +0 -19
  202. package/dist/ast/classes/ExpressionNode.d.ts +0 -21
  203. package/dist/ast/classes/ExpressionNode.d.ts.map +0 -1
  204. package/dist/ast/classes/ExpressionNode.js +0 -57
  205. package/dist/ast/classes/GroupNode.d.ts +0 -64
  206. package/dist/ast/classes/GroupNode.d.ts.map +0 -1
  207. package/dist/ast/classes/GroupNode.js +0 -69
  208. package/dist/ast/classes/Node.d.ts +0 -22
  209. package/dist/ast/classes/Node.d.ts.map +0 -1
  210. package/dist/ast/classes/Node.js +0 -28
  211. package/dist/ast/classes/Token.d.ts +0 -27
  212. package/dist/ast/classes/Token.d.ts.map +0 -1
  213. package/dist/ast/classes/Token.js +0 -28
  214. package/dist/ast/classes/ValidToken.d.ts +0 -26
  215. package/dist/ast/classes/ValidToken.d.ts.map +0 -1
  216. package/dist/ast/classes/ValidToken.js +0 -49
  217. package/dist/ast/classes/VariableNode.d.ts +0 -33
  218. package/dist/ast/classes/VariableNode.d.ts.map +0 -1
  219. package/dist/ast/classes/VariableNode.js +0 -58
  220. package/dist/ast/classes/index.d.ts +0 -12
  221. package/dist/ast/classes/index.d.ts.map +0 -1
  222. package/dist/ast/classes/index.js +0 -24
  223. package/dist/helpers/errors.d.ts.map +0 -1
  224. package/dist/helpers/general/applyBoolean.d.ts.map +0 -1
  225. package/dist/helpers/general/applyPrefix.d.ts.map +0 -1
  226. package/dist/helpers/general/defaultConditionNormalizer.d.ts +0 -3
  227. package/dist/helpers/general/defaultConditionNormalizer.d.ts.map +0 -1
  228. package/dist/helpers/general/defaultKeyParser.d.ts +0 -3
  229. package/dist/helpers/general/defaultKeyParser.d.ts.map +0 -1
  230. package/dist/helpers/general/defaultPrefixApplier.d.ts +0 -3
  231. package/dist/helpers/general/defaultPrefixApplier.d.ts.map +0 -1
  232. package/dist/helpers/general/defaultValueComparer.d.ts +0 -3
  233. package/dist/helpers/general/defaultValueComparer.d.ts.map +0 -1
  234. package/dist/helpers/general/index.d.ts.map +0 -1
  235. package/dist/helpers/index.d.ts +0 -4
  236. package/dist/helpers/index.d.ts.map +0 -1
  237. package/dist/helpers/index.js +0 -8
  238. package/dist/helpers/parser/assignParents.d.ts +0 -4
  239. package/dist/helpers/parser/assignParents.d.ts.map +0 -1
  240. package/dist/helpers/parser/assignParents.js +0 -71
  241. package/dist/helpers/parser/checkParserOpts.d.ts.map +0 -1
  242. package/dist/helpers/parser/extractPosition.d.ts +0 -5
  243. package/dist/helpers/parser/extractPosition.d.ts.map +0 -1
  244. package/dist/helpers/parser/getUnclosedRightParenCount.d.ts +0 -4
  245. package/dist/helpers/parser/getUnclosedRightParenCount.d.ts.map +0 -1
  246. package/dist/helpers/parser/index.d.ts +0 -9
  247. package/dist/helpers/parser/index.d.ts.map +0 -1
  248. package/dist/helpers/parser/index.js +0 -18
  249. package/dist/helpers/parser/parseParserOptions.d.ts.map +0 -1
  250. package/dist/helpers/parser/seal.d.ts +0 -8
  251. package/dist/helpers/parser/seal.d.ts.map +0 -1
  252. package/dist/helpers/parser/seal.js +0 -10
  253. package/dist/helpers/parser/setParent.d.ts +0 -6
  254. package/dist/helpers/parser/setParent.d.ts.map +0 -1
  255. package/dist/helpers/parser/setParent.js +0 -4
  256. package/dist/helpers/parser/unescape.d.ts.map +0 -1
  257. package/src/ast/classes/ArrayNode.ts +0 -46
  258. package/src/ast/classes/Condition.ts +0 -22
  259. package/src/ast/classes/ConditionNode.ts +0 -141
  260. package/src/ast/classes/ErrorToken.ts +0 -49
  261. package/src/ast/classes/Expression.ts +0 -26
  262. package/src/ast/classes/ExpressionNode.ts +0 -62
  263. package/src/ast/classes/GroupNode.ts +0 -127
  264. package/src/ast/classes/Node.ts +0 -47
  265. package/src/ast/classes/Token.ts +0 -59
  266. package/src/ast/classes/ValidToken.ts +0 -56
  267. package/src/ast/classes/VariableNode.ts +0 -67
  268. package/src/ast/classes/index.ts +0 -13
  269. package/src/helpers/index.ts +0 -6
  270. package/src/helpers/parser/assignParents.ts +0 -51
  271. package/src/helpers/parser/index.ts +0 -10
  272. package/src/helpers/parser/seal.ts +0 -14
  273. package/src/helpers/parser/setParent.ts +0 -5
  274. /package/dist/{helpers/general → defaults}/defaultConditionNormalizer.js +0 -0
  275. /package/dist/{helpers/general → defaults}/defaultKeyParser.js +0 -0
  276. /package/dist/{helpers/general → defaults}/defaultPrefixApplier.js +0 -0
  277. /package/dist/{helpers/general → defaults}/defaultValueComparer.js +0 -0
  278. /package/dist/{helpers/general → internal}/applyBoolean.d.ts +0 -0
  279. /package/dist/{helpers/general → internal}/applyBoolean.js +0 -0
  280. /package/dist/{helpers/general → internal}/applyPrefix.js +0 -0
  281. /package/dist/{helpers/parser → internal}/extractPosition.js +0 -0
  282. /package/dist/{helpers/parser → internal}/unescape.d.ts +0 -0
  283. /package/dist/{helpers/parser → internal}/unescape.js +0 -0
  284. /package/src/{helpers/general → internal}/applyBoolean.ts +0 -0
  285. /package/src/{helpers/parser → internal}/unescape.ts +0 -0
package/src/Parser.ts CHANGED
@@ -8,34 +8,34 @@ import type { AddParameters , DeepPartial } from "@alanscodelog/utils/types"
8
8
  import { unreachable } from "@alanscodelog/utils/unreachable.js"
9
9
 
10
10
  import { pos } from "./ast/builders/pos.js"
11
- import { ArrayNode } from "./ast/classes/ArrayNode.js"
12
- import { ConditionNode } from "./ast/classes/ConditionNode.js"
13
- import { ErrorToken } from "./ast/classes/ErrorToken.js"
14
- import { ExpressionNode } from "./ast/classes/ExpressionNode.js"
15
- import { GroupNode } from "./ast/classes/GroupNode.js"
16
- import { Condition, Expression } from "./ast/classes/index.js"
17
- import { ValidToken } from "./ast/classes/ValidToken.js"
18
- import { VariableNode } from "./ast/classes/VariableNode.js"
11
+ import { createCondition } from "./ast/createNormalizedCondition.js"
12
+ import { createExpression } from "./ast/createNormalizedExpression.js"
19
13
  import * as handle from "./ast/handlers.js"
20
- import { applyBoolean } from "./helpers/general/applyBoolean.js"
21
- import { applyPrefix } from "./helpers/general/applyPrefix.js"
22
- import { checkParserOpts } from "./helpers/parser/checkParserOpts.js"
23
- import { extractPosition } from "./helpers/parser/extractPosition.js"
24
- import { getUnclosedRightParenCount } from "./helpers/parser/getUnclosedRightParenCount.js"
25
- import { parseParserOptions } from "./helpers/parser/parseParserOptions.js"
26
- import { seal } from "./helpers/parser/seal.js"
14
+ import { applyBoolean } from "./internal/applyBoolean.js"
15
+ import { applyPrefix } from "./internal/applyPrefix.js"
16
+ import { checkParserOpts } from "./internal/checkParserOpts.js"
17
+ import { escapeVariableOrPrefix } from "./internal/escapeVariableOrPrefix.js"
18
+ import { extractPosition } from "./internal/extractPosition.js"
19
+ import { getUnclosedRightParenCount } from "./internal/getUnclosedRightParenCount.js"
20
+ import { parseParserOptions } from "./internal/parseParserOptions.js"
21
+ import { unescape } from "./internal/unescape.js"
27
22
  import { $C, $T, Lexer,type RealTokenType, type Token, type TokenCategoryType, type TokenType } from "./Lexer.js"
28
- import type { ParserResults, TokenBooleanTypes } from "./types/ast.js"
29
- import { type AnyToken, type Completion, type Position, type Suggestion,SUGGESTION_TYPE, TOKEN_TYPE } from "./types/index.js"
23
+ import type { ArrayNode, ConditionNode, GroupNode, NormalizedCondition, NormalizedExpression, ParserResults, TokenBooleanTypes, ValidToken, VariableNode, } from "./types/ast.js"
24
+ import { type AnyToken, AST_TYPE,type Completion, type Position, type Suggestion,SUGGESTION_TYPE, TOKEN_TYPE } from "./types/index.js"
30
25
  import type { FullParserOptions, KeywordEntry, ParserOptions, ValidationQuery, ValueQuery } from "./types/parser.js"
31
26
  import { extractTokens } from "./utils/extractTokens.js"
27
+ import { generateParentsMap } from "./utils/generateParentsMap.js"
32
28
  import { getCursorInfo } from "./utils/getCursorInfo.js"
29
+ import { getParent } from "./utils/getParent.js"
33
30
  import { getSurroundingErrors } from "./utils/getSurroundingErrors.js"
31
+ import { isNode } from "./utils/isNode.js"
32
+ import { isToken } from "./utils/isToken.js"
34
33
 
35
34
  const OPPOSITE = {
36
35
  [TOKEN_TYPE.AND]: TOKEN_TYPE.OR,
37
36
  [TOKEN_TYPE.OR]: TOKEN_TYPE.AND,
38
37
  }
38
+
39
39
  function isEqualSet(setA: Set<any>, setB: Set<any>): boolean {
40
40
  if (setA.size !== setB.size) return false
41
41
  for (const key of setA) {
@@ -59,11 +59,11 @@ const createDefaultRequires = (partial: DeepPartial<Suggestion["requires"]> = {}
59
59
  })
60
60
 
61
61
  /** Returns if valid token requires whitespace if none between cursor and token. */
62
- const tokenRequiresWhitespace = (validToken: ValidToken | undefined, whitespace: boolean, wordOps: KeywordEntry[]): boolean => {
63
- if (whitespace || validToken === undefined) return false
64
- return validToken.type === TOKEN_TYPE.VALUE ||
65
- ([TOKEN_TYPE.AND, TOKEN_TYPE.OR, TOKEN_TYPE.NOT].includes(validToken.type) &&
66
- wordOps.find(_ => _.value === validToken.value) !== undefined)
62
+ const tokenRequiresWhitespace = (valid: ValidToken | undefined, whitespace: boolean, wordOps: KeywordEntry[]): boolean => {
63
+ if (whitespace || valid === undefined) return false
64
+ return valid.type === TOKEN_TYPE.VALUE ||
65
+ ([TOKEN_TYPE.AND, TOKEN_TYPE.OR, TOKEN_TYPE.NOT].includes(valid.type) &&
66
+ wordOps.find(_ => _.value === valid.value) !== undefined)
67
67
  }
68
68
  const tokenVariable = [TOKEN_TYPE.BACKTICK, TOKEN_TYPE.DOUBLEQUOTE, TOKEN_TYPE.SINGLEQUOTE, TOKEN_TYPE.VALUE, TOKEN_TYPE.REGEX]
69
69
 
@@ -173,8 +173,6 @@ export class Parser<T extends {} = {}> {
173
173
  rawInput: string
174
174
  },
175
175
  ): ParserResults {
176
- // eslint-disable-next-line prefer-rest-params
177
- const doSeal = arguments[1]?.seal ?? true
178
176
  if (typeof input === "string" && isWhitespace(input)) {
179
177
  return handle.token.value(undefined, { start: 0, end: 0 }) as any
180
178
  }
@@ -187,9 +185,6 @@ export class Parser<T extends {} = {}> {
187
185
  lexedTokens,
188
186
  }
189
187
  const res = this.ruleMain()
190
- if (doSeal) {
191
- seal(res)
192
- }
193
188
  this.state = {
194
189
  rawInput: "",
195
190
  shift: 0,
@@ -199,14 +194,9 @@ export class Parser<T extends {} = {}> {
199
194
  return res
200
195
  }
201
196
 
202
- subParserOne?: Parser<T> & {
203
- parse: AddParameters<Parser<T>["parse"], [{ seal: boolean }]>
204
- }
205
-
206
- subParserTwo?: Parser<T> & {
207
- parse: AddParameters<Parser<T>["parse"], [{ seal: boolean }]>
208
- }
209
-
197
+ subParserOne?: Parser<T>
198
+
199
+ subParserTwo?: Parser<T>
210
200
 
211
201
  createSubParserIfNotExists(opts: ParserOptions<T>, which: "One" | "Two" = "One"): Parser["subParserOne"] {
212
202
  if (this[`subParser${which}`] === undefined) {
@@ -444,13 +434,13 @@ export class Parser<T extends {} = {}> {
444
434
  const property = this.ruleConditionProperty()
445
435
  const propVal = property?.prop?.value === undefined
446
436
  ? undefined
447
- : property.prop.value instanceof ErrorToken
437
+ : !property.prop.value.valid
448
438
  ? ""
449
439
  : property.prop.value.value
450
440
 
451
441
  const propOpVal = property?.rest?.propertyOperator === undefined
452
442
  ? undefined
453
- : property.rest.propertyOperator instanceof ErrorToken
443
+ : !property.rest.propertyOperator?.valid
454
444
  ? ""
455
445
  : property.rest.propertyOperator?.value
456
446
 
@@ -466,7 +456,9 @@ export class Parser<T extends {} = {}> {
466
456
  let value = this.ruleConditionValue(property, { convertRegexValues, convertArrayValues })
467
457
 
468
458
  let group
469
- if (!(value instanceof ArrayNode)
459
+ if (
460
+ isNode(value)
461
+ && !(value.type === AST_TYPE.ARRAY)
470
462
  && !isArray(value)
471
463
  && (!value || this.options.prefixableGroups)
472
464
  && this.isType(this.peek(1), $T.PAREN_L) // is not already plain group
@@ -478,7 +470,11 @@ export class Parser<T extends {} = {}> {
478
470
  group = value
479
471
  value = undefined
480
472
  }
481
- if (convertRegexValues && value instanceof VariableNode && value.quote?.left.type === TOKEN_TYPE.REGEX) {
473
+ if (
474
+ convertRegexValues && isNode(value)
475
+ && value.type === AST_TYPE.VARIABLE
476
+ && value.quote?.left.type === TOKEN_TYPE.REGEX
477
+ ) {
482
478
  value = handle.variable(undefined, undefined, handle.token.value(
483
479
  (value.quote?.left?.value ?? "") + (value.value.value ?? "") + (value.quote?.right?.value ?? ""),
484
480
  pos(value),
@@ -607,7 +603,7 @@ export class Parser<T extends {} = {}> {
607
603
  regexValues: convertRegexValues,
608
604
  arrayValues: convertArrayValues,
609
605
  }, "One")
610
- const parsed = this.subParserOne!.parse(" ".repeat(start) + subInput, { seal: false })
606
+ const parsed = this.subParserOne!.parse(" ".repeat(start) + subInput)
611
607
  return [parenL, parsed, parenR]
612
608
  }
613
609
  return [parenL, condition, parenR]
@@ -655,14 +651,16 @@ export class Parser<T extends {} = {}> {
655
651
  expandedPropertySeparator: undefined,
656
652
  arrayValues: false,
657
653
  }, "Two")
658
- const parsed = this.subParserTwo!.parse(" ".repeat(start) + subInput, { seal: false })
659
- if (parsed instanceof ConditionNode) {
654
+ const parsed = this.subParserTwo!.parse(" ".repeat(start) + subInput)
655
+ if ("type" in parsed && parsed.type === AST_TYPE.CONDITION) {
660
656
  return parsed.value as ArrayNode
661
657
  }
662
- if (parsed instanceof ErrorToken || parsed instanceof ExpressionNode || parsed instanceof GroupNode) {
658
+ if (("valid" in parsed && !parsed.valid)
659
+ || ("type" in parsed && (parsed.type === AST_TYPE.EXPRESSION || parsed.type === AST_TYPE.GROUP))
660
+ ) {
663
661
  unreachable("parsed.value should not be an ErrorToken, ExpressionNode, or GroupNode.")
664
662
  }
665
- return parsed
663
+ return parsed as any as VariableNode
666
664
  }
667
665
 
668
666
  ruleConditionProperty(): {
@@ -961,15 +959,16 @@ export class Parser<T extends {} = {}> {
961
959
  }
962
960
 
963
961
  /**
964
- * Given a list of @see Suggestion entries, the parser options, and a list of variables, prefixes, operators, etc, and the preferred quote type, returns a list of @see Completion entries.
962
+ * Given the ast, a list of {@link Suggestion} entries, the parser options, and a list of variables, prefixes, operators, etc, and the preferred quote type, returns a list of {@link Completion} entries.
965
963
  *
966
964
  * It takes care of suggesting the correct delimiters for fixes, quoting variables/prefixes if it would not be possible to parse them unquoted, and separating symbol from non-symbol (word) operators.
967
965
  *
968
- * Does not add whitespace or group requirements. The suggestion information is still in the completion if you wish to show these. But they should not be added to the completion value if using @see autoreplace which will take care of it.
966
+ * Does not add whitespace or group requirements. The suggestion information is still in the completion if you wish to show these. But they should not be added to the completion value if using {@link autoreplace} which will take care of it.
969
967
  *
970
- * Is not aware of existing values. You will have to use @see getCursorInfo to understand the context in which the suggestion was made, so that, for example, you could filter out used regex flags.
968
+ * Is not aware of existing values. You will have to use {@link getCursorInfo} to understand the context in which the suggestion was made, so that, for example, you could filter out used regex flags.
971
969
  */
972
970
  autocomplete(
971
+ ast: ParserResults,
973
972
  suggestions: Suggestion[],
974
973
  {
975
974
  values = [], arrayValues = [], variables = [], prefixes = [], properties = [], expandedPropertyOperators = [], customPropertyOperators = (this as any as Parser<T>).options.customPropertyOperators ?? [], keywords = (this as any as Parser<T>).options.keywords, regexFlags = ["i", "m", "u"], quote = "\"",
@@ -986,6 +985,7 @@ export class Parser<T extends {} = {}> {
986
985
  keywords?: FullParserOptions<T>["keywords"]
987
986
  } = {},
988
987
  ): Completion[] {
988
+ const parentMap = generateParentsMap(ast)
989
989
  const self = (this as any as Parser<T>)
990
990
  return suggestions.map(suggestion => {
991
991
  const type = suggestion.type
@@ -1007,11 +1007,11 @@ export class Parser<T extends {} = {}> {
1007
1007
  if (suggestion.type !== SUGGESTION_TYPE.REGEX_FLAGS) {return true}
1008
1008
 
1009
1009
  const token = suggestion.cursorInfo
1010
- const flags = token.at && (token.at.parent as VariableNode)?.quote?.flags === suggestion.cursorInfo.at
1010
+ const flags = token.at && (getParent(token.at, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.at
1011
1011
  ? token.at
1012
- : token.next && (token.next.parent as VariableNode)?.quote?.flags === suggestion.cursorInfo.next
1012
+ : token.next && (getParent(token.next, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.next
1013
1013
  ? token.next
1014
- : token.prev && (token.prev.parent as VariableNode)?.quote?.flags === suggestion.cursorInfo.prev
1014
+ : token.prev && (getParent(token.prev, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.prev
1015
1015
  ? token.prev
1016
1016
  : undefined
1017
1017
 
@@ -1050,38 +1050,17 @@ export class Parser<T extends {} = {}> {
1050
1050
  : type === SUGGESTION_TYPE.VALUE
1051
1051
  ? values
1052
1052
  : unreachable()
1053
- return arr.map(variable => {
1054
- // we don't need to alter options since we can just check there are no quotes (also tells us no prefixes are used) and no operators are defined
1055
- const res = self.parse(variable)
1056
- if (res instanceof ConditionNode &&
1057
- res.operator === undefined &&
1058
- res.value instanceof VariableNode &&
1059
- res.value.quote === undefined) {
1060
- return { suggestion, value: res.value.value.value }
1061
- } else {
1062
- return { suggestion, value: quote + variable.replace(new RegExp(quote, "g"), `\\${quote}`) + quote }
1063
- }
1064
- })
1053
+ return arr.map(variable => ({ suggestion, value: escapeVariableOrPrefix(variable, quote) }))
1065
1054
  }
1066
- case SUGGESTION_TYPE.PREFIX: return prefixes.map(prefix => {
1067
- const res = self.parse(prefix)
1068
- if (res instanceof ConditionNode &&
1069
- res.operator === undefined &&
1070
- res.value instanceof VariableNode &&
1071
- res.value.quote === undefined) {
1072
- return { suggestion, value: res.value.value.value }
1073
- } else {
1074
- return { suggestion, value: quote + prefix.replace(new RegExp(quote, "g"), `\\${quote}`) + quote }
1075
- }
1076
- })
1055
+ case SUGGESTION_TYPE.PREFIX: return prefixes.map(prefix => ({ suggestion, value: escapeVariableOrPrefix(prefix, quote) }))
1077
1056
  }
1078
1057
  }).flat()
1079
1058
  }
1080
1059
 
1081
1060
  /**
1082
- * Given the input string and a @see Completion consisting of the value of the replacement and a @see Suggestion entry, returns the replacement string and the new position of the cursor.
1061
+ * Given the input string and a {@link Completion} consisting of the value of the replacement and a {@link Suggestion} entry, returns the replacement string and the new position of the cursor.
1083
1062
  *
1084
- * The value passed should be escaped if it's needed (or quoted). @see autocomplete already takes care of quoting variables if you're using it.
1063
+ * The value passed should be escaped if it's needed (or quoted). {@link autocomplete} already takes care of quoting variables if you're using it.
1085
1064
  */
1086
1065
  autoreplace(
1087
1066
  input: string,
@@ -1119,9 +1098,9 @@ export class Parser<T extends {} = {}> {
1119
1098
  }
1120
1099
 
1121
1100
  /**
1122
- * Returns a list of suggestions ( @see Suggestion ). These are not a list of autocomplete entries (with values), but more a list of entries describing possible suggestions. This list can then be passed to @see Parser["autocomplete"] to build a list to show users, from which you can then pick an entry to pass to @see Parser["autoreplace"] .
1101
+ * Returns a list of suggestions ( {@link Suggestion} ). These are not a list of autocomplete entries (with values), but more a list of entries describing possible suggestions. This list can then be passed to {@link Parser}["autocomplete"] to build a list to show users, from which you can then pick an entry to pass to {@link Parser}["autoreplace"] .
1123
1102
  *
1124
- * The list returned is "unsorted", but there is still some logic to the order. Fixes for errors are suggested first, in the order returned by @see getSurroundingErrors. Regular suggestions come after in the following order: prefixes if enabled, variables, boolean symbol operators, then boolean word operators.
1103
+ * The list returned is "unsorted", but there is still some logic to the order. Fixes for errors are suggested first, in the order returned by {@link getSurroundingErrors}. Regular suggestions come after in the following order: prefixes if enabled, variables, boolean symbol operators, then boolean word operators.
1125
1104
  *
1126
1105
  * When the cursor is between two tokens that have possible suggestions, only suggestion types for the token before are returned. For example:
1127
1106
  *
@@ -1141,6 +1120,7 @@ export class Parser<T extends {} = {}> {
1141
1120
  * ```
1142
1121
  */
1143
1122
  autosuggest(input: string, ast: ParserResults, index: number): Suggestion[] {
1123
+ const parentMap = generateParentsMap(ast)
1144
1124
  // wrapped like this because the function is HUGE
1145
1125
  const opts = (this as any as Parser<T>).options
1146
1126
  const tokens = extractTokens(ast)
@@ -1171,7 +1151,7 @@ export class Parser<T extends {} = {}> {
1171
1151
  : requiresWhitespaceNext
1172
1152
 
1173
1153
  const suggestions: Suggestion[] = []
1174
- if (ast instanceof ErrorToken) {
1154
+ if (isToken(ast) && !ast.valid) {
1175
1155
  suggestions.push({
1176
1156
  type: SUGGESTION_TYPE.PREFIX,
1177
1157
  requires: createDefaultRequires({ group: true }),
@@ -1207,8 +1187,9 @@ export class Parser<T extends {} = {}> {
1207
1187
  case TOKEN_TYPE.DOUBLEQUOTE:
1208
1188
  case TOKEN_TYPE.SINGLEQUOTE:
1209
1189
  case TOKEN_TYPE.BACKTICK: {
1210
- const isLeft = (error.parent as VariableNode).quote!.left === error
1211
- const isRight = (error.parent as VariableNode).quote!.right === error
1190
+ const errorParent = getParent(error, parentMap)
1191
+ const isLeft = (errorParent as VariableNode).quote!.left === error
1192
+ const isRight = (errorParent as VariableNode).quote!.right === error
1212
1193
  suggestions.push({
1213
1194
  ...errorSuggestion,
1214
1195
  type: type as any as SUGGESTION_TYPE,
@@ -1254,10 +1235,13 @@ export class Parser<T extends {} = {}> {
1254
1235
  })
1255
1236
  break
1256
1237
  case TOKEN_TYPE.VALUE: {
1257
- const prefixedValue = error.parent instanceof VariableNode ? error.parent?.prefix?.value : false
1258
- const isRegexValue = error.parent instanceof VariableNode && (
1259
- error.parent.quote?.left.type === TOKEN_TYPE.REGEX ||
1260
- error.parent.quote?.right.type === TOKEN_TYPE.REGEX
1238
+ const errorParent = getParent(error, parentMap)
1239
+ const prefixedValue = errorParent?.type === AST_TYPE.VARIABLE
1240
+ ? (getParent(error, parentMap) as VariableNode)?.prefix?.value
1241
+ : false
1242
+ const isRegexValue = errorParent?.type === AST_TYPE.VARIABLE && (
1243
+ errorParent.quote?.left.type === TOKEN_TYPE.REGEX ||
1244
+ errorParent.quote?.right.type === TOKEN_TYPE.REGEX
1261
1245
  )
1262
1246
  if (!isRegexValue) {
1263
1247
  // both are always suggested since missing value tokens only happen for variables
@@ -1322,22 +1306,23 @@ export class Parser<T extends {} = {}> {
1322
1306
  }
1323
1307
  }
1324
1308
  }
1309
+
1325
1310
 
1326
1311
  /** The quotes are checked because of situations like `prefix|"var"`.*/
1327
- const prevVar = token.valid.prev?.parent
1328
- const nextVar = token.valid.next?.parent
1329
- const prevCondition = prevVar?.parent
1330
- const nextCondition = nextVar?.parent
1331
- const atVar = token.at?.parent
1332
- const atCondition = atVar?.parent
1312
+ const prevVar = getParent(token.valid.prev, parentMap)
1313
+ const nextVar = getParent(token.valid.next, parentMap)
1314
+ const prevCondition = getParent(prevVar, parentMap)
1315
+ const nextCondition = getParent(nextVar, parentMap)
1316
+ const atVar = getParent(token.at, parentMap)
1317
+ const atCondition = getParent(atVar, parentMap)
1333
1318
 
1334
1319
  const isVarPrev =
1335
1320
  !token.whitespace.prev &&
1336
1321
  token.valid.prev?.type !== TOKEN_TYPE.REGEX &&
1337
- prevVar instanceof VariableNode &&
1322
+ prevVar?.type === AST_TYPE.VARIABLE &&
1338
1323
  (
1339
1324
  (
1340
- prevCondition instanceof ConditionNode &&
1325
+ prevCondition?.type === AST_TYPE.CONDITION &&
1341
1326
  prevCondition.value === prevVar &&
1342
1327
  (
1343
1328
  prevVar.quote?.right === token.valid.prev ||
@@ -1345,17 +1330,17 @@ export class Parser<T extends {} = {}> {
1345
1330
  )
1346
1331
  ) ||
1347
1332
  (
1348
- prevCondition instanceof ArrayNode
1333
+ prevCondition?.type === AST_TYPE.ARRAY
1349
1334
  )
1350
1335
  )
1351
1336
 
1352
1337
  const isVarNext =
1353
1338
  !token.whitespace.next &&
1354
1339
  token.valid.next?.type !== TOKEN_TYPE.REGEX &&
1355
- nextVar instanceof VariableNode &&
1356
- (
1340
+ nextVar?.type === AST_TYPE.VARIABLE
1341
+ && (
1357
1342
  (
1358
- nextCondition instanceof ConditionNode &&
1343
+ nextCondition?.type === AST_TYPE.CONDITION &&
1359
1344
  nextCondition.value === nextVar &&
1360
1345
  (
1361
1346
  nextVar.quote?.left === token.valid.next ||
@@ -1363,41 +1348,44 @@ export class Parser<T extends {} = {}> {
1363
1348
  )
1364
1349
  ) ||
1365
1350
  (
1366
- nextCondition instanceof ArrayNode
1351
+ nextCondition?.type === AST_TYPE.ARRAY
1367
1352
  )
1368
1353
  )
1369
1354
 
1370
1355
  const isVarAt = (
1371
1356
  (
1372
- atVar instanceof VariableNode &&
1373
- atCondition instanceof ConditionNode
1357
+ atVar?.type === AST_TYPE.VARIABLE &&
1358
+ atCondition?.type === AST_TYPE.CONDITION
1374
1359
  ) ||
1375
1360
  (
1376
- prevVar instanceof VariableNode &&
1361
+ prevVar?.type === AST_TYPE.VARIABLE &&
1377
1362
  token.valid.prev === prevVar?.quote?.left) ||
1378
1363
 
1379
1364
  (
1380
- nextVar instanceof VariableNode &&
1365
+ nextVar?.type === AST_TYPE.VARIABLE &&
1381
1366
  token.valid.next === nextVar?.quote?.right
1382
1367
  )
1383
1368
  )
1384
1369
 
1385
1370
  const isPropertyPrev =
1386
- prevCondition instanceof ConditionNode &&
1371
+ prevCondition?.type === AST_TYPE.CONDITION &&
1387
1372
  prevVar !== undefined &&
1388
1373
  prevVar === prevCondition?.property
1389
1374
  const isPropertyNext =
1390
- nextCondition instanceof ConditionNode &&
1375
+ nextCondition?.type === AST_TYPE.CONDITION &&
1391
1376
  nextVar !== undefined &&
1392
1377
  nextVar === nextCondition?.property
1393
1378
  const isPropertyAt =
1394
- atCondition instanceof ConditionNode &&
1379
+ atCondition?.type === AST_TYPE.CONDITION &&
1395
1380
  atVar !== undefined &&
1396
1381
  atVar === atCondition?.property
1397
1382
 
1398
- const isPropertyOperatorPrev = prevVar instanceof ConditionNode && token.valid.prev === prevVar?.propertyOperator
1399
- const isPropertyOperatorNext = nextVar instanceof ConditionNode && token.valid.next === nextVar?.propertyOperator
1400
- const isPropertyOperatorAt = atVar instanceof ConditionNode && token.at === atVar?.propertyOperator
1383
+ const isPropertyOperatorPrev = prevVar?.type === AST_TYPE.CONDITION
1384
+ && token.valid.prev === prevVar?.propertyOperator
1385
+ const isPropertyOperatorNext = nextVar?.type === AST_TYPE.CONDITION
1386
+ && token.valid.next === nextVar?.propertyOperator
1387
+ const isPropertyOperatorAt = atVar?.type === AST_TYPE.CONDITION
1388
+ && token.at === atVar?.propertyOperator
1401
1389
 
1402
1390
  /** Situations like `[|]` and `[|` */
1403
1391
  const noArrayValuesTarget = token.valid.prev?.type === TOKEN_TYPE.BRACKETL &&
@@ -1434,24 +1422,26 @@ export class Parser<T extends {} = {}> {
1434
1422
 
1435
1423
 
1436
1424
  if (target) {
1437
- const parent = target.parent
1438
- if (parent instanceof VariableNode) {
1425
+ const parent = getParent(target, parentMap)
1426
+ if (parent && parent.type === AST_TYPE.VARIABLE) {
1439
1427
  const range = pos(parent)
1440
- const condition = parent?.parent as ConditionNode
1428
+ const parentParent = getParent(parent, parentMap)
1429
+ const condition = parentParent as ConditionNode
1441
1430
  const isValue = condition.propertyOperator !== undefined && condition.value === parent
1442
- const maybeGroup = parent?.parent?.parent
1443
- const isPrefix = maybeGroup instanceof GroupNode && maybeGroup.prefix === condition
1431
+ const maybeGroup = getParent(parentParent, parentMap)
1432
+ const isPrefix = maybeGroup?.type === AST_TYPE.GROUP
1433
+ && maybeGroup.prefix === condition
1444
1434
 
1445
1435
  // look at whitespace before/after the entire variable
1446
1436
  const varStart = getCursorInfo(input, ast, parent.start)
1447
1437
  const varEnd = getCursorInfo(input, ast, parent.end)
1448
1438
  const targetRequiresWhitespacePrev = tokenRequiresWhitespace(varStart.valid.prev, varStart.whitespace.prev, wordOps)
1449
1439
  const targetRequiresWhitespaceNext = tokenRequiresWhitespace(varEnd.valid.next, varEnd.whitespace.next, wordOps)
1450
- const prefixedValue = target.parent instanceof VariableNode ? target.parent?.prefix?.value : false
1440
+ const prefixedValue = parent.type === AST_TYPE.VARIABLE ? parent?.prefix?.value : false
1451
1441
 
1452
1442
  // most of these require additional handling below
1453
1443
  const isSepPrev = token.prev?.type === TOKEN_TYPE.OP_EXPANDED_SEP
1454
- const arrayValue = target.parent?.parent instanceof ArrayNode
1444
+ const arrayValue = parentParent?.type === AST_TYPE.ARRAY
1455
1445
  const isRegexFlag = target === parent.quote?.flags
1456
1446
 
1457
1447
  if (!isRegexFlag && !isSepPrev && !isValue && !arrayValue && !prefixedValue && opts.prefixableGroups) {
@@ -1508,9 +1498,10 @@ export class Parser<T extends {} = {}> {
1508
1498
  })
1509
1499
  }
1510
1500
  if (propOpTarget) {
1501
+ const propOpTargetParent = getParent(propOpTarget, parentMap)
1511
1502
  suggestions.push({
1512
1503
  ...baseSuggestion,
1513
- type: (propOpTarget.parent as ConditionNode).sep
1504
+ type: (propOpTargetParent as ConditionNode).sep
1514
1505
  ? SUGGESTION_TYPE.EXPANDED_PROPERTY_OPERATOR
1515
1506
  : SUGGESTION_TYPE.CUSTOM_PROPERTY_OPERATOR
1516
1507
  ,
@@ -1540,7 +1531,7 @@ export class Parser<T extends {} = {}> {
1540
1531
  )
1541
1532
 
1542
1533
  if (canSuggestValue) {
1543
- const inArrayNode = [nextCondition, prevCondition, nextVar, prevVar].find(_ => _ instanceof ArrayNode) !== undefined
1534
+ const inArrayNode = [nextCondition, prevCondition, nextVar, prevVar].find(_ => _?.type === AST_TYPE.ARRAY) !== undefined
1544
1535
  const opsNotNeeded = ["and", "or"].includes(opts.onMissingBooleanOperator)
1545
1536
 
1546
1537
 
@@ -1564,24 +1555,26 @@ export class Parser<T extends {} = {}> {
1564
1555
  })
1565
1556
  }
1566
1557
  }
1567
-
1558
+ const tokenAtParent = getParent(token.at, parentMap)
1559
+ const tokenValidPrevParent = getParent(token.valid.prev, parentMap)
1560
+ const tokenValidNextParent = getParent(token.valid.next, parentMap)
1568
1561
  const canSuggestRegexFlags =
1569
1562
  // has existing flags before/after
1570
1563
  (
1571
1564
  token.at &&
1572
- token.at === (token.at?.parent as VariableNode)?.quote?.flags
1565
+ token.at === (tokenAtParent as VariableNode)?.quote?.flags
1573
1566
  ) ||
1574
1567
  (
1575
1568
  token.valid.prev &&
1576
- token.valid.prev === (token.valid.prev?.parent as VariableNode)?.quote?.flags
1569
+ token.valid.prev === (tokenValidPrevParent as VariableNode)?.quote?.flags
1577
1570
  ) ||
1578
1571
  (
1579
1572
  token.valid.next &&
1580
- token.valid.next === (token.valid.next?.parent as VariableNode)?.quote?.flags
1573
+ token.valid.next === (tokenValidNextParent as VariableNode)?.quote?.flags
1581
1574
  ) ||
1582
1575
  ( // no flags
1583
1576
  token.valid.prev?.type === TOKEN_TYPE.REGEX &&
1584
- token.valid.prev === (token.valid.prev.parent as VariableNode).quote?.right
1577
+ token.valid.prev === (tokenValidPrevParent as VariableNode).quote?.right
1585
1578
  )
1586
1579
 
1587
1580
  if (canSuggestRegexFlags) {
@@ -1622,16 +1615,16 @@ export class Parser<T extends {} = {}> {
1622
1615
  *
1623
1616
  * How the ast is evaluated for different operators can be controlled by the {@link ParserOptions.valueComparer valueComparer} option.
1624
1617
  */
1625
- evaluate(ast: Expression<any, any> | Condition<any, any>, context: Record<string, any>): boolean {
1618
+ evaluate(ast: NormalizedExpression<any, any> | NormalizedCondition<any, any>, context: Record<string, any>): boolean {
1626
1619
  this._checkEvaluationOptions()
1627
1620
  const opts = (this as any as Parser<T>).options
1628
1621
 
1629
- if (ast instanceof Condition) {
1622
+ if (ast.type === AST_TYPE.NORMALIZED_CONDITION) {
1630
1623
  const contextValue = get(context, ast.property)
1631
- const res = opts.valueComparer({ property: ast.property, value: ast.value, operator: ast.operator }, contextValue, context)
1624
+ const res = opts.valueComparer(ast, contextValue, context)
1632
1625
  return ast.negate ? !res : res
1633
1626
  }
1634
- if (ast instanceof Expression) {
1627
+ if (ast.type === AST_TYPE.NORMALIZED_EXPRESSION) {
1635
1628
  const left = this.evaluate(ast.left, context)
1636
1629
  const right = this.evaluate(ast.right, context)
1637
1630
 
@@ -1705,11 +1698,11 @@ export class Parser<T extends {} = {}> {
1705
1698
  *
1706
1699
  * Queries like `(a || b) && (a || c)` would require all the variables to be indexed `[Set(a), Set(b), Set(c)]`.
1707
1700
  */
1708
- getIndexes(ast: Condition | Expression): Set<string>[] {
1709
- if (ast instanceof Condition) {
1701
+ getIndexes(ast: NormalizedCondition | NormalizedExpression): Set<string>[] {
1702
+ if (ast.type === AST_TYPE.NORMALIZED_CONDITION) {
1710
1703
  return [new Set(ast.property.join("."))]
1711
1704
  }
1712
- if (ast instanceof Expression) {
1705
+ if (ast.type === AST_TYPE.NORMALIZED_EXPRESSION) {
1713
1706
  const left = this.getIndexes(ast.left)
1714
1707
  const right = this.getIndexes(ast.right)
1715
1708
 
@@ -1779,10 +1772,10 @@ export class Parser<T extends {} = {}> {
1779
1772
  /**
1780
1773
  * Normalizes the ast by applying {@link GroupNode GroupNodes} and converting {@link ConditionNode ConditionNodes} to {@link NormalizedConditionNode NormalizedConditionNodes}.
1781
1774
  */
1782
- normalize<TType extends string, TValue>(ast: ParserResults): Condition<TType, TValue> | Expression<TType, TValue> {
1775
+ normalize<TType extends string, TValue>(ast: ParserResults): NormalizedCondition<TType, TValue> | NormalizedExpression<TType, TValue> {
1783
1776
  this._checkEvaluationOptions()
1784
1777
  const opts = (this as any as Parser<T>).options
1785
- if (ast instanceof ErrorToken || !ast.valid) {
1778
+ if (!ast.valid) {
1786
1779
  throw new Error("AST node must be valid.")
1787
1780
  }
1788
1781
  // eslint-disable-next-line prefer-rest-params
@@ -1794,16 +1787,16 @@ export class Parser<T extends {} = {}> {
1794
1787
 
1795
1788
  const self_ = this as any as Parser & { normalize: AddParameters<Parser["normalize"], [typeof prefix, typeof groupValue, typeof operator]> }
1796
1789
 
1797
- if (ast instanceof ConditionNode) {
1798
- if (!(ast.value instanceof GroupNode)) {
1799
- const isValue = ast.value instanceof ArrayNode || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1800
- let name = ast.property
1790
+ if (ast.type === AST_TYPE.CONDITION) {
1791
+ if (!(ast.value.type === AST_TYPE.GROUP)) {
1792
+ const isValue = ast.value.type === AST_TYPE.ARRAY || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1793
+ let name = ast.property?.value?.value
1801
1794
  ? unescape(ast.property.value.value)
1802
1795
  : isValue
1803
1796
  // the property might be missing, whether this is valid or not is up to the user
1804
1797
  // e.g. if prefix is defined this would make some sense
1805
1798
  ? undefined
1806
- : unescape((ast.value as VariableNode)?.value.value)
1799
+ : unescape((ast.value as VariableNode)!.value!.value!)
1807
1800
  // some ancestor node went through the else block because it was a group node (e.g. prop:op(val))
1808
1801
  // so the "prefix" we passed is actually the name of the property (e.g. prop) and the value is the name we're getting here (e.g. val)
1809
1802
  const isNested = operator !== undefined
@@ -1815,18 +1808,18 @@ export class Parser<T extends {} = {}> {
1815
1808
  value = name ?? true
1816
1809
  name = prefix
1817
1810
  } else {
1818
- value = ast.value instanceof ArrayNode
1819
- ? ast.value.values.map(val => unescape(val.value.value))
1811
+ value = ast.value.type === AST_TYPE.ARRAY
1812
+ ? ast.value.values.map(val => unescape(val.value.value!))
1820
1813
  : (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1821
- ? ast.value.value.value
1822
- : ast.property && ast.value instanceof VariableNode
1823
- ? unescape(ast.value.value.value)
1814
+ ? ast.value.value?.value
1815
+ : ast.property && ast.value.type === AST_TYPE.VARIABLE
1816
+ ? unescape(ast.value.value.value!)
1824
1817
  : true
1825
1818
  }
1826
1819
  const propertyKeys = name ? opts.keyParser(name) : []
1827
1820
 
1828
1821
  const boolValue = applyBoolean(groupValue, ast.operator === undefined)
1829
- const valuePrefix = ast.value instanceof VariableNode && ast.value.prefix
1822
+ const valuePrefix = ast.value.type === AST_TYPE.VARIABLE && ast.value.prefix
1830
1823
  ? unescape(ast.value.prefix.value)
1831
1824
  : undefined
1832
1825
  // one or the other might be defined, but never both since nested properties (e.g. `prop:op(prop:op(...))`) are not allowed
@@ -1848,9 +1841,9 @@ export class Parser<T extends {} = {}> {
1848
1841
  condition: ast,
1849
1842
  }
1850
1843
  const res = opts.conditionNormalizer(query)
1851
- return new Condition({ property: propertyKeys, ...res })
1844
+ return createCondition({ property: propertyKeys, ...res })
1852
1845
  } else {
1853
- let name = unescape((ast.property as VariableNode).value.value) // this is always a variable node
1846
+ let name = unescape((ast.property as VariableNode).value.value!) // this is always a variable node
1854
1847
  if (prefix !== undefined) {
1855
1848
  name = applyPrefix(prefix, name, opts.prefixApplier)
1856
1849
  }
@@ -1863,26 +1856,26 @@ export class Parser<T extends {} = {}> {
1863
1856
  }
1864
1857
  }
1865
1858
 
1866
- if (ast instanceof GroupNode) {
1867
- const _prefix = ast.prefix instanceof ConditionNode && ast.prefix.value instanceof VariableNode
1868
- ? unescape(ast.prefix.value.value.value)
1859
+ if (ast.type === AST_TYPE.GROUP) {
1860
+ const _prefix = ast.prefix?.type === AST_TYPE.CONDITION && ast.prefix?.value.type === AST_TYPE.VARIABLE
1861
+ ? unescape(ast.prefix.value.value.value!)
1869
1862
  : undefined // we do not want to apply not tokens
1870
- const _groupValue = ast.prefix instanceof ConditionNode
1863
+ const _groupValue = ast.prefix?.type === AST_TYPE.CONDITION
1871
1864
  ? ast.prefix.operator === undefined
1872
- : !(ast.prefix instanceof ValidToken)
1865
+ : !(ast.prefix?.valid === true)
1873
1866
 
1874
1867
  const applied = applyPrefix(prefix, _prefix ?? "", opts.prefixApplier)
1875
1868
 
1876
1869
  return self_.normalize(ast.expression as any, applied, applyBoolean(groupValue, _groupValue), operator) as any
1877
1870
  }
1878
- if (ast instanceof ExpressionNode) {
1871
+ if (ast.type === AST_TYPE.EXPRESSION) {
1879
1872
  const left = self_.normalize(ast.left, prefix, groupValue, operator)
1880
1873
  const right = self_.normalize(ast.right, prefix, groupValue, operator)
1881
1874
 
1882
1875
  // apply De Morgan's laws if group prefix was negative
1883
1876
  // the values are already flipped, we just have to flip the operator
1884
- const type: TokenBooleanTypes = (groupValue === false ? OPPOSITE[ast.operator.type] : ast.operator.type) as TokenBooleanTypes
1885
- return new Expression<TType, TValue>({ operator: type, left: left as any, right: right as any })
1877
+ const type: TokenBooleanTypes = (groupValue === false ? OPPOSITE[ast.operator!.type!] : ast.operator.type) as TokenBooleanTypes
1878
+ return createExpression<TType, TValue>({ operator: type, left: left as any, right: right as any })
1886
1879
  }
1887
1880
  return unreachable()
1888
1881
  }
@@ -1898,7 +1891,7 @@ export class Parser<T extends {} = {}> {
1898
1891
  self._checkValidationOptions()
1899
1892
  const opts = self.options
1900
1893
  // see evaluate function, this method is practically identical, except we don't keep track of the real value (since we are not evaluating) and the actual nodes/tokens are passed to the valueValidator, not just the string values.
1901
- if (ast instanceof ErrorToken || !ast.valid) {
1894
+ if (!ast.valid) {
1902
1895
  throw new Error("AST node must be valid.")
1903
1896
  }
1904
1897
  /** Handle hidden recursive version of the function. */
@@ -1915,16 +1908,16 @@ export class Parser<T extends {} = {}> {
1915
1908
 
1916
1909
  const self_ = this as any as Parser & { validate: AddParameters<Parser["validate"], [typeof prefix, typeof groupValue, typeof results, typeof prefixes, typeof operator]> }
1917
1910
 
1918
- if (ast instanceof ConditionNode) {
1919
- if (!(ast.value instanceof GroupNode)) {
1920
- const isValue = ast.value instanceof ArrayNode || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1911
+ if (ast.type === AST_TYPE.CONDITION) {
1912
+ if (!(ast.value.type === AST_TYPE.GROUP)) {
1913
+ const isValue = ast.value.type === AST_TYPE.ARRAY || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1921
1914
  const nameNode = ast.property
1922
1915
  ? ast.property as VariableNode
1923
1916
  : isValue
1924
1917
  ? undefined
1925
1918
  : ast.value as VariableNode
1926
1919
 
1927
- let name = nameNode ? unescape(nameNode.value.value) : undefined
1920
+ let name = nameNode ? unescape(nameNode.value.value!) : undefined
1928
1921
  const isNested = operator !== undefined
1929
1922
  if (prefix !== undefined && !isNested) {
1930
1923
  name = name ? applyPrefix(prefix, name, opts.prefixApplier) : prefix
@@ -1938,11 +1931,11 @@ export class Parser<T extends {} = {}> {
1938
1931
  propertyNodes = [...prefixes]
1939
1932
  } else {
1940
1933
  propertyNodes = [...prefixes, ...(nameNode ? [nameNode] : [])]
1941
- value = ast.value instanceof ArrayNode
1934
+ value = ast.value.type === AST_TYPE.ARRAY
1942
1935
  ? ast.value.values
1943
1936
  : (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
1944
1937
  ? ast.value
1945
- : ast.property && ast.value instanceof VariableNode
1938
+ : ast.property && ast.value.type === AST_TYPE.VARIABLE
1946
1939
  ? ast.value
1947
1940
  : true
1948
1941
  }
@@ -1950,7 +1943,7 @@ export class Parser<T extends {} = {}> {
1950
1943
  const contextValue = context !== undefined ? get(context, propertyKeys) : undefined
1951
1944
 
1952
1945
  const boolValue = applyBoolean(groupValue, ast.operator === undefined)
1953
- const valuePrefix = ast.value instanceof VariableNode && ast.value.prefix
1946
+ const valuePrefix = ast.value.type === AST_TYPE.VARIABLE && ast.value.prefix
1954
1947
  ? ast.value.prefix
1955
1948
  : undefined
1956
1949
  operator ??= ast.propertyOperator as ValidToken<TOKEN_TYPE.VALUE | TOKEN_TYPE.OP_CUSTOM>
@@ -1977,7 +1970,7 @@ export class Parser<T extends {} = {}> {
1977
1970
  if (res && !isArray(res)) throw new Error("The valueValidator must return an array or nothing/undefined")
1978
1971
  if (res) { for (const entry of res) results.push(entry) }
1979
1972
  } else {
1980
- let name = unescape((ast.property as VariableNode).value.value) // this is always a variable node
1973
+ let name = unescape((ast.property as VariableNode).value.value!) // this is always a variable node
1981
1974
  if (prefix !== undefined) {
1982
1975
  name = applyPrefix(prefix, name, opts.prefixApplier)
1983
1976
  }
@@ -1991,19 +1984,19 @@ export class Parser<T extends {} = {}> {
1991
1984
  }
1992
1985
  }
1993
1986
 
1994
- if (ast instanceof GroupNode) {
1995
- const _prefix = ast.prefix instanceof ConditionNode && ast.prefix.value instanceof VariableNode
1987
+ if (ast.type === AST_TYPE.GROUP) {
1988
+ const _prefix = ast.prefix?.type === AST_TYPE.CONDITION && ast.prefix.value.type === AST_TYPE.VARIABLE
1996
1989
  ? ast.prefix.value
1997
1990
  : undefined // we do not want to apply not tokens
1998
1991
  if (_prefix) prefixes.push(_prefix)
1999
1992
 
2000
- const _groupValue = ast.prefix instanceof ConditionNode
1993
+ const _groupValue = ast.prefix?.type === AST_TYPE.CONDITION
2001
1994
  ? ast.prefix.operator === undefined
2002
- : !(ast.prefix instanceof ValidToken)
1995
+ : !(ast.prefix?.valid === true)
2003
1996
 
2004
1997
  self_.validate(ast.expression as any, context, applyPrefix(prefix, _prefix?.value.value ?? "", opts.prefixApplier), applyBoolean(groupValue, _groupValue), results, prefixes, operator)
2005
1998
  }
2006
- if (ast instanceof ExpressionNode) {
1999
+ if (ast.type === AST_TYPE.EXPRESSION) {
2007
2000
  // prefixes must be spread because we don't want the left branch (if it goes deeper) to affect the right
2008
2001
  self_.validate(ast.left, context, prefix, groupValue, results, [...prefixes], operator)
2009
2002
  self_.validate(ast.right, context, prefix, groupValue, results, [...prefixes], operator)