flowquery 1.0.16 → 1.0.18

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 (319) hide show
  1. package/.github/workflows/python-publish.yml +96 -0
  2. package/dist/compute/runner.d.ts +3 -2
  3. package/dist/compute/runner.d.ts.map +1 -1
  4. package/dist/compute/runner.js +7 -7
  5. package/dist/compute/runner.js.map +1 -1
  6. package/dist/flowquery.min.js +1 -1
  7. package/dist/graph/data.d.ts +31 -0
  8. package/dist/graph/data.d.ts.map +1 -0
  9. package/dist/graph/data.js +110 -0
  10. package/dist/graph/data.js.map +1 -0
  11. package/dist/graph/database.d.ts +20 -0
  12. package/dist/graph/database.d.ts.map +1 -0
  13. package/dist/graph/database.js +77 -0
  14. package/dist/graph/database.js.map +1 -0
  15. package/dist/graph/hops.d.ts +11 -0
  16. package/dist/graph/hops.d.ts.map +1 -0
  17. package/dist/graph/hops.js +25 -0
  18. package/dist/graph/hops.js.map +1 -0
  19. package/dist/graph/node.d.ts +35 -0
  20. package/dist/graph/node.d.ts.map +1 -0
  21. package/dist/graph/node.js +113 -0
  22. package/dist/graph/node.js.map +1 -0
  23. package/dist/graph/node_data.d.ts +11 -0
  24. package/dist/graph/node_data.d.ts.map +1 -0
  25. package/dist/graph/node_data.js +20 -0
  26. package/dist/graph/node_data.js.map +1 -0
  27. package/dist/graph/node_reference.d.ts +10 -0
  28. package/dist/graph/node_reference.d.ts.map +1 -0
  29. package/dist/graph/node_reference.js +52 -0
  30. package/dist/graph/node_reference.js.map +1 -0
  31. package/dist/graph/pattern.d.ts +18 -0
  32. package/dist/graph/pattern.d.ts.map +1 -0
  33. package/dist/graph/pattern.js +114 -0
  34. package/dist/graph/pattern.js.map +1 -0
  35. package/dist/graph/pattern_expression.d.ts +15 -0
  36. package/dist/graph/pattern_expression.d.ts.map +1 -0
  37. package/dist/graph/pattern_expression.js +69 -0
  38. package/dist/graph/pattern_expression.js.map +1 -0
  39. package/dist/graph/patterns.d.ts +11 -0
  40. package/dist/graph/patterns.d.ts.map +1 -0
  41. package/dist/graph/patterns.js +49 -0
  42. package/dist/graph/patterns.js.map +1 -0
  43. package/dist/graph/physical_node.d.ts +10 -0
  44. package/dist/graph/physical_node.d.ts.map +1 -0
  45. package/dist/graph/physical_node.js +40 -0
  46. package/dist/graph/physical_node.js.map +1 -0
  47. package/dist/graph/physical_relationship.d.ts +10 -0
  48. package/dist/graph/physical_relationship.d.ts.map +1 -0
  49. package/dist/graph/physical_relationship.js +40 -0
  50. package/dist/graph/physical_relationship.js.map +1 -0
  51. package/dist/graph/relationship.d.ts +40 -0
  52. package/dist/graph/relationship.d.ts.map +1 -0
  53. package/dist/graph/relationship.js +124 -0
  54. package/dist/graph/relationship.js.map +1 -0
  55. package/dist/graph/relationship_data.d.ts +12 -0
  56. package/dist/graph/relationship_data.d.ts.map +1 -0
  57. package/dist/graph/relationship_data.js +40 -0
  58. package/dist/graph/relationship_data.js.map +1 -0
  59. package/dist/graph/relationship_match_collector.d.ts +19 -0
  60. package/dist/graph/relationship_match_collector.d.ts.map +1 -0
  61. package/dist/graph/relationship_match_collector.js +55 -0
  62. package/dist/graph/relationship_match_collector.js.map +1 -0
  63. package/dist/graph/relationship_reference.d.ts +8 -0
  64. package/dist/graph/relationship_reference.d.ts.map +1 -0
  65. package/dist/graph/relationship_reference.js +37 -0
  66. package/dist/graph/relationship_reference.js.map +1 -0
  67. package/dist/parsing/base_parser.d.ts +1 -0
  68. package/dist/parsing/base_parser.d.ts.map +1 -1
  69. package/dist/parsing/base_parser.js +4 -1
  70. package/dist/parsing/base_parser.js.map +1 -1
  71. package/dist/parsing/context.d.ts +2 -2
  72. package/dist/parsing/context.js +5 -5
  73. package/dist/parsing/expressions/boolean.d.ts +8 -0
  74. package/dist/parsing/expressions/boolean.d.ts.map +1 -0
  75. package/dist/parsing/expressions/boolean.js +26 -0
  76. package/dist/parsing/expressions/boolean.js.map +1 -0
  77. package/dist/parsing/expressions/expression.d.ts +4 -1
  78. package/dist/parsing/expressions/expression.d.ts.map +1 -1
  79. package/dist/parsing/expressions/expression.js +15 -8
  80. package/dist/parsing/expressions/expression.js.map +1 -1
  81. package/dist/parsing/expressions/operator.d.ts +1 -1
  82. package/dist/parsing/expressions/operator.d.ts.map +1 -1
  83. package/dist/parsing/expressions/operator.js.map +1 -1
  84. package/dist/parsing/functions/function_factory.d.ts +13 -13
  85. package/dist/parsing/functions/function_factory.d.ts.map +1 -1
  86. package/dist/parsing/functions/function_factory.js +20 -18
  87. package/dist/parsing/functions/function_factory.js.map +1 -1
  88. package/dist/parsing/operations/create_node.d.ts +14 -0
  89. package/dist/parsing/operations/create_node.d.ts.map +1 -0
  90. package/dist/parsing/operations/create_node.js +51 -0
  91. package/dist/parsing/operations/create_node.js.map +1 -0
  92. package/dist/parsing/operations/create_relationship.d.ts +14 -0
  93. package/dist/parsing/operations/create_relationship.d.ts.map +1 -0
  94. package/dist/parsing/operations/create_relationship.js +51 -0
  95. package/dist/parsing/operations/create_relationship.js.map +1 -0
  96. package/dist/parsing/operations/match.d.ts +15 -0
  97. package/dist/parsing/operations/match.d.ts.map +1 -0
  98. package/dist/parsing/operations/match.js +45 -0
  99. package/dist/parsing/operations/match.js.map +1 -0
  100. package/dist/parsing/operations/operation.d.ts +1 -0
  101. package/dist/parsing/operations/operation.d.ts.map +1 -1
  102. package/dist/parsing/operations/operation.js +6 -0
  103. package/dist/parsing/operations/operation.js.map +1 -1
  104. package/dist/parsing/operations/return.d.ts +1 -0
  105. package/dist/parsing/operations/return.d.ts.map +1 -1
  106. package/dist/parsing/operations/return.js +7 -1
  107. package/dist/parsing/operations/return.js.map +1 -1
  108. package/dist/parsing/operations/where.d.ts +1 -1
  109. package/dist/parsing/operations/where.d.ts.map +1 -1
  110. package/dist/parsing/operations/where.js +4 -0
  111. package/dist/parsing/operations/where.js.map +1 -1
  112. package/dist/parsing/parser.d.ts +10 -0
  113. package/dist/parsing/parser.d.ts.map +1 -1
  114. package/dist/parsing/parser.js +345 -5
  115. package/dist/parsing/parser.js.map +1 -1
  116. package/dist/parsing/token_to_node.d.ts.map +1 -1
  117. package/dist/parsing/token_to_node.js +7 -0
  118. package/dist/parsing/token_to_node.js.map +1 -1
  119. package/dist/tokenization/keyword.d.ts +1 -0
  120. package/dist/tokenization/keyword.d.ts.map +1 -1
  121. package/dist/tokenization/keyword.js +1 -0
  122. package/dist/tokenization/keyword.js.map +1 -1
  123. package/dist/tokenization/token.d.ts +4 -0
  124. package/dist/tokenization/token.d.ts.map +1 -1
  125. package/dist/tokenization/token.js +14 -1
  126. package/dist/tokenization/token.js.map +1 -1
  127. package/dist/tokenization/token_type.d.ts +1 -0
  128. package/dist/tokenization/token_type.d.ts.map +1 -1
  129. package/dist/tokenization/token_type.js +1 -0
  130. package/dist/tokenization/token_type.js.map +1 -1
  131. package/dist/tokenization/tokenizer.d.ts +2 -1
  132. package/dist/tokenization/tokenizer.d.ts.map +1 -1
  133. package/dist/tokenization/tokenizer.js +25 -12
  134. package/dist/tokenization/tokenizer.js.map +1 -1
  135. package/docs/flowquery.min.js +1 -1
  136. package/flowquery-py/CONTRIBUTING.md +127 -0
  137. package/flowquery-py/README.md +67 -0
  138. package/flowquery-py/pyproject.toml +75 -0
  139. package/flowquery-py/setup_env.ps1 +92 -0
  140. package/flowquery-py/setup_env.sh +87 -0
  141. package/flowquery-py/src/__init__.py +34 -0
  142. package/flowquery-py/src/__main__.py +10 -0
  143. package/flowquery-py/src/compute/__init__.py +5 -0
  144. package/flowquery-py/src/compute/runner.py +60 -0
  145. package/flowquery-py/src/extensibility.py +52 -0
  146. package/flowquery-py/src/graph/__init__.py +31 -0
  147. package/flowquery-py/src/graph/data.py +118 -0
  148. package/flowquery-py/src/graph/database.py +82 -0
  149. package/flowquery-py/src/graph/hops.py +43 -0
  150. package/flowquery-py/src/graph/node.py +112 -0
  151. package/flowquery-py/src/graph/node_data.py +26 -0
  152. package/flowquery-py/src/graph/node_reference.py +49 -0
  153. package/flowquery-py/src/graph/pattern.py +125 -0
  154. package/flowquery-py/src/graph/pattern_expression.py +65 -0
  155. package/flowquery-py/src/graph/patterns.py +42 -0
  156. package/flowquery-py/src/graph/physical_node.py +40 -0
  157. package/flowquery-py/src/graph/physical_relationship.py +36 -0
  158. package/flowquery-py/src/graph/relationship.py +135 -0
  159. package/flowquery-py/src/graph/relationship_data.py +33 -0
  160. package/flowquery-py/src/graph/relationship_match_collector.py +77 -0
  161. package/flowquery-py/src/graph/relationship_reference.py +21 -0
  162. package/flowquery-py/src/io/__init__.py +5 -0
  163. package/flowquery-py/src/io/command_line.py +109 -0
  164. package/flowquery-py/src/parsing/__init__.py +17 -0
  165. package/flowquery-py/src/parsing/alias.py +20 -0
  166. package/flowquery-py/src/parsing/alias_option.py +11 -0
  167. package/flowquery-py/src/parsing/ast_node.py +146 -0
  168. package/flowquery-py/src/parsing/base_parser.py +84 -0
  169. package/flowquery-py/src/parsing/components/__init__.py +19 -0
  170. package/flowquery-py/src/parsing/components/csv.py +8 -0
  171. package/flowquery-py/src/parsing/components/from_.py +10 -0
  172. package/flowquery-py/src/parsing/components/headers.py +12 -0
  173. package/flowquery-py/src/parsing/components/json.py +8 -0
  174. package/flowquery-py/src/parsing/components/null.py +10 -0
  175. package/flowquery-py/src/parsing/components/post.py +8 -0
  176. package/flowquery-py/src/parsing/components/text.py +8 -0
  177. package/flowquery-py/src/parsing/context.py +50 -0
  178. package/flowquery-py/src/parsing/data_structures/__init__.py +15 -0
  179. package/flowquery-py/src/parsing/data_structures/associative_array.py +41 -0
  180. package/flowquery-py/src/parsing/data_structures/json_array.py +30 -0
  181. package/flowquery-py/src/parsing/data_structures/key_value_pair.py +38 -0
  182. package/flowquery-py/src/parsing/data_structures/lookup.py +49 -0
  183. package/flowquery-py/src/parsing/data_structures/range_lookup.py +42 -0
  184. package/flowquery-py/src/parsing/expressions/__init__.py +57 -0
  185. package/flowquery-py/src/parsing/expressions/boolean.py +20 -0
  186. package/flowquery-py/src/parsing/expressions/expression.py +138 -0
  187. package/flowquery-py/src/parsing/expressions/expression_map.py +26 -0
  188. package/flowquery-py/src/parsing/expressions/f_string.py +27 -0
  189. package/flowquery-py/src/parsing/expressions/identifier.py +20 -0
  190. package/flowquery-py/src/parsing/expressions/number.py +32 -0
  191. package/flowquery-py/src/parsing/expressions/operator.py +169 -0
  192. package/flowquery-py/src/parsing/expressions/reference.py +47 -0
  193. package/flowquery-py/src/parsing/expressions/string.py +27 -0
  194. package/flowquery-py/src/parsing/functions/__init__.py +75 -0
  195. package/flowquery-py/src/parsing/functions/aggregate_function.py +60 -0
  196. package/flowquery-py/src/parsing/functions/async_function.py +62 -0
  197. package/flowquery-py/src/parsing/functions/avg.py +55 -0
  198. package/flowquery-py/src/parsing/functions/collect.py +75 -0
  199. package/flowquery-py/src/parsing/functions/function.py +68 -0
  200. package/flowquery-py/src/parsing/functions/function_factory.py +173 -0
  201. package/flowquery-py/src/parsing/functions/function_metadata.py +149 -0
  202. package/flowquery-py/src/parsing/functions/functions.py +59 -0
  203. package/flowquery-py/src/parsing/functions/join.py +47 -0
  204. package/flowquery-py/src/parsing/functions/keys.py +34 -0
  205. package/flowquery-py/src/parsing/functions/predicate_function.py +46 -0
  206. package/flowquery-py/src/parsing/functions/predicate_sum.py +47 -0
  207. package/flowquery-py/src/parsing/functions/rand.py +28 -0
  208. package/flowquery-py/src/parsing/functions/range_.py +34 -0
  209. package/flowquery-py/src/parsing/functions/reducer_element.py +15 -0
  210. package/flowquery-py/src/parsing/functions/replace.py +37 -0
  211. package/flowquery-py/src/parsing/functions/round_.py +32 -0
  212. package/flowquery-py/src/parsing/functions/size.py +32 -0
  213. package/flowquery-py/src/parsing/functions/split.py +47 -0
  214. package/flowquery-py/src/parsing/functions/stringify.py +47 -0
  215. package/flowquery-py/src/parsing/functions/sum.py +51 -0
  216. package/flowquery-py/src/parsing/functions/to_json.py +33 -0
  217. package/flowquery-py/src/parsing/functions/type_.py +47 -0
  218. package/flowquery-py/src/parsing/functions/value_holder.py +24 -0
  219. package/flowquery-py/src/parsing/logic/__init__.py +15 -0
  220. package/flowquery-py/src/parsing/logic/case.py +29 -0
  221. package/flowquery-py/src/parsing/logic/else_.py +12 -0
  222. package/flowquery-py/src/parsing/logic/end.py +8 -0
  223. package/flowquery-py/src/parsing/logic/then.py +12 -0
  224. package/flowquery-py/src/parsing/logic/when.py +10 -0
  225. package/flowquery-py/src/parsing/operations/__init__.py +35 -0
  226. package/flowquery-py/src/parsing/operations/aggregated_return.py +24 -0
  227. package/flowquery-py/src/parsing/operations/aggregated_with.py +22 -0
  228. package/flowquery-py/src/parsing/operations/call.py +74 -0
  229. package/flowquery-py/src/parsing/operations/create_node.py +34 -0
  230. package/flowquery-py/src/parsing/operations/create_relationship.py +34 -0
  231. package/flowquery-py/src/parsing/operations/group_by.py +130 -0
  232. package/flowquery-py/src/parsing/operations/limit.py +22 -0
  233. package/flowquery-py/src/parsing/operations/load.py +146 -0
  234. package/flowquery-py/src/parsing/operations/match.py +29 -0
  235. package/flowquery-py/src/parsing/operations/operation.py +69 -0
  236. package/flowquery-py/src/parsing/operations/projection.py +21 -0
  237. package/flowquery-py/src/parsing/operations/return_op.py +50 -0
  238. package/flowquery-py/src/parsing/operations/unwind.py +37 -0
  239. package/flowquery-py/src/parsing/operations/where.py +41 -0
  240. package/flowquery-py/src/parsing/operations/with_op.py +18 -0
  241. package/flowquery-py/src/parsing/parser.py +1010 -0
  242. package/flowquery-py/src/parsing/token_to_node.py +109 -0
  243. package/flowquery-py/src/tokenization/__init__.py +23 -0
  244. package/flowquery-py/src/tokenization/keyword.py +48 -0
  245. package/flowquery-py/src/tokenization/operator.py +29 -0
  246. package/flowquery-py/src/tokenization/string_walker.py +158 -0
  247. package/flowquery-py/src/tokenization/symbol.py +19 -0
  248. package/flowquery-py/src/tokenization/token.py +605 -0
  249. package/flowquery-py/src/tokenization/token_mapper.py +52 -0
  250. package/flowquery-py/src/tokenization/token_type.py +21 -0
  251. package/flowquery-py/src/tokenization/tokenizer.py +214 -0
  252. package/flowquery-py/src/tokenization/trie.py +124 -0
  253. package/flowquery-py/src/utils/__init__.py +6 -0
  254. package/flowquery-py/src/utils/object_utils.py +20 -0
  255. package/flowquery-py/src/utils/string_utils.py +113 -0
  256. package/flowquery-py/tests/__init__.py +1 -0
  257. package/flowquery-py/tests/compute/__init__.py +1 -0
  258. package/flowquery-py/tests/compute/test_runner.py +1335 -0
  259. package/flowquery-py/tests/graph/__init__.py +1 -0
  260. package/flowquery-py/tests/graph/test_create.py +56 -0
  261. package/flowquery-py/tests/graph/test_data.py +73 -0
  262. package/flowquery-py/tests/graph/test_match.py +40 -0
  263. package/flowquery-py/tests/parsing/__init__.py +1 -0
  264. package/flowquery-py/tests/parsing/test_context.py +34 -0
  265. package/flowquery-py/tests/parsing/test_expression.py +49 -0
  266. package/flowquery-py/tests/parsing/test_parser.py +680 -0
  267. package/flowquery-py/tests/test_extensibility.py +611 -0
  268. package/flowquery-py/tests/tokenization/__init__.py +1 -0
  269. package/flowquery-py/tests/tokenization/test_token_mapper.py +60 -0
  270. package/flowquery-py/tests/tokenization/test_tokenizer.py +164 -0
  271. package/flowquery-py/tests/tokenization/test_trie.py +30 -0
  272. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  273. package/misc/apps/RAG/package.json +1 -1
  274. package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +76 -8
  275. package/misc/apps/RAG/src/components/index.ts +19 -10
  276. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +70 -140
  277. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +12 -0
  278. package/package.json +1 -1
  279. package/src/compute/runner.ts +24 -19
  280. package/src/graph/data.ts +112 -0
  281. package/src/graph/database.ts +63 -0
  282. package/src/graph/hops.ts +22 -0
  283. package/src/graph/node.ts +99 -0
  284. package/src/graph/node_data.ts +18 -0
  285. package/src/graph/node_reference.ts +33 -0
  286. package/src/graph/pattern.ts +101 -0
  287. package/src/graph/pattern_expression.ts +48 -0
  288. package/src/graph/patterns.ts +36 -0
  289. package/src/graph/physical_node.ts +23 -0
  290. package/src/graph/physical_relationship.ts +23 -0
  291. package/src/graph/relationship.ts +116 -0
  292. package/src/graph/relationship_data.ts +27 -0
  293. package/src/graph/relationship_match_collector.ts +58 -0
  294. package/src/graph/relationship_reference.ts +24 -0
  295. package/src/parsing/base_parser.ts +20 -14
  296. package/src/parsing/context.ts +14 -14
  297. package/src/parsing/expressions/boolean.ts +21 -0
  298. package/src/parsing/expressions/expression.ts +34 -26
  299. package/src/parsing/expressions/operator.ts +19 -1
  300. package/src/parsing/functions/function_factory.ts +45 -45
  301. package/src/parsing/operations/create_node.ts +39 -0
  302. package/src/parsing/operations/create_relationship.ts +38 -0
  303. package/src/parsing/operations/match.ts +31 -0
  304. package/src/parsing/operations/operation.ts +3 -0
  305. package/src/parsing/operations/return.ts +11 -7
  306. package/src/parsing/operations/where.ts +10 -6
  307. package/src/parsing/parser.ts +349 -8
  308. package/src/parsing/token_to_node.ts +6 -0
  309. package/src/tokenization/keyword.ts +41 -40
  310. package/src/tokenization/token.ts +21 -1
  311. package/src/tokenization/token_type.ts +2 -1
  312. package/src/tokenization/tokenizer.ts +52 -31
  313. package/tests/compute/runner.test.ts +654 -0
  314. package/tests/extensibility.test.ts +97 -93
  315. package/tests/graph/create.test.ts +36 -0
  316. package/tests/graph/data.test.ts +58 -0
  317. package/tests/graph/match.test.ts +29 -0
  318. package/tests/parsing/parser.test.ts +281 -2
  319. package/tests/tokenization/tokenizer.test.ts +90 -0
@@ -0,0 +1,605 @@
1
+ """Represents a single token in the FlowQuery language."""
2
+
3
+ from __future__ import annotations
4
+ from typing import TYPE_CHECKING, Optional, Any
5
+
6
+ from .token_type import TokenType
7
+ from .keyword import Keyword
8
+ from .operator import Operator
9
+ from .symbol import Symbol
10
+ from ..utils.string_utils import StringUtils
11
+
12
+ if TYPE_CHECKING:
13
+ from ..parsing.ast_node import ASTNode
14
+
15
+
16
+ class Token:
17
+ """Represents a single token in the FlowQuery language.
18
+
19
+ Tokens are the atomic units of lexical analysis, produced by the tokenizer
20
+ and consumed by the parser. Each token has a type (keyword, operator, identifier, etc.)
21
+ and an optional value.
22
+
23
+ Example:
24
+ with_token = Token.WITH()
25
+ ident_token = Token.IDENTIFIER("myVar")
26
+ num_token = Token.NUMBER("42")
27
+ """
28
+
29
+ def __init__(self, type_: TokenType, value: Optional[str] = None):
30
+ """Creates a new Token instance.
31
+
32
+ Args:
33
+ type_: The type of the token
34
+ value: The optional value associated with the token
35
+ """
36
+ self._position: int = -1
37
+ self._type = type_
38
+ self._value = value
39
+ self._case_sensitive_value: Optional[str] = None
40
+ self._can_be_identifier = StringUtils.can_be_identifier(value or "")
41
+
42
+ def equals(self, other: Token) -> bool:
43
+ """Checks if this token equals another token.
44
+
45
+ Args:
46
+ other: The token to compare against
47
+
48
+ Returns:
49
+ True if tokens are equal, False otherwise
50
+ """
51
+ if self._type == TokenType.IDENTIFIER and other.type == TokenType.IDENTIFIER:
52
+ return True # Identifier values are not compared
53
+ return self._type == other.type and self._value == other.value
54
+
55
+ @property
56
+ def position(self) -> int:
57
+ return self._position
58
+
59
+ @position.setter
60
+ def position(self, value: int) -> None:
61
+ self._position = value
62
+
63
+ @property
64
+ def type(self) -> TokenType:
65
+ return self._type
66
+
67
+ @property
68
+ def value(self) -> Optional[str]:
69
+ return self._case_sensitive_value or self._value
70
+
71
+ @property
72
+ def case_sensitive_value(self) -> Optional[str]:
73
+ return self._case_sensitive_value
74
+
75
+ @case_sensitive_value.setter
76
+ def case_sensitive_value(self, value: str) -> None:
77
+ self._case_sensitive_value = value
78
+
79
+ @property
80
+ def can_be_identifier(self) -> bool:
81
+ return self._can_be_identifier
82
+
83
+ @property
84
+ def node(self) -> ASTNode:
85
+ from ..parsing.token_to_node import TokenToNode
86
+ return TokenToNode.convert(self)
87
+
88
+ def __str__(self) -> str:
89
+ return f"{self._type.value} {self._value}"
90
+
91
+ # Comment tokens
92
+
93
+ @staticmethod
94
+ def COMMENT(comment: str) -> Token:
95
+ return Token(TokenType.COMMENT, comment)
96
+
97
+ def is_comment(self) -> bool:
98
+ return self._type == TokenType.COMMENT
99
+
100
+ # Identifier token
101
+
102
+ @staticmethod
103
+ def IDENTIFIER(value: str) -> Token:
104
+ return Token(TokenType.IDENTIFIER, value)
105
+
106
+ def is_identifier(self) -> bool:
107
+ return self._type == TokenType.IDENTIFIER or self._type == TokenType.BACKTICK_STRING
108
+
109
+ # String token
110
+
111
+ @staticmethod
112
+ def STRING(value: str, quote_char: str = '"') -> Token:
113
+ unquoted = StringUtils.unquote(value)
114
+ unescaped = StringUtils.remove_escaped_quotes(unquoted, quote_char)
115
+ return Token(TokenType.STRING, unescaped)
116
+
117
+ def is_string(self) -> bool:
118
+ return self._type == TokenType.STRING or self._type == TokenType.BACKTICK_STRING
119
+
120
+ @staticmethod
121
+ def BACKTICK_STRING(value: str, quote_char: str = '"') -> Token:
122
+ unquoted = StringUtils.unquote(value)
123
+ unescaped = StringUtils.remove_escaped_quotes(unquoted, quote_char)
124
+ return Token(TokenType.BACKTICK_STRING, unescaped)
125
+
126
+ @staticmethod
127
+ def F_STRING(value: str, quote_char: str = '"') -> Token:
128
+ unquoted = StringUtils.unquote(value)
129
+ unescaped = StringUtils.remove_escaped_quotes(unquoted, quote_char)
130
+ fstring = StringUtils.remove_escaped_braces(unescaped)
131
+ return Token(TokenType.F_STRING, fstring)
132
+
133
+ def is_f_string(self) -> bool:
134
+ return self._type == TokenType.F_STRING
135
+
136
+ # Number token
137
+
138
+ @staticmethod
139
+ def NUMBER(value: str) -> Token:
140
+ return Token(TokenType.NUMBER, value)
141
+
142
+ def is_number(self) -> bool:
143
+ return self._type == TokenType.NUMBER
144
+
145
+ # Boolean token
146
+
147
+ @staticmethod
148
+ def BOOLEAN(value: str) -> Token:
149
+ return Token(TokenType.BOOLEAN, value)
150
+
151
+ def is_boolean(self) -> bool:
152
+ return self._type == TokenType.BOOLEAN and self._value in ("TRUE", "FALSE")
153
+
154
+ # Symbol tokens
155
+
156
+ @staticmethod
157
+ def LEFT_PARENTHESIS() -> Token:
158
+ return Token(TokenType.SYMBOL, Symbol.LEFT_PARENTHESIS.value)
159
+
160
+ def is_left_parenthesis(self) -> bool:
161
+ return self._type == TokenType.SYMBOL and self._value == Symbol.LEFT_PARENTHESIS.value
162
+
163
+ @staticmethod
164
+ def RIGHT_PARENTHESIS() -> Token:
165
+ return Token(TokenType.SYMBOL, Symbol.RIGHT_PARENTHESIS.value)
166
+
167
+ def is_right_parenthesis(self) -> bool:
168
+ return self._type == TokenType.SYMBOL and self._value == Symbol.RIGHT_PARENTHESIS.value
169
+
170
+ @staticmethod
171
+ def COMMA() -> Token:
172
+ return Token(TokenType.SYMBOL, Symbol.COMMA.value)
173
+
174
+ def is_comma(self) -> bool:
175
+ return self._type == TokenType.SYMBOL and self._value == Symbol.COMMA.value
176
+
177
+ @staticmethod
178
+ def DOT() -> Token:
179
+ return Token(TokenType.SYMBOL, Symbol.DOT.value)
180
+
181
+ def is_dot(self) -> bool:
182
+ return self._type == TokenType.SYMBOL and self._value == Symbol.DOT.value
183
+
184
+ @staticmethod
185
+ def COLON() -> Token:
186
+ return Token(TokenType.SYMBOL, Symbol.COLON.value)
187
+
188
+ def is_colon(self) -> bool:
189
+ return self._type == TokenType.SYMBOL and self._value == Symbol.COLON.value
190
+
191
+ @staticmethod
192
+ def OPENING_BRACE() -> Token:
193
+ return Token(TokenType.SYMBOL, Symbol.OPENING_BRACE.value)
194
+
195
+ def is_opening_brace(self) -> bool:
196
+ return self._type == TokenType.SYMBOL and self._value == Symbol.OPENING_BRACE.value
197
+
198
+ @staticmethod
199
+ def CLOSING_BRACE() -> Token:
200
+ return Token(TokenType.SYMBOL, Symbol.CLOSING_BRACE.value)
201
+
202
+ def is_closing_brace(self) -> bool:
203
+ return self._type == TokenType.SYMBOL and self._value == Symbol.CLOSING_BRACE.value
204
+
205
+ @staticmethod
206
+ def OPENING_BRACKET() -> Token:
207
+ return Token(TokenType.SYMBOL, Symbol.OPENING_BRACKET.value)
208
+
209
+ def is_opening_bracket(self) -> bool:
210
+ return self._type == TokenType.SYMBOL and self._value == Symbol.OPENING_BRACKET.value
211
+
212
+ @staticmethod
213
+ def CLOSING_BRACKET() -> Token:
214
+ return Token(TokenType.SYMBOL, Symbol.CLOSING_BRACKET.value)
215
+
216
+ def is_closing_bracket(self) -> bool:
217
+ return self._type == TokenType.SYMBOL and self._value == Symbol.CLOSING_BRACKET.value
218
+
219
+ # Whitespace token
220
+
221
+ @staticmethod
222
+ def WHITESPACE() -> Token:
223
+ return Token(TokenType.WHITESPACE)
224
+
225
+ def is_whitespace(self) -> bool:
226
+ return self._type == TokenType.WHITESPACE
227
+
228
+ # Operator tokens
229
+
230
+ def is_operator(self) -> bool:
231
+ return self._type == TokenType.OPERATOR
232
+
233
+ def is_unary_operator(self) -> bool:
234
+ return self._type == TokenType.UNARY_OPERATOR
235
+
236
+ @staticmethod
237
+ def ADD() -> Token:
238
+ return Token(TokenType.OPERATOR, Operator.ADD.value)
239
+
240
+ def is_add(self) -> bool:
241
+ return self._type == TokenType.OPERATOR and self._value == Operator.ADD.value
242
+
243
+ @staticmethod
244
+ def SUBTRACT() -> Token:
245
+ return Token(TokenType.OPERATOR, Operator.SUBTRACT.value)
246
+
247
+ def is_subtract(self) -> bool:
248
+ return self._type == TokenType.OPERATOR and self._value == Operator.SUBTRACT.value
249
+
250
+ def is_negation(self) -> bool:
251
+ return self.is_subtract()
252
+
253
+ @staticmethod
254
+ def MULTIPLY() -> Token:
255
+ return Token(TokenType.OPERATOR, Operator.MULTIPLY.value)
256
+
257
+ def is_multiply(self) -> bool:
258
+ return self._type == TokenType.OPERATOR and self._value == Operator.MULTIPLY.value
259
+
260
+ @staticmethod
261
+ def DIVIDE() -> Token:
262
+ return Token(TokenType.OPERATOR, Operator.DIVIDE.value)
263
+
264
+ def is_divide(self) -> bool:
265
+ return self._type == TokenType.OPERATOR and self._value == Operator.DIVIDE.value
266
+
267
+ @staticmethod
268
+ def EXPONENT() -> Token:
269
+ return Token(TokenType.OPERATOR, Operator.EXPONENT.value)
270
+
271
+ def is_exponent(self) -> bool:
272
+ return self._type == TokenType.OPERATOR and self._value == Operator.EXPONENT.value
273
+
274
+ @staticmethod
275
+ def MODULO() -> Token:
276
+ return Token(TokenType.OPERATOR, Operator.MODULO.value)
277
+
278
+ def is_modulo(self) -> bool:
279
+ return self._type == TokenType.OPERATOR and self._value == Operator.MODULO.value
280
+
281
+ @staticmethod
282
+ def EQUALS() -> Token:
283
+ return Token(TokenType.OPERATOR, Operator.EQUALS.value)
284
+
285
+ def is_equals(self) -> bool:
286
+ return self._type == TokenType.OPERATOR and self._value == Operator.EQUALS.value
287
+
288
+ @staticmethod
289
+ def NOT_EQUALS() -> Token:
290
+ return Token(TokenType.OPERATOR, Operator.NOT_EQUALS.value)
291
+
292
+ def is_not_equals(self) -> bool:
293
+ return self._type == TokenType.OPERATOR and self._value == Operator.NOT_EQUALS.value
294
+
295
+ @staticmethod
296
+ def LESS_THAN() -> Token:
297
+ return Token(TokenType.OPERATOR, Operator.LESS_THAN.value)
298
+
299
+ def is_less_than(self) -> bool:
300
+ return self._type == TokenType.OPERATOR and self._value == Operator.LESS_THAN.value
301
+
302
+ @staticmethod
303
+ def LESS_THAN_OR_EQUAL() -> Token:
304
+ return Token(TokenType.OPERATOR, Operator.LESS_THAN_OR_EQUAL.value)
305
+
306
+ def is_less_than_or_equal(self) -> bool:
307
+ return self._type == TokenType.OPERATOR and self._value == Operator.LESS_THAN_OR_EQUAL.value
308
+
309
+ @staticmethod
310
+ def GREATER_THAN() -> Token:
311
+ return Token(TokenType.OPERATOR, Operator.GREATER_THAN.value)
312
+
313
+ def is_greater_than(self) -> bool:
314
+ return self._type == TokenType.OPERATOR and self._value == Operator.GREATER_THAN.value
315
+
316
+ @staticmethod
317
+ def GREATER_THAN_OR_EQUAL() -> Token:
318
+ return Token(TokenType.OPERATOR, Operator.GREATER_THAN_OR_EQUAL.value)
319
+
320
+ def is_greater_than_or_equal(self) -> bool:
321
+ return self._type == TokenType.OPERATOR and self._value == Operator.GREATER_THAN_OR_EQUAL.value
322
+
323
+ @staticmethod
324
+ def AND() -> Token:
325
+ return Token(TokenType.OPERATOR, Operator.AND.value)
326
+
327
+ def is_and(self) -> bool:
328
+ return self._type == TokenType.OPERATOR and self._value == Operator.AND.value
329
+
330
+ @staticmethod
331
+ def OR() -> Token:
332
+ return Token(TokenType.OPERATOR, Operator.OR.value)
333
+
334
+ def is_or(self) -> bool:
335
+ return self._type == TokenType.OPERATOR and self._value == Operator.OR.value
336
+
337
+ @staticmethod
338
+ def NOT() -> Token:
339
+ return Token(TokenType.UNARY_OPERATOR, Operator.NOT.value)
340
+
341
+ def is_not(self) -> bool:
342
+ return self._type == TokenType.UNARY_OPERATOR and self._value == Operator.NOT.value
343
+
344
+ @staticmethod
345
+ def IS() -> Token:
346
+ return Token(TokenType.OPERATOR, Operator.IS.value)
347
+
348
+ def is_is(self) -> bool:
349
+ return self._type == TokenType.OPERATOR and self._value == Operator.IS.value
350
+
351
+ # Keyword tokens
352
+
353
+ def is_keyword(self) -> bool:
354
+ return self._type == TokenType.KEYWORD
355
+
356
+ @staticmethod
357
+ def WITH() -> Token:
358
+ return Token(TokenType.KEYWORD, Keyword.WITH.value)
359
+
360
+ def is_with(self) -> bool:
361
+ return self._type == TokenType.KEYWORD and self._value == Keyword.WITH.value
362
+
363
+ @staticmethod
364
+ def RETURN() -> Token:
365
+ return Token(TokenType.KEYWORD, Keyword.RETURN.value)
366
+
367
+ def is_return(self) -> bool:
368
+ return self._type == TokenType.KEYWORD and self._value == Keyword.RETURN.value
369
+
370
+ @staticmethod
371
+ def LOAD() -> Token:
372
+ return Token(TokenType.KEYWORD, Keyword.LOAD.value)
373
+
374
+ def is_load(self) -> bool:
375
+ return self._type == TokenType.KEYWORD and self._value == Keyword.LOAD.value
376
+
377
+ @staticmethod
378
+ def CALL() -> Token:
379
+ return Token(TokenType.KEYWORD, Keyword.CALL.value)
380
+
381
+ def is_call(self) -> bool:
382
+ return self._type == TokenType.KEYWORD and self._value == Keyword.CALL.value
383
+
384
+ @staticmethod
385
+ def YIELD() -> Token:
386
+ return Token(TokenType.KEYWORD, Keyword.YIELD.value)
387
+
388
+ def is_yield(self) -> bool:
389
+ return self._type == TokenType.KEYWORD and self._value == Keyword.YIELD.value
390
+
391
+ @staticmethod
392
+ def JSON() -> Token:
393
+ return Token(TokenType.KEYWORD, Keyword.JSON.value)
394
+
395
+ def is_json(self) -> bool:
396
+ return self._type == TokenType.KEYWORD and self._value == Keyword.JSON.value
397
+
398
+ @staticmethod
399
+ def CSV() -> Token:
400
+ return Token(TokenType.KEYWORD, Keyword.CSV.value)
401
+
402
+ def is_csv(self) -> bool:
403
+ return self._type == TokenType.KEYWORD and self._value == Keyword.CSV.value
404
+
405
+ @staticmethod
406
+ def TEXT() -> Token:
407
+ return Token(TokenType.KEYWORD, Keyword.TEXT.value)
408
+
409
+ def is_text(self) -> bool:
410
+ return self._type == TokenType.KEYWORD and self._value == Keyword.TEXT.value
411
+
412
+ @staticmethod
413
+ def FROM() -> Token:
414
+ return Token(TokenType.KEYWORD, Keyword.FROM.value)
415
+
416
+ def is_from(self) -> bool:
417
+ return self._type == TokenType.KEYWORD and self._value == Keyword.FROM.value
418
+
419
+ @staticmethod
420
+ def HEADERS() -> Token:
421
+ return Token(TokenType.KEYWORD, Keyword.HEADERS.value)
422
+
423
+ def is_headers(self) -> bool:
424
+ return self._type == TokenType.KEYWORD and self._value == Keyword.HEADERS.value
425
+
426
+ @staticmethod
427
+ def POST() -> Token:
428
+ return Token(TokenType.KEYWORD, Keyword.POST.value)
429
+
430
+ def is_post(self) -> bool:
431
+ return self._type == TokenType.KEYWORD and self._value == Keyword.POST.value
432
+
433
+ @staticmethod
434
+ def UNWIND() -> Token:
435
+ return Token(TokenType.KEYWORD, Keyword.UNWIND.value)
436
+
437
+ def is_unwind(self) -> bool:
438
+ return self._type == TokenType.KEYWORD and self._value == Keyword.UNWIND.value
439
+
440
+ @staticmethod
441
+ def MATCH() -> Token:
442
+ return Token(TokenType.KEYWORD, Keyword.MATCH.value)
443
+
444
+ def is_match(self) -> bool:
445
+ return self._type == TokenType.KEYWORD and self._value == Keyword.MATCH.value
446
+
447
+ @staticmethod
448
+ def AS() -> Token:
449
+ return Token(TokenType.KEYWORD, Keyword.AS.value)
450
+
451
+ def is_as(self) -> bool:
452
+ return self._type == TokenType.KEYWORD and self._value == Keyword.AS.value
453
+
454
+ @staticmethod
455
+ def WHERE() -> Token:
456
+ return Token(TokenType.KEYWORD, Keyword.WHERE.value)
457
+
458
+ def is_where(self) -> bool:
459
+ return self._type == TokenType.KEYWORD and self._value == Keyword.WHERE.value
460
+
461
+ @staticmethod
462
+ def MERGE() -> Token:
463
+ return Token(TokenType.KEYWORD, Keyword.MERGE.value)
464
+
465
+ def is_merge(self) -> bool:
466
+ return self._type == TokenType.KEYWORD and self._value == Keyword.MERGE.value
467
+
468
+ @staticmethod
469
+ def CREATE() -> Token:
470
+ return Token(TokenType.KEYWORD, Keyword.CREATE.value)
471
+
472
+ def is_create(self) -> bool:
473
+ return self._type == TokenType.KEYWORD and self._value == Keyword.CREATE.value
474
+
475
+ @staticmethod
476
+ def VIRTUAL() -> Token:
477
+ return Token(TokenType.KEYWORD, Keyword.VIRTUAL.value)
478
+
479
+ def is_virtual(self) -> bool:
480
+ return self._type == TokenType.KEYWORD and self._value == Keyword.VIRTUAL.value
481
+
482
+ @staticmethod
483
+ def DELETE() -> Token:
484
+ return Token(TokenType.KEYWORD, Keyword.DELETE.value)
485
+
486
+ def is_delete(self) -> bool:
487
+ return self._type == TokenType.KEYWORD and self._value == Keyword.DELETE.value
488
+
489
+ @staticmethod
490
+ def SET() -> Token:
491
+ return Token(TokenType.KEYWORD, Keyword.SET.value)
492
+
493
+ def is_set(self) -> bool:
494
+ return self._type == TokenType.KEYWORD and self._value == Keyword.SET.value
495
+
496
+ @staticmethod
497
+ def REMOVE() -> Token:
498
+ return Token(TokenType.KEYWORD, Keyword.REMOVE.value)
499
+
500
+ def is_remove(self) -> bool:
501
+ return self._type == TokenType.KEYWORD and self._value == Keyword.REMOVE.value
502
+
503
+ @staticmethod
504
+ def CASE() -> Token:
505
+ return Token(TokenType.KEYWORD, Keyword.CASE.value)
506
+
507
+ def is_case(self) -> bool:
508
+ return self._type == TokenType.KEYWORD and self._value == Keyword.CASE.value
509
+
510
+ @staticmethod
511
+ def WHEN() -> Token:
512
+ return Token(TokenType.KEYWORD, Keyword.WHEN.value)
513
+
514
+ def is_when(self) -> bool:
515
+ return self._type == TokenType.KEYWORD and self._value == Keyword.WHEN.value
516
+
517
+ @staticmethod
518
+ def THEN() -> Token:
519
+ return Token(TokenType.KEYWORD, Keyword.THEN.value)
520
+
521
+ def is_then(self) -> bool:
522
+ return self._type == TokenType.KEYWORD and self._value == Keyword.THEN.value
523
+
524
+ @staticmethod
525
+ def ELSE() -> Token:
526
+ return Token(TokenType.KEYWORD, Keyword.ELSE.value)
527
+
528
+ def is_else(self) -> bool:
529
+ return self._type == TokenType.KEYWORD and self._value == Keyword.ELSE.value
530
+
531
+ @staticmethod
532
+ def END() -> Token:
533
+ return Token(TokenType.KEYWORD, Keyword.END.value)
534
+
535
+ def is_end(self) -> bool:
536
+ return self._type == TokenType.KEYWORD and self._value == Keyword.END.value
537
+
538
+ @staticmethod
539
+ def NULL() -> Token:
540
+ return Token(TokenType.KEYWORD, Keyword.NULL.value)
541
+
542
+ def is_null(self) -> bool:
543
+ return self._type == TokenType.KEYWORD and self._value == Keyword.NULL.value
544
+
545
+ @staticmethod
546
+ def IN() -> Token:
547
+ return Token(TokenType.KEYWORD, Keyword.IN.value)
548
+
549
+ def is_in(self) -> bool:
550
+ return self._type == TokenType.KEYWORD and self._value == Keyword.IN.value
551
+
552
+ @staticmethod
553
+ def PIPE() -> Token:
554
+ return Token(TokenType.KEYWORD, Operator.PIPE.value)
555
+
556
+ def is_pipe(self) -> bool:
557
+ return self._type == TokenType.KEYWORD and self._value == Operator.PIPE.value
558
+
559
+ @staticmethod
560
+ def DISTINCT() -> Token:
561
+ return Token(TokenType.KEYWORD, Keyword.DISTINCT.value)
562
+
563
+ def is_distinct(self) -> bool:
564
+ return self._type == TokenType.KEYWORD and self._value == Keyword.DISTINCT.value
565
+
566
+ @staticmethod
567
+ def LIMIT() -> Token:
568
+ return Token(TokenType.KEYWORD, Keyword.LIMIT.value)
569
+
570
+ def is_limit(self) -> bool:
571
+ return self._type == TokenType.KEYWORD and self._value == Keyword.LIMIT.value
572
+
573
+ # End of file token
574
+
575
+ @staticmethod
576
+ def EOF() -> Token:
577
+ return Token(TokenType.EOF)
578
+
579
+ def is_eof(self) -> bool:
580
+ return self._type == TokenType.EOF
581
+
582
+ # Other utility methods
583
+
584
+ def is_operand(self) -> bool:
585
+ return self.is_number() or self.is_boolean() or self.is_string() or self.is_null()
586
+
587
+ def is_whitespace_or_comment(self) -> bool:
588
+ return self.is_whitespace() or self.is_comment()
589
+
590
+ def is_symbol(self) -> bool:
591
+ return self._type == TokenType.SYMBOL
592
+
593
+ # Static class method lookup via string
594
+ @staticmethod
595
+ def method(name: str) -> Optional[Token]:
596
+ name_upper = name.upper()
597
+ if hasattr(Token, name_upper):
598
+ attr = getattr(Token, name_upper)
599
+ if callable(attr):
600
+ result = attr()
601
+ if isinstance(result, Token):
602
+ return result
603
+ elif isinstance(attr, Token):
604
+ return attr
605
+ return None
@@ -0,0 +1,52 @@
1
+ """Maps string values to tokens using a Trie for efficient lookup."""
2
+
3
+ from typing import Optional
4
+
5
+ from .token import Token
6
+ from .trie import Trie
7
+
8
+
9
+ class TokenMapper:
10
+ """Maps string values to tokens using a Trie for efficient lookup.
11
+
12
+ Takes an enum of keywords, operators, or symbols and builds a trie
13
+ for fast token matching during tokenization.
14
+
15
+ Example:
16
+ mapper = TokenMapper(Keyword)
17
+ token = mapper.map("WITH")
18
+ """
19
+
20
+ def __init__(self, enum_class):
21
+ """Creates a TokenMapper from an enum of token values.
22
+
23
+ Args:
24
+ enum_class: An enum class containing token values
25
+ """
26
+ self._trie = Trie()
27
+ self._enum = enum_class
28
+
29
+ for member in enum_class:
30
+ token = Token.method(member.name)
31
+ if token is not None and token.value is not None:
32
+ self._trie.insert(token)
33
+
34
+ def map(self, value: str) -> Optional[Token]:
35
+ """Maps a string value to its corresponding token.
36
+
37
+ Args:
38
+ value: The string value to map
39
+
40
+ Returns:
41
+ The matched token, or None if no match found
42
+ """
43
+ return self._trie.find(value)
44
+
45
+ @property
46
+ def last_found(self) -> Optional[str]:
47
+ """Gets the last matched string from the most recent map operation.
48
+
49
+ Returns:
50
+ The last found string, or None if no match
51
+ """
52
+ return self._trie.last_found
@@ -0,0 +1,21 @@
1
+ """Token type enumeration for FlowQuery tokenization."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class TokenType(Enum):
7
+ """Enumeration of all token types in FlowQuery."""
8
+
9
+ KEYWORD = "KEYWORD"
10
+ BOOLEAN = "BOOLEAN"
11
+ OPERATOR = "OPERATOR"
12
+ UNARY_OPERATOR = "UNARY_OPERATOR"
13
+ IDENTIFIER = "IDENTIFIER"
14
+ STRING = "STRING"
15
+ F_STRING = "F-STRING"
16
+ BACKTICK_STRING = "BACKTICK_STRING"
17
+ NUMBER = "NUMBER"
18
+ SYMBOL = "SYMBOL"
19
+ WHITESPACE = "WHITESPACE"
20
+ COMMENT = "COMMENT"
21
+ EOF = "EOF"