@witchcraft/expressit 0.0.2

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 (307) hide show
  1. package/README.md +86 -0
  2. package/dist/ast/builders/array.d.ts +8 -0
  3. package/dist/ast/builders/array.d.ts.map +1 -0
  4. package/dist/ast/builders/array.js +31 -0
  5. package/dist/ast/builders/condition.d.ts +20 -0
  6. package/dist/ast/builders/condition.d.ts.map +1 -0
  7. package/dist/ast/builders/condition.js +28 -0
  8. package/dist/ast/builders/delim.d.ts +11 -0
  9. package/dist/ast/builders/delim.d.ts.map +1 -0
  10. package/dist/ast/builders/delim.js +20 -0
  11. package/dist/ast/builders/error.d.ts +9 -0
  12. package/dist/ast/builders/error.d.ts.map +1 -0
  13. package/dist/ast/builders/error.js +16 -0
  14. package/dist/ast/builders/expression.d.ts +12 -0
  15. package/dist/ast/builders/expression.d.ts.map +1 -0
  16. package/dist/ast/builders/expression.js +31 -0
  17. package/dist/ast/builders/group.d.ts +20 -0
  18. package/dist/ast/builders/group.d.ts.map +1 -0
  19. package/dist/ast/builders/group.js +47 -0
  20. package/dist/ast/builders/index.d.ts +12 -0
  21. package/dist/ast/builders/index.d.ts.map +1 -0
  22. package/dist/ast/builders/index.js +24 -0
  23. package/dist/ast/builders/isFullPos.d.ts +6 -0
  24. package/dist/ast/builders/isFullPos.d.ts.map +1 -0
  25. package/dist/ast/builders/isFullPos.js +6 -0
  26. package/dist/ast/builders/pos.d.ts +21 -0
  27. package/dist/ast/builders/pos.d.ts.map +1 -0
  28. package/dist/ast/builders/pos.js +28 -0
  29. package/dist/ast/builders/token.d.ts +12 -0
  30. package/dist/ast/builders/token.d.ts.map +1 -0
  31. package/dist/ast/builders/token.js +26 -0
  32. package/dist/ast/builders/type.d.ts +6 -0
  33. package/dist/ast/builders/type.d.ts.map +1 -0
  34. package/dist/ast/builders/type.js +37 -0
  35. package/dist/ast/builders/variable.d.ts +17 -0
  36. package/dist/ast/builders/variable.d.ts.map +1 -0
  37. package/dist/ast/builders/variable.js +62 -0
  38. package/dist/ast/classes/ArrayNode.d.ts +18 -0
  39. package/dist/ast/classes/ArrayNode.d.ts.map +1 -0
  40. package/dist/ast/classes/ArrayNode.js +55 -0
  41. package/dist/ast/classes/Condition.d.ts +13 -0
  42. package/dist/ast/classes/Condition.d.ts.map +1 -0
  43. package/dist/ast/classes/Condition.js +21 -0
  44. package/dist/ast/classes/ConditionNode.d.ts +73 -0
  45. package/dist/ast/classes/ConditionNode.d.ts.map +1 -0
  46. package/dist/ast/classes/ConditionNode.js +101 -0
  47. package/dist/ast/classes/ErrorToken.d.ts +27 -0
  48. package/dist/ast/classes/ErrorToken.d.ts.map +1 -0
  49. package/dist/ast/classes/ErrorToken.js +47 -0
  50. package/dist/ast/classes/Expression.d.ts +13 -0
  51. package/dist/ast/classes/Expression.d.ts.map +1 -0
  52. package/dist/ast/classes/Expression.js +19 -0
  53. package/dist/ast/classes/ExpressionNode.d.ts +21 -0
  54. package/dist/ast/classes/ExpressionNode.d.ts.map +1 -0
  55. package/dist/ast/classes/ExpressionNode.js +57 -0
  56. package/dist/ast/classes/GroupNode.d.ts +64 -0
  57. package/dist/ast/classes/GroupNode.d.ts.map +1 -0
  58. package/dist/ast/classes/GroupNode.js +69 -0
  59. package/dist/ast/classes/Node.d.ts +22 -0
  60. package/dist/ast/classes/Node.d.ts.map +1 -0
  61. package/dist/ast/classes/Node.js +28 -0
  62. package/dist/ast/classes/Token.d.ts +27 -0
  63. package/dist/ast/classes/Token.d.ts.map +1 -0
  64. package/dist/ast/classes/Token.js +28 -0
  65. package/dist/ast/classes/ValidToken.d.ts +26 -0
  66. package/dist/ast/classes/ValidToken.d.ts.map +1 -0
  67. package/dist/ast/classes/ValidToken.js +49 -0
  68. package/dist/ast/classes/VariableNode.d.ts +33 -0
  69. package/dist/ast/classes/VariableNode.d.ts.map +1 -0
  70. package/dist/ast/classes/VariableNode.js +58 -0
  71. package/dist/ast/classes/index.d.ts +12 -0
  72. package/dist/ast/classes/index.d.ts.map +1 -0
  73. package/dist/ast/classes/index.js +24 -0
  74. package/dist/ast/handlers.d.ts +42 -0
  75. package/dist/ast/handlers.d.ts.map +1 -0
  76. package/dist/ast/handlers.js +150 -0
  77. package/dist/ast/index.d.ts +4 -0
  78. package/dist/ast/index.d.ts.map +1 -0
  79. package/dist/ast/index.js +8 -0
  80. package/dist/examples/advancedValueComparer.d.ts +3 -0
  81. package/dist/examples/advancedValueComparer.d.ts.map +1 -0
  82. package/dist/examples/advancedValueComparer.js +28 -0
  83. package/dist/examples/shortcutContextParser.d.ts +22 -0
  84. package/dist/examples/shortcutContextParser.d.ts.map +1 -0
  85. package/dist/examples/shortcutContextParser.js +126 -0
  86. package/dist/global.d.js +1 -0
  87. package/dist/grammar/ParserBase.d.ts +51 -0
  88. package/dist/grammar/ParserBase.d.ts.map +1 -0
  89. package/dist/grammar/ParserBase.js +516 -0
  90. package/dist/grammar/createTokens.d.ts +56 -0
  91. package/dist/grammar/createTokens.d.ts.map +1 -0
  92. package/dist/grammar/createTokens.js +843 -0
  93. package/dist/grammar/index.d.ts +3 -0
  94. package/dist/grammar/index.d.ts.map +1 -0
  95. package/dist/grammar/index.js +6 -0
  96. package/dist/helpers/errors.d.ts +9 -0
  97. package/dist/helpers/errors.d.ts.map +1 -0
  98. package/dist/helpers/errors.js +41 -0
  99. package/dist/helpers/general/applyBoolean.d.ts +3 -0
  100. package/dist/helpers/general/applyBoolean.d.ts.map +1 -0
  101. package/dist/helpers/general/applyBoolean.js +17 -0
  102. package/dist/helpers/general/applyPrefix.d.ts +4 -0
  103. package/dist/helpers/general/applyPrefix.d.ts.map +1 -0
  104. package/dist/helpers/general/applyPrefix.js +9 -0
  105. package/dist/helpers/general/defaultConditionNormalizer.d.ts +3 -0
  106. package/dist/helpers/general/defaultConditionNormalizer.d.ts.map +1 -0
  107. package/dist/helpers/general/defaultConditionNormalizer.js +6 -0
  108. package/dist/helpers/general/defaultKeyParser.d.ts +3 -0
  109. package/dist/helpers/general/defaultKeyParser.d.ts.map +1 -0
  110. package/dist/helpers/general/defaultKeyParser.js +8 -0
  111. package/dist/helpers/general/defaultPrefixApplier.d.ts +3 -0
  112. package/dist/helpers/general/defaultPrefixApplier.d.ts.map +1 -0
  113. package/dist/helpers/general/defaultPrefixApplier.js +6 -0
  114. package/dist/helpers/general/defaultValueComparer.d.ts +3 -0
  115. package/dist/helpers/general/defaultValueComparer.d.ts.map +1 -0
  116. package/dist/helpers/general/defaultValueComparer.js +6 -0
  117. package/dist/helpers/general/index.d.ts +7 -0
  118. package/dist/helpers/general/index.d.ts.map +1 -0
  119. package/dist/helpers/general/index.js +14 -0
  120. package/dist/helpers/index.d.ts +4 -0
  121. package/dist/helpers/index.d.ts.map +1 -0
  122. package/dist/helpers/index.js +8 -0
  123. package/dist/helpers/parser/assignParents.d.ts +4 -0
  124. package/dist/helpers/parser/assignParents.d.ts.map +1 -0
  125. package/dist/helpers/parser/assignParents.js +71 -0
  126. package/dist/helpers/parser/checkParserOpts.d.ts +3 -0
  127. package/dist/helpers/parser/checkParserOpts.d.ts.map +1 -0
  128. package/dist/helpers/parser/checkParserOpts.js +126 -0
  129. package/dist/helpers/parser/extractPosition.d.ts +9 -0
  130. package/dist/helpers/parser/extractPosition.d.ts.map +1 -0
  131. package/dist/helpers/parser/extractPosition.js +9 -0
  132. package/dist/helpers/parser/getUnclosedRightParenCount.d.ts +5 -0
  133. package/dist/helpers/parser/getUnclosedRightParenCount.d.ts.map +1 -0
  134. package/dist/helpers/parser/getUnclosedRightParenCount.js +20 -0
  135. package/dist/helpers/parser/index.d.ts +9 -0
  136. package/dist/helpers/parser/index.d.ts.map +1 -0
  137. package/dist/helpers/parser/index.js +18 -0
  138. package/dist/helpers/parser/parseParserOptions.d.ts +4 -0
  139. package/dist/helpers/parser/parseParserOptions.d.ts.map +1 -0
  140. package/dist/helpers/parser/parseParserOptions.js +45 -0
  141. package/dist/helpers/parser/seal.d.ts +8 -0
  142. package/dist/helpers/parser/seal.d.ts.map +1 -0
  143. package/dist/helpers/parser/seal.js +10 -0
  144. package/dist/helpers/parser/setParent.d.ts +6 -0
  145. package/dist/helpers/parser/setParent.d.ts.map +1 -0
  146. package/dist/helpers/parser/setParent.js +4 -0
  147. package/dist/helpers/parser/unescape.d.ts +3 -0
  148. package/dist/helpers/parser/unescape.d.ts.map +1 -0
  149. package/dist/helpers/parser/unescape.js +6 -0
  150. package/dist/index.d.ts +6 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +17 -0
  153. package/dist/methods/autocomplete.d.ts +18 -0
  154. package/dist/methods/autocomplete.d.ts.map +1 -0
  155. package/dist/methods/autocomplete.js +109 -0
  156. package/dist/methods/autoreplace.d.ts +13 -0
  157. package/dist/methods/autoreplace.d.ts.map +1 -0
  158. package/dist/methods/autoreplace.js +36 -0
  159. package/dist/methods/autosuggest.d.ts +28 -0
  160. package/dist/methods/autosuggest.d.ts.map +1 -0
  161. package/dist/methods/autosuggest.js +371 -0
  162. package/dist/methods/evaluate.d.ts +11 -0
  163. package/dist/methods/evaluate.d.ts.map +1 -0
  164. package/dist/methods/evaluate.js +30 -0
  165. package/dist/methods/getBestIndex.d.ts +19 -0
  166. package/dist/methods/getBestIndex.d.ts.map +1 -0
  167. package/dist/methods/getBestIndex.js +53 -0
  168. package/dist/methods/getIndexes.d.ts +17 -0
  169. package/dist/methods/getIndexes.d.ts.map +1 -0
  170. package/dist/methods/getIndexes.js +97 -0
  171. package/dist/methods/index.d.ts +9 -0
  172. package/dist/methods/index.d.ts.map +1 -0
  173. package/dist/methods/index.js +18 -0
  174. package/dist/methods/normalize.d.ts +12 -0
  175. package/dist/methods/normalize.d.ts.map +1 -0
  176. package/dist/methods/normalize.js +99 -0
  177. package/dist/methods/validate.d.ts +11 -0
  178. package/dist/methods/validate.d.ts.map +1 -0
  179. package/dist/methods/validate.js +111 -0
  180. package/dist/package.js +7 -0
  181. package/dist/package.json.js +193 -0
  182. package/dist/parser.d.ts +58 -0
  183. package/dist/parser.d.ts.map +1 -0
  184. package/dist/parser.js +136 -0
  185. package/dist/types/ast.d.ts +70 -0
  186. package/dist/types/ast.d.ts.map +1 -0
  187. package/dist/types/ast.js +29 -0
  188. package/dist/types/autocomplete.d.ts +143 -0
  189. package/dist/types/autocomplete.d.ts.map +1 -0
  190. package/dist/types/autocomplete.js +24 -0
  191. package/dist/types/errors.d.ts +34 -0
  192. package/dist/types/errors.d.ts.map +1 -0
  193. package/dist/types/errors.js +10 -0
  194. package/dist/types/index.d.ts +5 -0
  195. package/dist/types/index.d.ts.map +1 -0
  196. package/dist/types/index.js +9 -0
  197. package/dist/types/parser.d.ts +451 -0
  198. package/dist/types/parser.d.ts.map +1 -0
  199. package/dist/types/parser.js +1 -0
  200. package/dist/utils/extractTokens.d.ts +8 -0
  201. package/dist/utils/extractTokens.d.ts.map +1 -0
  202. package/dist/utils/extractTokens.js +50 -0
  203. package/dist/utils/getCursorInfo.d.ts +7 -0
  204. package/dist/utils/getCursorInfo.d.ts.map +1 -0
  205. package/dist/utils/getCursorInfo.js +86 -0
  206. package/dist/utils/getOppositeDelimiter.d.ts +6 -0
  207. package/dist/utils/getOppositeDelimiter.d.ts.map +1 -0
  208. package/dist/utils/getOppositeDelimiter.js +35 -0
  209. package/dist/utils/getSurroundingErrors.d.ts +25 -0
  210. package/dist/utils/getSurroundingErrors.d.ts.map +1 -0
  211. package/dist/utils/getSurroundingErrors.js +37 -0
  212. package/dist/utils/index.d.ts +10 -0
  213. package/dist/utils/index.d.ts.map +1 -0
  214. package/dist/utils/index.js +20 -0
  215. package/dist/utils/isBracket.d.ts +3 -0
  216. package/dist/utils/isBracket.d.ts.map +1 -0
  217. package/dist/utils/isBracket.js +7 -0
  218. package/dist/utils/isDelimiter.d.ts +6 -0
  219. package/dist/utils/isDelimiter.d.ts.map +1 -0
  220. package/dist/utils/isDelimiter.js +17 -0
  221. package/dist/utils/isParen.d.ts +3 -0
  222. package/dist/utils/isParen.d.ts.map +1 -0
  223. package/dist/utils/isParen.js +7 -0
  224. package/dist/utils/isQuote.d.ts +4 -0
  225. package/dist/utils/isQuote.d.ts.map +1 -0
  226. package/dist/utils/isQuote.js +7 -0
  227. package/dist/utils/prettyAst.d.ts +35 -0
  228. package/dist/utils/prettyAst.d.ts.map +1 -0
  229. package/dist/utils/prettyAst.js +112 -0
  230. package/package.json +152 -0
  231. package/src/ast/builders/array.ts +45 -0
  232. package/src/ast/builders/condition.ts +56 -0
  233. package/src/ast/builders/delim.ts +39 -0
  234. package/src/ast/builders/error.ts +22 -0
  235. package/src/ast/builders/expression.ts +66 -0
  236. package/src/ast/builders/group.ts +79 -0
  237. package/src/ast/builders/index.ts +13 -0
  238. package/src/ast/builders/isFullPos.ts +10 -0
  239. package/src/ast/builders/pos.ts +57 -0
  240. package/src/ast/builders/token.ts +46 -0
  241. package/src/ast/builders/type.ts +32 -0
  242. package/src/ast/builders/variable.ts +89 -0
  243. package/src/ast/classes/ArrayNode.ts +46 -0
  244. package/src/ast/classes/Condition.ts +22 -0
  245. package/src/ast/classes/ConditionNode.ts +141 -0
  246. package/src/ast/classes/ErrorToken.ts +49 -0
  247. package/src/ast/classes/Expression.ts +26 -0
  248. package/src/ast/classes/ExpressionNode.ts +62 -0
  249. package/src/ast/classes/GroupNode.ts +127 -0
  250. package/src/ast/classes/Node.ts +47 -0
  251. package/src/ast/classes/Token.ts +59 -0
  252. package/src/ast/classes/ValidToken.ts +56 -0
  253. package/src/ast/classes/VariableNode.ts +67 -0
  254. package/src/ast/classes/index.ts +13 -0
  255. package/src/ast/handlers.ts +190 -0
  256. package/src/ast/index.ts +5 -0
  257. package/src/examples/advancedValueComparer.ts +31 -0
  258. package/src/examples/shortcutContextParser.ts +140 -0
  259. package/src/global.d.ts +4 -0
  260. package/src/grammar/ParserBase.ts +715 -0
  261. package/src/grammar/createTokens.ts +512 -0
  262. package/src/grammar/index.ts +4 -0
  263. package/src/helpers/errors.ts +45 -0
  264. package/src/helpers/general/applyBoolean.ts +9 -0
  265. package/src/helpers/general/applyPrefix.ts +7 -0
  266. package/src/helpers/general/defaultConditionNormalizer.ts +9 -0
  267. package/src/helpers/general/defaultKeyParser.ts +8 -0
  268. package/src/helpers/general/defaultPrefixApplier.ts +7 -0
  269. package/src/helpers/general/defaultValueComparer.ts +7 -0
  270. package/src/helpers/general/index.ts +8 -0
  271. package/src/helpers/index.ts +5 -0
  272. package/src/helpers/parser/assignParents.ts +51 -0
  273. package/src/helpers/parser/checkParserOpts.ts +143 -0
  274. package/src/helpers/parser/extractPosition.ts +15 -0
  275. package/src/helpers/parser/getUnclosedRightParenCount.ts +22 -0
  276. package/src/helpers/parser/index.ts +10 -0
  277. package/src/helpers/parser/parseParserOptions.ts +54 -0
  278. package/src/helpers/parser/seal.ts +14 -0
  279. package/src/helpers/parser/setParent.ts +5 -0
  280. package/src/helpers/parser/unescape.ts +4 -0
  281. package/src/index.ts +7 -0
  282. package/src/methods/autocomplete.ts +128 -0
  283. package/src/methods/autoreplace.ts +46 -0
  284. package/src/methods/autosuggest.ts +543 -0
  285. package/src/methods/evaluate.ts +37 -0
  286. package/src/methods/getBestIndex.ts +53 -0
  287. package/src/methods/getIndexes.ts +99 -0
  288. package/src/methods/index.ts +10 -0
  289. package/src/methods/normalize.ts +138 -0
  290. package/src/methods/validate.ts +141 -0
  291. package/src/package.js +11 -0
  292. package/src/parser.ts +183 -0
  293. package/src/types/ast.ts +148 -0
  294. package/src/types/autocomplete.ts +152 -0
  295. package/src/types/errors.ts +40 -0
  296. package/src/types/index.ts +6 -0
  297. package/src/types/parser.ts +479 -0
  298. package/src/utils/extractTokens.ts +67 -0
  299. package/src/utils/getCursorInfo.ts +106 -0
  300. package/src/utils/getOppositeDelimiter.ts +36 -0
  301. package/src/utils/getSurroundingErrors.ts +57 -0
  302. package/src/utils/index.ts +11 -0
  303. package/src/utils/isBracket.ts +6 -0
  304. package/src/utils/isDelimiter.ts +18 -0
  305. package/src/utils/isParen.ts +6 -0
  306. package/src/utils/isQuote.ts +6 -0
  307. package/src/utils/prettyAst.ts +152 -0
@@ -0,0 +1,45 @@
1
+ import type { Mutable } from "@alanscodelog/utils"
2
+
3
+ import { token } from "./token.js"
4
+
5
+ import { AST_TYPE, type Position, TOKEN_TYPE } from "../../types/ast.js"
6
+ import { ArrayNode } from "../classes/ArrayNode.js"
7
+ import type { VariableNode } from "../classes/VariableNode.js"
8
+
9
+
10
+ export function array(
11
+ values: VariableNode[],
12
+ bracket: { left?: boolean, right?: boolean } = { right: true, left: true },
13
+ parenLeftPos?: Position,
14
+ parenRightPos?: Position
15
+ ): ArrayNode {
16
+ const node: Mutable<Partial<ArrayNode>> = {
17
+ type: AST_TYPE.ARRAY,
18
+ values,
19
+ }
20
+
21
+ node.bracket = {} as any
22
+
23
+ const start = values[0]?.start ?? parenLeftPos?.end
24
+ const end = values[values.length - 1]?.end ?? parenRightPos?.start ?? parenLeftPos?.end
25
+
26
+
27
+ parenLeftPos ??= (start !== undefined ? { start: start - 1, end: start } : undefined)
28
+ parenRightPos ??= (end !== undefined ? { start: end, end: end + 1 } : undefined)
29
+
30
+ // is always valid for now
31
+ node.bracket!.left = token(TOKEN_TYPE.BRACKETL, "[", parenLeftPos)
32
+
33
+ if (bracket?.right) {
34
+ node.bracket!.right = token(TOKEN_TYPE.BRACKETR, "]", parenRightPos)
35
+ } else {
36
+ if (parenRightPos) { parenRightPos.end = parenRightPos.start }
37
+ node.bracket!.right = token(TOKEN_TYPE.BRACKETR, undefined, parenRightPos)
38
+ }
39
+
40
+ node.start = node.bracket!.left?.start ?? start ?? node.bracket?.right.start
41
+ node.end = node.bracket?.right?.end ?? end ?? node.bracket!.left.end
42
+
43
+ const instance = new ArrayNode(node as any)
44
+ return instance
45
+ }
@@ -0,0 +1,56 @@
1
+ import { pos } from "./pos.js"
2
+
3
+ import { type AnyToken, type Position, type TOKEN_TYPE } from "../../types/ast.js"
4
+ import type { ArrayNode } from "../classes/ArrayNode.js"
5
+ import { ConditionNode } from "../classes/ConditionNode.js"
6
+ import type { ErrorToken } from "../classes/ErrorToken.js"
7
+ import type { GroupNode } from "../classes/GroupNode.js"
8
+ import type { ValidToken } from "../classes/ValidToken.js"
9
+ import type { VariableNode } from "../classes/VariableNode.js"
10
+
11
+ /**
12
+ * Creates a @see ConditionNode
13
+ *
14
+ * @param variable An existing @see VariableNode
15
+ *
16
+ * @param not Defaults to plain true condition. To negate it you must pass an existing "not" operator @see ValidToken which will be set as the node's operator and set the node's value to false.
17
+ *
18
+ * @param property Set the property for a property operator. A property operator must be passed if this is passed.
19
+ * @param propertyOperator Set the operator for a property condition. A property must have been passed. The property operator must be a valid token. There is no case where it would not be. If using an operator that is the same as a separator, if used as an operator, should be set as an operator.
20
+ * @param sep Pass separator tokens for expanded property conditions.
21
+ */
22
+ // todo doc property operator
23
+ export function condition(
24
+ value:
25
+ | VariableNode
26
+ | GroupNode
27
+ | ArrayNode
28
+ | ErrorToken<TOKEN_TYPE.VALUE>,
29
+ not: true | ValidToken<TOKEN_TYPE.NOT> = true,
30
+ property?: VariableNode | ErrorToken<TOKEN_TYPE.VALUE>,
31
+ propertyOperator?: AnyToken<TOKEN_TYPE.OP_CUSTOM | TOKEN_TYPE.VALUE>,
32
+ { right, left }: Partial<Record<"right" | "left", ValidToken<TOKEN_TYPE.OP_EXPANDED_SEP>>> = { }
33
+ ): ConditionNode {
34
+ const position = pos(value satisfies Position)
35
+ const notStart = not === true ? undefined : not.start
36
+ position.start = notStart ?? property?.start ?? propertyOperator?.start ?? position.start
37
+
38
+ const node: Partial<ConstructorParameters<typeof ConditionNode>[0]> = {
39
+ property,
40
+ value,
41
+ propertyOperator,
42
+ ...position,
43
+ }
44
+
45
+ if (not !== true) {
46
+ node.operator = not
47
+ }
48
+ if (right || left) {
49
+ node.sep = {}
50
+ if (right) node.sep.right = right
51
+ if (left) node.sep.left = left
52
+ }
53
+ const instance = new ConditionNode(node as any)
54
+ return instance
55
+ }
56
+
@@ -0,0 +1,39 @@
1
+ import { type } from "./type.js"
2
+
3
+ import { type ExtractTokenType, TOKEN_TYPE } from "../../types/ast.js"
4
+
5
+ /**
6
+ * Faster way, more intuitive way to generate the options for matching delimiters (e.g. quotes and parens) for functions like @see variable and @see group .
7
+ */
8
+
9
+ export function delim<
10
+ TLeft extends boolean | string,
11
+ TRight extends boolean | string,
12
+ TType extends TLeft extends string
13
+ ? ExtractTokenType<TLeft>
14
+ : TRight extends string
15
+ ? ExtractTokenType<TRight>
16
+ : undefined,
17
+ >(
18
+ left: TLeft = false as TLeft,
19
+ right: TRight = false as TRight,
20
+ ):
21
+ {
22
+ left: TLeft extends string ? true : TLeft
23
+ right: TRight extends string ? true : TRight
24
+ } & TType extends undefined ? {} : { type: TType } {
25
+ let quoteType
26
+ if (typeof left === "string") quoteType = type(left)
27
+ else if (typeof right === "string") quoteType = type(right)
28
+
29
+ const opts: any = {
30
+ left: left === true || (typeof left === "string" && left !== undefined),
31
+ right: right === true || (typeof right === "string" && right !== undefined),
32
+ }
33
+ if (quoteType !== undefined &&
34
+ ![TOKEN_TYPE.PARENL, TOKEN_TYPE.PARENR].includes(quoteType)
35
+ ) {
36
+ opts.type = quoteType
37
+ }
38
+ return opts
39
+ }
@@ -0,0 +1,22 @@
1
+ import { type } from "./type.js"
2
+
3
+ import { TOKEN_TYPE } from "../../types/ast.js"
4
+ import { ErrorToken } from "../classes/ErrorToken.js"
5
+
6
+
7
+ /**
8
+ * Creates an error token.
9
+ *
10
+ * @param expected Can be passed an array of @see ValidToken_TYPE or strings, in which case it will use @see type internally. So instead of `[TOKEN_TYPE.VALUE]` we can do `[""]` and instead of `[TOKEN_TYPE.PARENR]` we can do `[")"]`.
11
+ */
12
+ export function error<T extends TOKEN_TYPE>(pos: number, expected: T[]): ErrorToken<T>
13
+ export function error<T extends TOKEN_TYPE>(pos: number, expected_: T[]): ErrorToken<T> {
14
+ const expected = expected_.map(item => {
15
+ if (TOKEN_TYPE[item as keyof typeof TOKEN_TYPE] === undefined) {
16
+ return type(item)
17
+ } else {
18
+ return item
19
+ }
20
+ }) as T []
21
+ return new ErrorToken({ expected, start: pos, end: pos })
22
+ }
@@ -0,0 +1,66 @@
1
+ import { pos } from "./pos.js"
2
+ import { token } from "./token.js"
3
+
4
+ import { type AnyToken, type Position, TOKEN_TYPE, type TokenBooleanTypes } from "../../types/ast.js"
5
+ import type { ConditionNode } from "../classes/ConditionNode.js"
6
+ import type { ErrorToken } from "../classes/ErrorToken.js"
7
+ import { ExpressionNode } from "../classes/ExpressionNode.js"
8
+ import type { GroupNode } from "../classes/GroupNode.js"
9
+
10
+
11
+ /**
12
+ * Creates an @see ExpressionNode, can be passed nothing for any of the tokens to automatically create error tokens.
13
+ *
14
+ * Also automatically sets the correct start/end positions from valid tokens (e.g. for start, searching left to right for a valid token and vice versa) assuming at least one is defined.
15
+ */
16
+ export function expression(
17
+ left:
18
+ ConditionNode |
19
+ ExpressionNode |
20
+ GroupNode |
21
+ ErrorToken<TOKEN_TYPE.VALUE> |
22
+ undefined,
23
+ operator:
24
+ AnyToken<TokenBooleanTypes> |
25
+ undefined,
26
+ right:
27
+ ConditionNode |
28
+ ExpressionNode |
29
+ GroupNode |
30
+ ErrorToken<TOKEN_TYPE.VALUE> |
31
+ undefined
32
+ ): ExpressionNode {
33
+ const start =
34
+ left?.start ??
35
+ operator?.start ??
36
+ right?.start
37
+ const end =
38
+ right?.end ??
39
+ operator?.end ??
40
+ left?.end
41
+
42
+
43
+ const position = pos({ start, end } as Position)
44
+
45
+ if (left === undefined) {
46
+ left = token(TOKEN_TYPE.VALUE, undefined, { start: position.start })
47
+ }
48
+ let op!: ExpressionNode["operator"]
49
+ if (operator === undefined) {
50
+ operator = token([TOKEN_TYPE.AND, TOKEN_TYPE.OR], undefined, { start: left.end })
51
+ } else op = operator
52
+
53
+ if (right === undefined) {
54
+ right = token(TOKEN_TYPE.VALUE, undefined, { start: op.end })
55
+ }
56
+
57
+ const node: ConstructorParameters<typeof ExpressionNode>[0] = {
58
+ left,
59
+ operator: op,
60
+ right,
61
+ ...position,
62
+ }
63
+
64
+ const instance = new ExpressionNode(node)
65
+ return instance
66
+ }
@@ -0,0 +1,79 @@
1
+ import { token } from "./token.js"
2
+
3
+ import { type Position, TOKEN_TYPE } from "../../types/ast.js"
4
+ import type { ConditionNode } from "../classes/ConditionNode.js"
5
+ import type { ErrorToken } from "../classes/ErrorToken.js"
6
+ import type { ExpressionNode } from "../classes/ExpressionNode.js"
7
+ import { GroupNode } from "../classes/GroupNode.js"
8
+ import type { ValidToken } from "../classes/ValidToken.js"
9
+
10
+ /**
11
+ * Creates a group.
12
+ *
13
+ * Automatically creates error tokens if missing condition or parens (not prefix because it is optional). Will look at the position of prefix if available.
14
+ *
15
+ * @param paren Use to add parens to group, usually by using @see delim . If either `right` or `left` are false or undefined, error tokens will be created. Unlike @see variable, if undefined is passed for parens, parens are created by default.
16
+ *
17
+ * The positions of the parens can be adjusted with the last two parameters by passing positions.
18
+ */
19
+
20
+ export function group(
21
+ prefix:
22
+ | ConditionNode
23
+ | ValidToken<TOKEN_TYPE.NOT>
24
+ | undefined,
25
+
26
+ expression:
27
+ | ConditionNode
28
+ | ExpressionNode
29
+ | GroupNode
30
+ | ErrorToken<TOKEN_TYPE.VALUE>
31
+ | undefined,
32
+
33
+ paren: { left?: boolean, right?: boolean } = { right: true, left: true },
34
+ parenLeftPos?: Position,
35
+ parenRightPos?: Position
36
+ ): GroupNode {
37
+ if (expression === undefined) {
38
+ expression = token(TOKEN_TYPE.VALUE, undefined, prefix?.end !== undefined ? { start: prefix.end } : undefined)
39
+ }
40
+
41
+ const node: Partial<ConstructorParameters<typeof GroupNode>[0]> = {
42
+ expression,
43
+ }
44
+ if (prefix) {
45
+ node.prefix = prefix
46
+ const locToRight = node.paren?.left?.start ?? node.expression?.start ?? node.paren?.right.start
47
+ if (prefix.start === undefined && locToRight !== undefined) {
48
+ throw new Error("group builder: missing prefix location when passed expression with location")
49
+ }
50
+ }
51
+
52
+ node.paren = {} as any
53
+
54
+ const start = expression.start
55
+ const end = expression.end
56
+
57
+ parenLeftPos ??= (start !== undefined ? { start: start - 1, end: start } : undefined)
58
+ parenRightPos ??= (end !== undefined ? { start: end, end: end + 1 } : undefined)
59
+
60
+ if (paren?.left) {
61
+ node.paren!.left = token(TOKEN_TYPE.PARENL, "(", parenLeftPos)
62
+ } else {
63
+ if (parenLeftPos) {parenLeftPos.start = parenLeftPos.end}
64
+ node.paren!.left = token(TOKEN_TYPE.PARENL, undefined, parenLeftPos)
65
+ }
66
+
67
+ if (paren?.right) {
68
+ node.paren!.right = token(TOKEN_TYPE.PARENR, ")", parenRightPos)
69
+ } else {
70
+ if (parenRightPos) {parenRightPos.end = parenRightPos.start}
71
+ node.paren!.right = token(TOKEN_TYPE.PARENR, undefined, parenRightPos)
72
+ }
73
+
74
+ node.start = node.prefix?.start ?? node.paren?.left?.start ?? node.expression?.start ?? node.paren?.right.start
75
+ node.end = node.paren?.right?.end ?? node.expression?.end ?? node.paren?.left.end ?? node.prefix?.end
76
+
77
+ const instance = new GroupNode(node as any)
78
+ return instance
79
+ }
@@ -0,0 +1,13 @@
1
+ /* Autogenerated Index */
2
+
3
+ export { array } from "./array.js"
4
+ export { condition } from "./condition.js"
5
+ export { delim } from "./delim.js"
6
+ export { error } from "./error.js"
7
+ export { expression } from "./expression.js"
8
+ export { group } from "./group.js"
9
+ export { isFullPos } from "./isFullPos.js"
10
+ export { pos } from "./pos.js"
11
+ export { token } from "./token.js"
12
+ export { type } from "./type.js"
13
+ export { variable } from "./variable.js"
@@ -0,0 +1,10 @@
1
+ import type { Position } from "../../types/ast.js"
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export function isFullPos(position?: Partial<Position> | any): position is Position {
7
+ return typeof position === "object" &&
8
+ position.start !== undefined &&
9
+ position.end !== undefined
10
+ }
@@ -0,0 +1,57 @@
1
+ import { isFullPos } from "./isFullPos.js"
2
+
3
+ import type { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE } from "../../types/ast.js"
4
+ import type { Node } from "../classes/Node.js"
5
+
6
+ /**
7
+ * Can either:
8
+ *
9
+ * - Create a position from two numbers.
10
+ * - Extract just a position from anything with a (full) position.
11
+ * - From a partial position if `{fill:true}`.
12
+ */
13
+ export function pos<TItem extends Position | Partial<Position> | EmptyObj>(
14
+ item: TItem,
15
+ opts: { fill: true }
16
+ ): TItem extends { start: number } | { end: number }
17
+ ? Position
18
+ : EmptyObj
19
+ export function pos<TItem extends Position | Partial<Position> | EmptyObj>(
20
+ item: TItem,
21
+ opts?: undefined | { fill: false }
22
+ ):
23
+ // not sure why this needs the AnyToken check, prob something to do with using classes
24
+ TItem extends Position
25
+ ? Position
26
+ : TItem extends AnyToken<TOKEN_TYPE> | Position | EmptyObj
27
+ ? Position | EmptyObj
28
+ : TItem extends Node<AST_TYPE> | Position | EmptyObj
29
+ ? Position | EmptyObj
30
+ : EmptyObj
31
+ export function pos(start: number, end: number): Position
32
+ export function pos(
33
+ start: number | Position | Partial<Position> | EmptyObj | undefined,
34
+ end?: number | { fill: boolean }
35
+ ): Position | EmptyObj {
36
+ if (typeof start === "number") {
37
+ return { start, end: end as number }
38
+ } else {
39
+ const item = start
40
+ if (item === undefined) return {} as any
41
+ const fill = typeof end === "object" ? end.fill : false
42
+
43
+ if (isFullPos(item)) {
44
+ return { start: item.start, end: item.end }
45
+ } else {
46
+ if (fill) {
47
+ /* eslint-disable @typescript-eslint/no-shadow */
48
+ let start = item.start
49
+ let end = item.end
50
+ if (start !== undefined && end === undefined) end = start
51
+ if (end !== undefined && start === undefined) start = end
52
+ return { start: start!, end: end! }
53
+ }
54
+ return {} as any
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,46 @@
1
+ import { isArray } from "@alanscodelog/utils"
2
+
3
+ import { pos } from "./pos.js"
4
+
5
+ import type { AnyToken, EmptyObj, Position, TOKEN_TYPE } from "../../types/ast.js"
6
+ import { ErrorToken } from "../classes/ErrorToken.js"
7
+ import { ValidToken } from "../classes/ValidToken.js"
8
+
9
+
10
+ /**
11
+ * Creates a @see ValidToken or of the given type with the given value. If no value is given, creates an @see ErrorToken instead.
12
+ *
13
+ * Can be passed multiple types when creating an error token to set the expected field.
14
+ *
15
+ * If the token is an error token, just `start` or `end` can be passed, and the other position will be filled to the same value.
16
+ */
17
+
18
+ export function token<
19
+ TValue extends string | undefined,
20
+ TType extends TOKEN_TYPE = TOKEN_TYPE,
21
+ >(
22
+ type: TValue extends undefined ? TType | TType[] : TType,
23
+ value: TValue,
24
+ position: Position | Partial<Position> | EmptyObj = {}
25
+ ): TValue extends undefined
26
+ ? ErrorToken<TType>
27
+ : ValidToken<TType> {
28
+ position = pos(position, { fill: true })
29
+ // eslint-disable-next-line @typescript-eslint/no-shadow
30
+ let token: AnyToken<TType>
31
+ if (value !== undefined) {
32
+ token = new ValidToken<TType>({
33
+ type: type as TType,
34
+ value,
35
+ start: position.start!,
36
+ end: position.end!,
37
+ })
38
+ } else {
39
+ token = new ErrorToken<TType>({
40
+ expected: (isArray(type) ? type : [type]) as TType[],
41
+ start: position.start!,
42
+ end: position.end!,
43
+ })
44
+ }
45
+ return token as any
46
+ }
@@ -0,0 +1,32 @@
1
+ import { type ExtractTokenType, TOKEN_TYPE } from "../../types/ast.js"
2
+ /**
3
+ * Given a the string value of an operator or single delimiter token, returns the corresponding @see ValidToken_TYPE .
4
+ */
5
+ export function type<T extends string>(
6
+ operatorSymbol: T
7
+ ): ExtractTokenType<T> {
8
+ switch (operatorSymbol) {
9
+ case "`": return TOKEN_TYPE.BACKTICK as any
10
+ case `'`: return TOKEN_TYPE.SINGLEQUOTE as any
11
+ case `"`: return TOKEN_TYPE.DOUBLEQUOTE as any
12
+ case `(`: return TOKEN_TYPE.PARENL as any
13
+ case `)`: return TOKEN_TYPE.PARENR as any
14
+ case `[`: return TOKEN_TYPE.BRACKETL as any
15
+ case `]`: return TOKEN_TYPE.BRACKETR as any
16
+ case `/`: return TOKEN_TYPE.REGEX as any
17
+ case `and`:
18
+ case `&&`:
19
+ case `&`:
20
+ return TOKEN_TYPE.AND as any
21
+ case `or`:
22
+ case `||`:
23
+ case `|`:
24
+ return TOKEN_TYPE.OR as any
25
+ case `not`:
26
+ case `!`:
27
+ return TOKEN_TYPE.NOT as any
28
+ default:
29
+ return TOKEN_TYPE.VALUE as any
30
+ }
31
+ }
32
+
@@ -0,0 +1,89 @@
1
+ import { pos } from "./pos.js"
2
+ import { token } from "./token.js"
3
+
4
+ import { type AnyToken, type EmptyObj, type Position, TOKEN_TYPE, type TokenQuoteTypes } from "../../types/ast.js"
5
+ import type { ValidToken } from "../classes/ValidToken.js"
6
+ import { VariableNode } from "../classes/VariableNode.js"
7
+
8
+
9
+ /**
10
+ * Creates an @see VariableNode .
11
+ *
12
+ * @param quote Use to add quotes to the variable, usually by using @see delim . If false or undefined, no quotes are added. Otherwise at least `type` must be passed. If one side is defined but not the other, error tokens will be created with the given type.
13
+ *
14
+ * @param position Refers to position of the value (in case it needs to be created) not the node. Quote positions are automatically calculated from this if used. If value is already a token, there's no need to pass a position, it can be extracted from the token.
15
+ */
16
+
17
+ export function variable(
18
+ prefix: ValidToken<TOKEN_TYPE.VALUE> | undefined,
19
+ value: string | AnyToken<TOKEN_TYPE.VALUE>,
20
+ quote?: { type: TokenQuoteTypes, left?: boolean, right?: boolean, flags?: string },
21
+ position?: Position | EmptyObj
22
+ ): VariableNode {
23
+ if (typeof value === "string") {
24
+ value = token(TOKEN_TYPE.VALUE, value, position)
25
+ }
26
+
27
+ position = pos(value)
28
+
29
+ const node: Partial<ConstructorParameters<typeof VariableNode>[0]> = {
30
+ value,
31
+ prefix,
32
+ }
33
+
34
+ if (quote) {
35
+ node.quote = {} as any
36
+
37
+ const quoteLeftPos = position?.start !== undefined
38
+ ? pos({ start: position.start }, { fill: true })
39
+ : undefined
40
+
41
+ if (quote.left) {
42
+ if (quoteLeftPos) quoteLeftPos.start -= 1
43
+ node.quote!.left = token(quote.type, quoteFromType(quote.type), quoteLeftPos)
44
+ } else {
45
+ node.quote!.left = token(quote.type, undefined, quoteLeftPos)
46
+ }
47
+
48
+ const quoteRightPos = position?.end !== undefined
49
+ ? pos({ end: position.end }, { fill: true })
50
+ : undefined
51
+
52
+ if (quote.right) {
53
+ if (quoteRightPos) quoteRightPos.end += 1
54
+ node.quote!.right = token(quote.type, quoteFromType(quote.type), quoteRightPos)
55
+ } else {
56
+ node.quote!.right = token(quote.type, undefined, quoteRightPos)
57
+ }
58
+ if (quote.flags) {
59
+ const start = node.quote!.right.end // is always defined if there are flags
60
+ node.quote!.flags = token(TOKEN_TYPE.VALUE, quote.flags, {
61
+ start, end: start + quote.flags?.length,
62
+ })
63
+ }
64
+ }
65
+
66
+ node.start =
67
+ node.prefix?.start ??
68
+ node.quote?.left.start ??
69
+ node.value?.start ??
70
+ node.quote?.right.start
71
+ node.end =
72
+ node.quote?.flags?.end ??
73
+ node.quote?.right.end ??
74
+ node.value?.end ??
75
+ node.quote?.left.end
76
+
77
+ const instance = new VariableNode(node as any)
78
+ return instance
79
+ }
80
+
81
+ function quoteFromType(type: TokenQuoteTypes | undefined): string {
82
+ switch (type) {
83
+ case TOKEN_TYPE.BACKTICK: return "`"
84
+ case TOKEN_TYPE.DOUBLEQUOTE: return "\""
85
+ case TOKEN_TYPE.SINGLEQUOTE: return "'"
86
+ case TOKEN_TYPE.REGEX: return "/"
87
+ case undefined: return ""
88
+ }
89
+ }
@@ -0,0 +1,46 @@
1
+ import type { ConditionNode } from "./ConditionNode.js"
2
+ import { Node } from "./Node.js"
3
+ import { ValidToken } from "./ValidToken.js"
4
+ import type { VariableNode } from "./VariableNode.js"
5
+
6
+ import { AST_TYPE, type NodeDelimiters, type TOKEN_TYPE } from "../../types/ast.js"
7
+
8
+
9
+ export class ArrayNode<
10
+ TValid extends boolean = boolean,
11
+ > extends Node<AST_TYPE.ARRAY> {
12
+ readonly values: VariableNode[]
13
+
14
+ readonly bracket: NodeDelimiters<TOKEN_TYPE.BRACKETL, TOKEN_TYPE.BRACKETR>
15
+
16
+ #parent: any
17
+
18
+ #setParent: boolean = false
19
+
20
+ get parent(): ConditionNode | undefined {
21
+ return this.#parent
22
+ }
23
+
24
+ set parent(value: ConditionNode | undefined) {
25
+ if (this.#setParent) { throw new Error("parent property is readonly") }
26
+ this.#parent = value
27
+ this.#setParent = true
28
+ }
29
+
30
+ constructor({ values, bracket, start, end }: {
31
+ values: ArrayNode<TValid>["values"]
32
+ bracket: ArrayNode<TValid>["bracket"]
33
+ start: number
34
+ end: number
35
+ }) {
36
+ super(AST_TYPE.ARRAY, start, end)
37
+ this.values = values
38
+ this.bracket = bracket
39
+ // @ts-expect-error ignore readonly
40
+ this.valid = (
41
+ this.values.every(val => val.valid) &&
42
+ this.bracket.left instanceof ValidToken &&
43
+ this.bracket.right instanceof ValidToken
44
+ ) as TValid
45
+ }
46
+ }
@@ -0,0 +1,22 @@
1
+ export class Condition<TOp extends string = string, TValue = any> {
2
+ readonly value: TValue
3
+
4
+ readonly operator?: TOp
5
+
6
+ readonly property: string[]
7
+
8
+ readonly negate: boolean
9
+
10
+ constructor({ property, operator, value, negate }: {
11
+ property: Condition<TOp, TValue>["property"]
12
+ operator: Condition<TOp, TValue>["operator"]
13
+ value: Condition<TOp, TValue>["value"]
14
+ negate: Condition<TOp, TValue>["negate"]
15
+ }) {
16
+ this.value = value
17
+ this.operator = operator
18
+ this.property = property
19
+ this.negate = negate
20
+ }
21
+ }
22
+