flowquery 1.0.15 → 1.0.17

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 (333) hide show
  1. package/.github/workflows/python-publish.yml +97 -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 +14 -0
  36. package/dist/graph/pattern_expression.d.ts.map +1 -0
  37. package/dist/graph/pattern_expression.js +58 -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/expression_map.d.ts +1 -0
  82. package/dist/parsing/expressions/expression_map.d.ts.map +1 -1
  83. package/dist/parsing/expressions/expression_map.js +3 -0
  84. package/dist/parsing/expressions/expression_map.js.map +1 -1
  85. package/dist/parsing/expressions/operator.d.ts +1 -1
  86. package/dist/parsing/expressions/operator.d.ts.map +1 -1
  87. package/dist/parsing/expressions/operator.js.map +1 -1
  88. package/dist/parsing/functions/function_factory.d.ts +13 -13
  89. package/dist/parsing/functions/function_factory.d.ts.map +1 -1
  90. package/dist/parsing/functions/function_factory.js +20 -18
  91. package/dist/parsing/functions/function_factory.js.map +1 -1
  92. package/dist/parsing/operations/call.d.ts.map +1 -1
  93. package/dist/parsing/operations/call.js +3 -1
  94. package/dist/parsing/operations/call.js.map +1 -1
  95. package/dist/parsing/operations/create_node.d.ts +14 -0
  96. package/dist/parsing/operations/create_node.d.ts.map +1 -0
  97. package/dist/parsing/operations/create_node.js +51 -0
  98. package/dist/parsing/operations/create_node.js.map +1 -0
  99. package/dist/parsing/operations/create_relationship.d.ts +14 -0
  100. package/dist/parsing/operations/create_relationship.d.ts.map +1 -0
  101. package/dist/parsing/operations/create_relationship.js +51 -0
  102. package/dist/parsing/operations/create_relationship.js.map +1 -0
  103. package/dist/parsing/operations/match.d.ts +15 -0
  104. package/dist/parsing/operations/match.d.ts.map +1 -0
  105. package/dist/parsing/operations/match.js +45 -0
  106. package/dist/parsing/operations/match.js.map +1 -0
  107. package/dist/parsing/operations/operation.d.ts +1 -0
  108. package/dist/parsing/operations/operation.d.ts.map +1 -1
  109. package/dist/parsing/operations/operation.js +6 -0
  110. package/dist/parsing/operations/operation.js.map +1 -1
  111. package/dist/parsing/operations/return.d.ts +1 -0
  112. package/dist/parsing/operations/return.d.ts.map +1 -1
  113. package/dist/parsing/operations/return.js +7 -1
  114. package/dist/parsing/operations/return.js.map +1 -1
  115. package/dist/parsing/operations/where.d.ts +1 -1
  116. package/dist/parsing/operations/where.d.ts.map +1 -1
  117. package/dist/parsing/operations/where.js +4 -0
  118. package/dist/parsing/operations/where.js.map +1 -1
  119. package/dist/parsing/parser.d.ts +10 -0
  120. package/dist/parsing/parser.d.ts.map +1 -1
  121. package/dist/parsing/parser.js +344 -5
  122. package/dist/parsing/parser.js.map +1 -1
  123. package/dist/parsing/token_to_node.d.ts.map +1 -1
  124. package/dist/parsing/token_to_node.js +7 -0
  125. package/dist/parsing/token_to_node.js.map +1 -1
  126. package/dist/tokenization/keyword.d.ts +1 -0
  127. package/dist/tokenization/keyword.d.ts.map +1 -1
  128. package/dist/tokenization/keyword.js +1 -0
  129. package/dist/tokenization/keyword.js.map +1 -1
  130. package/dist/tokenization/token.d.ts +4 -0
  131. package/dist/tokenization/token.d.ts.map +1 -1
  132. package/dist/tokenization/token.js +14 -1
  133. package/dist/tokenization/token.js.map +1 -1
  134. package/dist/tokenization/token_type.d.ts +1 -0
  135. package/dist/tokenization/token_type.d.ts.map +1 -1
  136. package/dist/tokenization/token_type.js +1 -0
  137. package/dist/tokenization/token_type.js.map +1 -1
  138. package/dist/tokenization/tokenizer.d.ts +2 -1
  139. package/dist/tokenization/tokenizer.d.ts.map +1 -1
  140. package/dist/tokenization/tokenizer.js +25 -12
  141. package/dist/tokenization/tokenizer.js.map +1 -1
  142. package/docs/flowquery.min.js +1 -1
  143. package/flowquery-py/README.md +166 -0
  144. package/flowquery-py/pyproject.toml +75 -0
  145. package/flowquery-py/setup_env.ps1 +92 -0
  146. package/flowquery-py/setup_env.sh +87 -0
  147. package/flowquery-py/src/__init__.py +34 -0
  148. package/flowquery-py/src/__main__.py +10 -0
  149. package/flowquery-py/src/compute/__init__.py +5 -0
  150. package/flowquery-py/src/compute/runner.py +60 -0
  151. package/flowquery-py/src/extensibility.py +52 -0
  152. package/flowquery-py/src/graph/__init__.py +31 -0
  153. package/flowquery-py/src/graph/data.py +118 -0
  154. package/flowquery-py/src/graph/database.py +82 -0
  155. package/flowquery-py/src/graph/hops.py +43 -0
  156. package/flowquery-py/src/graph/node.py +112 -0
  157. package/flowquery-py/src/graph/node_data.py +26 -0
  158. package/flowquery-py/src/graph/node_reference.py +49 -0
  159. package/flowquery-py/src/graph/pattern.py +125 -0
  160. package/flowquery-py/src/graph/pattern_expression.py +62 -0
  161. package/flowquery-py/src/graph/patterns.py +42 -0
  162. package/flowquery-py/src/graph/physical_node.py +40 -0
  163. package/flowquery-py/src/graph/physical_relationship.py +36 -0
  164. package/flowquery-py/src/graph/relationship.py +135 -0
  165. package/flowquery-py/src/graph/relationship_data.py +33 -0
  166. package/flowquery-py/src/graph/relationship_match_collector.py +77 -0
  167. package/flowquery-py/src/graph/relationship_reference.py +21 -0
  168. package/flowquery-py/src/io/__init__.py +5 -0
  169. package/flowquery-py/src/io/command_line.py +67 -0
  170. package/flowquery-py/src/parsing/__init__.py +17 -0
  171. package/flowquery-py/src/parsing/alias.py +20 -0
  172. package/flowquery-py/src/parsing/alias_option.py +11 -0
  173. package/flowquery-py/src/parsing/ast_node.py +146 -0
  174. package/flowquery-py/src/parsing/base_parser.py +84 -0
  175. package/flowquery-py/src/parsing/components/__init__.py +19 -0
  176. package/flowquery-py/src/parsing/components/csv.py +8 -0
  177. package/flowquery-py/src/parsing/components/from_.py +10 -0
  178. package/flowquery-py/src/parsing/components/headers.py +12 -0
  179. package/flowquery-py/src/parsing/components/json.py +8 -0
  180. package/flowquery-py/src/parsing/components/null.py +10 -0
  181. package/flowquery-py/src/parsing/components/post.py +8 -0
  182. package/flowquery-py/src/parsing/components/text.py +8 -0
  183. package/flowquery-py/src/parsing/context.py +50 -0
  184. package/flowquery-py/src/parsing/data_structures/__init__.py +15 -0
  185. package/flowquery-py/src/parsing/data_structures/associative_array.py +41 -0
  186. package/flowquery-py/src/parsing/data_structures/json_array.py +30 -0
  187. package/flowquery-py/src/parsing/data_structures/key_value_pair.py +38 -0
  188. package/flowquery-py/src/parsing/data_structures/lookup.py +49 -0
  189. package/flowquery-py/src/parsing/data_structures/range_lookup.py +42 -0
  190. package/flowquery-py/src/parsing/expressions/__init__.py +57 -0
  191. package/flowquery-py/src/parsing/expressions/boolean.py +20 -0
  192. package/flowquery-py/src/parsing/expressions/expression.py +138 -0
  193. package/flowquery-py/src/parsing/expressions/expression_map.py +26 -0
  194. package/flowquery-py/src/parsing/expressions/f_string.py +27 -0
  195. package/flowquery-py/src/parsing/expressions/identifier.py +20 -0
  196. package/flowquery-py/src/parsing/expressions/number.py +32 -0
  197. package/flowquery-py/src/parsing/expressions/operator.py +169 -0
  198. package/flowquery-py/src/parsing/expressions/reference.py +47 -0
  199. package/flowquery-py/src/parsing/expressions/string.py +27 -0
  200. package/flowquery-py/src/parsing/functions/__init__.py +75 -0
  201. package/flowquery-py/src/parsing/functions/aggregate_function.py +60 -0
  202. package/flowquery-py/src/parsing/functions/async_function.py +62 -0
  203. package/flowquery-py/src/parsing/functions/avg.py +55 -0
  204. package/flowquery-py/src/parsing/functions/collect.py +75 -0
  205. package/flowquery-py/src/parsing/functions/function.py +68 -0
  206. package/flowquery-py/src/parsing/functions/function_factory.py +173 -0
  207. package/flowquery-py/src/parsing/functions/function_metadata.py +149 -0
  208. package/flowquery-py/src/parsing/functions/functions.py +59 -0
  209. package/flowquery-py/src/parsing/functions/join.py +47 -0
  210. package/flowquery-py/src/parsing/functions/keys.py +34 -0
  211. package/flowquery-py/src/parsing/functions/predicate_function.py +46 -0
  212. package/flowquery-py/src/parsing/functions/predicate_sum.py +47 -0
  213. package/flowquery-py/src/parsing/functions/rand.py +28 -0
  214. package/flowquery-py/src/parsing/functions/range_.py +34 -0
  215. package/flowquery-py/src/parsing/functions/reducer_element.py +15 -0
  216. package/flowquery-py/src/parsing/functions/replace.py +37 -0
  217. package/flowquery-py/src/parsing/functions/round_.py +32 -0
  218. package/flowquery-py/src/parsing/functions/size.py +32 -0
  219. package/flowquery-py/src/parsing/functions/split.py +47 -0
  220. package/flowquery-py/src/parsing/functions/stringify.py +47 -0
  221. package/flowquery-py/src/parsing/functions/sum.py +51 -0
  222. package/flowquery-py/src/parsing/functions/to_json.py +33 -0
  223. package/flowquery-py/src/parsing/functions/type_.py +47 -0
  224. package/flowquery-py/src/parsing/functions/value_holder.py +24 -0
  225. package/flowquery-py/src/parsing/logic/__init__.py +15 -0
  226. package/flowquery-py/src/parsing/logic/case.py +29 -0
  227. package/flowquery-py/src/parsing/logic/else_.py +12 -0
  228. package/flowquery-py/src/parsing/logic/end.py +8 -0
  229. package/flowquery-py/src/parsing/logic/then.py +12 -0
  230. package/flowquery-py/src/parsing/logic/when.py +10 -0
  231. package/flowquery-py/src/parsing/operations/__init__.py +35 -0
  232. package/flowquery-py/src/parsing/operations/aggregated_return.py +24 -0
  233. package/flowquery-py/src/parsing/operations/aggregated_with.py +22 -0
  234. package/flowquery-py/src/parsing/operations/call.py +74 -0
  235. package/flowquery-py/src/parsing/operations/create_node.py +34 -0
  236. package/flowquery-py/src/parsing/operations/create_relationship.py +34 -0
  237. package/flowquery-py/src/parsing/operations/group_by.py +130 -0
  238. package/flowquery-py/src/parsing/operations/limit.py +22 -0
  239. package/flowquery-py/src/parsing/operations/load.py +140 -0
  240. package/flowquery-py/src/parsing/operations/match.py +29 -0
  241. package/flowquery-py/src/parsing/operations/operation.py +69 -0
  242. package/flowquery-py/src/parsing/operations/projection.py +21 -0
  243. package/flowquery-py/src/parsing/operations/return_op.py +50 -0
  244. package/flowquery-py/src/parsing/operations/unwind.py +37 -0
  245. package/flowquery-py/src/parsing/operations/where.py +41 -0
  246. package/flowquery-py/src/parsing/operations/with_op.py +18 -0
  247. package/flowquery-py/src/parsing/parser.py +1011 -0
  248. package/flowquery-py/src/parsing/token_to_node.py +109 -0
  249. package/flowquery-py/src/tokenization/__init__.py +23 -0
  250. package/flowquery-py/src/tokenization/keyword.py +48 -0
  251. package/flowquery-py/src/tokenization/operator.py +29 -0
  252. package/flowquery-py/src/tokenization/string_walker.py +158 -0
  253. package/flowquery-py/src/tokenization/symbol.py +19 -0
  254. package/flowquery-py/src/tokenization/token.py +659 -0
  255. package/flowquery-py/src/tokenization/token_mapper.py +52 -0
  256. package/flowquery-py/src/tokenization/token_type.py +21 -0
  257. package/flowquery-py/src/tokenization/tokenizer.py +214 -0
  258. package/flowquery-py/src/tokenization/trie.py +124 -0
  259. package/flowquery-py/src/utils/__init__.py +6 -0
  260. package/flowquery-py/src/utils/object_utils.py +20 -0
  261. package/flowquery-py/src/utils/string_utils.py +113 -0
  262. package/flowquery-py/tests/__init__.py +1 -0
  263. package/flowquery-py/tests/compute/__init__.py +1 -0
  264. package/flowquery-py/tests/compute/test_runner.py +1335 -0
  265. package/flowquery-py/tests/graph/__init__.py +1 -0
  266. package/flowquery-py/tests/graph/test_create.py +56 -0
  267. package/flowquery-py/tests/graph/test_data.py +73 -0
  268. package/flowquery-py/tests/graph/test_match.py +40 -0
  269. package/flowquery-py/tests/parsing/__init__.py +1 -0
  270. package/flowquery-py/tests/parsing/test_context.py +34 -0
  271. package/flowquery-py/tests/parsing/test_expression.py +49 -0
  272. package/flowquery-py/tests/parsing/test_parser.py +674 -0
  273. package/flowquery-py/tests/test_extensibility.py +611 -0
  274. package/flowquery-py/tests/tokenization/__init__.py +1 -0
  275. package/flowquery-py/tests/tokenization/test_token_mapper.py +60 -0
  276. package/flowquery-py/tests/tokenization/test_tokenizer.py +164 -0
  277. package/flowquery-py/tests/tokenization/test_trie.py +30 -0
  278. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  279. package/misc/apps/RAG/package.json +1 -1
  280. package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +76 -8
  281. package/misc/apps/RAG/src/components/index.ts +19 -10
  282. package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +21 -26
  283. package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +24 -25
  284. package/misc/apps/RAG/src/plugins/loaders/Form.ts +163 -147
  285. package/misc/apps/RAG/src/plugins/loaders/Llm.ts +103 -90
  286. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +80 -130
  287. package/misc/apps/RAG/src/plugins/loaders/Table.ts +104 -101
  288. package/misc/apps/RAG/src/plugins/loaders/Weather.ts +47 -36
  289. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +89 -78
  290. package/package.json +1 -1
  291. package/src/compute/runner.ts +24 -19
  292. package/src/graph/data.ts +112 -0
  293. package/src/graph/database.ts +63 -0
  294. package/src/graph/hops.ts +22 -0
  295. package/src/graph/node.ts +99 -0
  296. package/src/graph/node_data.ts +18 -0
  297. package/src/graph/node_reference.ts +33 -0
  298. package/src/graph/pattern.ts +101 -0
  299. package/src/graph/pattern_expression.ts +37 -0
  300. package/src/graph/patterns.ts +36 -0
  301. package/src/graph/physical_node.ts +23 -0
  302. package/src/graph/physical_relationship.ts +23 -0
  303. package/src/graph/relationship.ts +116 -0
  304. package/src/graph/relationship_data.ts +27 -0
  305. package/src/graph/relationship_match_collector.ts +58 -0
  306. package/src/graph/relationship_reference.ts +24 -0
  307. package/src/parsing/base_parser.ts +20 -14
  308. package/src/parsing/context.ts +14 -14
  309. package/src/parsing/expressions/boolean.ts +21 -0
  310. package/src/parsing/expressions/expression.ts +34 -26
  311. package/src/parsing/expressions/expression_map.ts +3 -0
  312. package/src/parsing/expressions/operator.ts +19 -1
  313. package/src/parsing/functions/function_factory.ts +45 -45
  314. package/src/parsing/operations/call.ts +3 -1
  315. package/src/parsing/operations/create_node.ts +39 -0
  316. package/src/parsing/operations/create_relationship.ts +38 -0
  317. package/src/parsing/operations/match.ts +31 -0
  318. package/src/parsing/operations/operation.ts +3 -0
  319. package/src/parsing/operations/return.ts +11 -7
  320. package/src/parsing/operations/where.ts +10 -6
  321. package/src/parsing/parser.ts +346 -8
  322. package/src/parsing/token_to_node.ts +6 -0
  323. package/src/tokenization/keyword.ts +41 -40
  324. package/src/tokenization/token.ts +21 -1
  325. package/src/tokenization/token_type.ts +2 -1
  326. package/src/tokenization/tokenizer.ts +52 -31
  327. package/tests/compute/runner.test.ts +660 -6
  328. package/tests/extensibility.test.ts +97 -93
  329. package/tests/graph/create.test.ts +36 -0
  330. package/tests/graph/data.test.ts +58 -0
  331. package/tests/graph/match.test.ts +29 -0
  332. package/tests/parsing/parser.test.ts +276 -8
  333. package/tests/tokenization/tokenizer.test.ts +107 -17
@@ -0,0 +1,84 @@
1
+ """Base class for parsers providing common token manipulation functionality."""
2
+
3
+ from typing import List, Optional
4
+
5
+ from ..tokenization.token import Token
6
+ from ..tokenization.tokenizer import Tokenizer
7
+
8
+
9
+ class BaseParser:
10
+ """Base class for parsers providing common token manipulation functionality.
11
+
12
+ This class handles tokenization and provides utility methods for navigating
13
+ through tokens, peeking ahead, and checking token sequences.
14
+ """
15
+
16
+ def __init__(self, tokens: Optional[List[Token]] = None):
17
+ self._tokens: List[Token] = tokens or []
18
+ self._token_index: int = 0
19
+
20
+ def tokenize(self, statement: str) -> None:
21
+ """Tokenizes a statement and initializes the token array.
22
+
23
+ Args:
24
+ statement: The input statement to tokenize
25
+ """
26
+ self._tokens = Tokenizer(statement).tokenize()
27
+ self._token_index = 0
28
+
29
+ def set_next_token(self) -> None:
30
+ """Advances to the next token in the sequence."""
31
+ self._token_index += 1
32
+
33
+ def peek(self) -> Optional[Token]:
34
+ """Peeks at the next token without advancing the current position.
35
+
36
+ Returns:
37
+ The next token, or None if at the end of the token stream
38
+ """
39
+ if self._token_index + 1 >= len(self._tokens):
40
+ return None
41
+ return self._tokens[self._token_index + 1]
42
+
43
+ def ahead(self, tokens: List[Token], skip_whitespace_and_comments: bool = True) -> bool:
44
+ """Checks if a sequence of tokens appears ahead in the token stream.
45
+
46
+ Args:
47
+ tokens: The sequence of tokens to look for
48
+ skip_whitespace_and_comments: Whether to skip whitespace and comments when matching
49
+
50
+ Returns:
51
+ True if the token sequence is found ahead, False otherwise
52
+ """
53
+ j = 0
54
+ for i in range(self._token_index, len(self._tokens)):
55
+ if skip_whitespace_and_comments and self._tokens[i].is_whitespace_or_comment():
56
+ continue
57
+ if not self._tokens[i].equals(tokens[j]):
58
+ return False
59
+ j += 1
60
+ if j == len(tokens):
61
+ break
62
+ return j == len(tokens)
63
+
64
+ @property
65
+ def token(self) -> Token:
66
+ """Gets the current token.
67
+
68
+ Returns:
69
+ The current token, or EOF if at the end
70
+ """
71
+ if self._token_index >= len(self._tokens):
72
+ return Token.EOF
73
+ return self._tokens[self._token_index]
74
+
75
+ @property
76
+ def previous_token(self) -> Token:
77
+ """Gets the previous token.
78
+
79
+ Returns:
80
+ The previous token, or EOF if at the beginning
81
+ """
82
+ if self._token_index - 1 < 0:
83
+ return Token.EOF
84
+ return self._tokens[self._token_index - 1]
@@ -0,0 +1,19 @@
1
+ """Components module for FlowQuery parsing."""
2
+
3
+ from .csv import CSV
4
+ from .json import JSON
5
+ from .text import Text
6
+ from .from_ import From
7
+ from .headers import Headers
8
+ from .post import Post
9
+ from .null import Null
10
+
11
+ __all__ = [
12
+ "CSV",
13
+ "JSON",
14
+ "Text",
15
+ "From",
16
+ "Headers",
17
+ "Post",
18
+ "Null",
19
+ ]
@@ -0,0 +1,8 @@
1
+ """CSV component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class CSV(ASTNode):
7
+ """Represents a CSV data type marker in LOAD operations."""
8
+ pass
@@ -0,0 +1,10 @@
1
+ """From component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class From(ASTNode):
7
+ """Represents a FROM clause in LOAD operations."""
8
+
9
+ def value(self) -> str:
10
+ return self.children[0].value()
@@ -0,0 +1,12 @@
1
+ """Headers component node."""
2
+
3
+ from typing import Dict
4
+
5
+ from ..ast_node import ASTNode
6
+
7
+
8
+ class Headers(ASTNode):
9
+ """Represents a HEADERS clause in LOAD operations."""
10
+
11
+ def value(self) -> Dict:
12
+ return self.first_child().value() or {}
@@ -0,0 +1,8 @@
1
+ """JSON component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class JSON(ASTNode):
7
+ """Represents a JSON data type marker in LOAD operations."""
8
+ pass
@@ -0,0 +1,10 @@
1
+ """Null component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class Null(ASTNode):
7
+ """Represents a NULL value in the AST."""
8
+
9
+ def value(self):
10
+ return None
@@ -0,0 +1,8 @@
1
+ """Post component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class Post(ASTNode):
7
+ """Represents a POST clause in LOAD operations."""
8
+ pass
@@ -0,0 +1,8 @@
1
+ """Text component node."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class Text(ASTNode):
7
+ """Represents a Text data type marker in LOAD operations."""
8
+ pass
@@ -0,0 +1,50 @@
1
+ """Maintains a stack of AST nodes to track parsing context."""
2
+
3
+ from typing import List, Optional, Type
4
+
5
+ from .ast_node import ASTNode
6
+
7
+
8
+ class Context:
9
+ """Maintains a stack of AST nodes to track parsing context.
10
+
11
+ Used during parsing to maintain the current context and check for specific node types
12
+ in the parsing hierarchy, which helps with context-sensitive parsing decisions.
13
+
14
+ Example:
15
+ context = Context()
16
+ context.push(node)
17
+ has_return = context.contains_type(Return)
18
+ """
19
+
20
+ def __init__(self):
21
+ self._nodes: List[ASTNode] = []
22
+
23
+ def push(self, node: ASTNode) -> None:
24
+ """Pushes a node onto the context stack.
25
+
26
+ Args:
27
+ node: The AST node to push
28
+ """
29
+ self._nodes.append(node)
30
+
31
+ def pop(self) -> Optional[ASTNode]:
32
+ """Pops the top node from the context stack.
33
+
34
+ Returns:
35
+ The popped node, or None if the stack is empty
36
+ """
37
+ if len(self._nodes) == 0:
38
+ return None
39
+ return self._nodes.pop()
40
+
41
+ def contains_type(self, type_: Type[ASTNode]) -> bool:
42
+ """Checks if the nodes stack contains a node of the specified type.
43
+
44
+ Args:
45
+ type_: The class of the node type to search for
46
+
47
+ Returns:
48
+ True if a node of the specified type is found in the stack, False otherwise
49
+ """
50
+ return any(isinstance(v, type_) for v in self._nodes)
@@ -0,0 +1,15 @@
1
+ """Data structures module for FlowQuery parsing."""
2
+
3
+ from .associative_array import AssociativeArray
4
+ from .json_array import JSONArray
5
+ from .key_value_pair import KeyValuePair
6
+ from .lookup import Lookup
7
+ from .range_lookup import RangeLookup
8
+
9
+ __all__ = [
10
+ "AssociativeArray",
11
+ "JSONArray",
12
+ "KeyValuePair",
13
+ "Lookup",
14
+ "RangeLookup",
15
+ ]
@@ -0,0 +1,41 @@
1
+ """Represents an associative array (object/dictionary) in the AST."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..ast_node import ASTNode
6
+ from .key_value_pair import KeyValuePair
7
+
8
+
9
+ class AssociativeArray(ASTNode):
10
+ """Represents an associative array (object/dictionary) in the AST.
11
+
12
+ Associative arrays map string keys to values, similar to JSON objects.
13
+
14
+ Example:
15
+ # For { name: "Alice", age: 30 }
16
+ obj = AssociativeArray()
17
+ obj.add_key_value(KeyValuePair("name", name_expr))
18
+ obj.add_key_value(KeyValuePair("age", age_expr))
19
+ """
20
+
21
+ def add_key_value(self, key_value_pair: KeyValuePair) -> None:
22
+ """Adds a key-value pair to the associative array.
23
+
24
+ Args:
25
+ key_value_pair: The key-value pair to add
26
+ """
27
+ self.add_child(key_value_pair)
28
+
29
+ def __str__(self) -> str:
30
+ return 'AssociativeArray'
31
+
32
+ def _value(self):
33
+ for child in self.children:
34
+ key_value = child
35
+ yield {key_value.key: key_value._value}
36
+
37
+ def value(self) -> Dict[str, Any]:
38
+ result = {}
39
+ for item in self._value():
40
+ result.update(item)
41
+ return result
@@ -0,0 +1,30 @@
1
+ """Represents a JSON array in the AST."""
2
+
3
+ from typing import Any, List
4
+
5
+ from ..ast_node import ASTNode
6
+
7
+
8
+ class JSONArray(ASTNode):
9
+ """Represents a JSON array in the AST.
10
+
11
+ JSON arrays are ordered collections of values.
12
+
13
+ Example:
14
+ # For [1, 2, 3]
15
+ arr = JSONArray()
16
+ arr.add_value(Number("1"))
17
+ arr.add_value(Number("2"))
18
+ arr.add_value(Number("3"))
19
+ """
20
+
21
+ def add_value(self, value: ASTNode) -> None:
22
+ """Adds a value to the array.
23
+
24
+ Args:
25
+ value: The AST node representing the value to add
26
+ """
27
+ self.add_child(value)
28
+
29
+ def value(self) -> List[Any]:
30
+ return [child.value() for child in self.children]
@@ -0,0 +1,38 @@
1
+ """Represents a key-value pair in an associative array."""
2
+
3
+ from typing import Any
4
+
5
+ from ..ast_node import ASTNode
6
+ from ..expressions.string import String
7
+
8
+
9
+ class KeyValuePair(ASTNode):
10
+ """Represents a key-value pair in an associative array.
11
+
12
+ Used to build object literals in FlowQuery.
13
+
14
+ Example:
15
+ kvp = KeyValuePair("name", String("Alice"))
16
+ """
17
+
18
+ def __init__(self, key: str, value: ASTNode):
19
+ """Creates a new key-value pair.
20
+
21
+ Args:
22
+ key: The key string
23
+ value: The AST node representing the value
24
+ """
25
+ super().__init__()
26
+ self.add_child(String(key))
27
+ self.add_child(value)
28
+
29
+ @property
30
+ def key(self) -> str:
31
+ return self.children[0].value()
32
+
33
+ @property
34
+ def _value(self) -> Any:
35
+ return self.children[1].value()
36
+
37
+ def __str__(self) -> str:
38
+ return "KeyValuePair"
@@ -0,0 +1,49 @@
1
+ """Represents a lookup operation (array/object indexing) in the AST."""
2
+
3
+ from typing import Any
4
+
5
+ from ..ast_node import ASTNode
6
+
7
+
8
+ class Lookup(ASTNode):
9
+ """Represents a lookup operation (array/object indexing) in the AST.
10
+
11
+ Lookups access elements from arrays or properties from objects using an index or key.
12
+
13
+ Example:
14
+ # For array[0] or obj.property or obj["key"]
15
+ lookup = Lookup()
16
+ lookup.variable = array_or_obj_node
17
+ lookup.index = index_node
18
+ """
19
+
20
+ @property
21
+ def index(self) -> ASTNode:
22
+ return self.children[0]
23
+
24
+ @index.setter
25
+ def index(self, index: ASTNode) -> None:
26
+ self.add_child(index)
27
+
28
+ @property
29
+ def variable(self) -> ASTNode:
30
+ return self.children[1]
31
+
32
+ @variable.setter
33
+ def variable(self, variable: ASTNode) -> None:
34
+ self.add_child(variable)
35
+
36
+ def is_operand(self) -> bool:
37
+ return True
38
+
39
+ def value(self) -> Any:
40
+ obj = self.variable.value()
41
+ key = self.index.value()
42
+ # Try dict-like access first, then fall back to attribute access for objects
43
+ try:
44
+ return obj[key]
45
+ except (TypeError, KeyError):
46
+ # For objects with attributes (like dataclasses), use getattr
47
+ if hasattr(obj, key):
48
+ return getattr(obj, key)
49
+ raise
@@ -0,0 +1,42 @@
1
+ """Represents a range lookup operation in the AST."""
2
+
3
+ from typing import Any, List
4
+
5
+ from ..ast_node import ASTNode
6
+
7
+
8
+ class RangeLookup(ASTNode):
9
+ """Represents a range lookup (array slicing) operation in the AST."""
10
+
11
+ @property
12
+ def from_(self) -> ASTNode:
13
+ return self.children[0]
14
+
15
+ @from_.setter
16
+ def from_(self, from_: ASTNode) -> None:
17
+ self.add_child(from_)
18
+
19
+ @property
20
+ def to(self) -> ASTNode:
21
+ return self.children[1]
22
+
23
+ @to.setter
24
+ def to(self, to: ASTNode) -> None:
25
+ self.add_child(to)
26
+
27
+ @property
28
+ def variable(self) -> ASTNode:
29
+ return self.children[2]
30
+
31
+ @variable.setter
32
+ def variable(self, variable: ASTNode) -> None:
33
+ self.add_child(variable)
34
+
35
+ def is_operand(self) -> bool:
36
+ return True
37
+
38
+ def value(self) -> List[Any]:
39
+ array = self.variable.value()
40
+ from_val = self.from_.value() or 0
41
+ to_val = self.to.value() or len(array)
42
+ return array[from_val:to_val]
@@ -0,0 +1,57 @@
1
+ """Expressions module for FlowQuery parsing."""
2
+
3
+ from .expression import Expression
4
+ from .boolean import Boolean
5
+ from .number import Number
6
+ from .string import String
7
+ from .identifier import Identifier
8
+ from .reference import Reference
9
+ from .f_string import FString
10
+ from .expression_map import ExpressionMap
11
+ from .operator import (
12
+ Operator,
13
+ Add,
14
+ Subtract,
15
+ Multiply,
16
+ Divide,
17
+ Modulo,
18
+ Power,
19
+ Equals,
20
+ NotEquals,
21
+ GreaterThan,
22
+ LessThan,
23
+ GreaterThanOrEqual,
24
+ LessThanOrEqual,
25
+ And,
26
+ Or,
27
+ Not,
28
+ Is,
29
+ )
30
+
31
+ __all__ = [
32
+ "Expression",
33
+ "Boolean",
34
+ "Number",
35
+ "String",
36
+ "Identifier",
37
+ "Reference",
38
+ "FString",
39
+ "ExpressionMap",
40
+ "Operator",
41
+ "Add",
42
+ "Subtract",
43
+ "Multiply",
44
+ "Divide",
45
+ "Modulo",
46
+ "Power",
47
+ "Equals",
48
+ "NotEquals",
49
+ "GreaterThan",
50
+ "LessThan",
51
+ "GreaterThanOrEqual",
52
+ "LessThanOrEqual",
53
+ "And",
54
+ "Or",
55
+ "Not",
56
+ "Is",
57
+ ]
@@ -0,0 +1,20 @@
1
+ """Represents a boolean literal in the AST."""
2
+
3
+ from ..ast_node import ASTNode
4
+
5
+
6
+ class Boolean(ASTNode):
7
+ """Represents a boolean literal in the AST."""
8
+
9
+ def __init__(self, value: str):
10
+ super().__init__()
11
+ _value = value.upper()
12
+ if _value == "TRUE":
13
+ self._value = True
14
+ elif _value == "FALSE":
15
+ self._value = False
16
+ else:
17
+ raise ValueError(f"Invalid boolean value: {value}")
18
+
19
+ def value(self) -> bool:
20
+ return self._value
@@ -0,0 +1,138 @@
1
+ """Represents an expression in the FlowQuery AST."""
2
+
3
+ from typing import Any, List, Optional, Generator, TYPE_CHECKING
4
+
5
+ from ..ast_node import ASTNode
6
+
7
+ if TYPE_CHECKING:
8
+ from ..functions.aggregate_function import AggregateFunction
9
+ from ...graph.pattern_expression import PatternExpression
10
+
11
+
12
+ class Expression(ASTNode):
13
+ """Represents an expression in the FlowQuery AST.
14
+
15
+ Expressions are built using the Shunting Yard algorithm to handle operator
16
+ precedence and associativity. They can contain operands (numbers, strings, identifiers)
17
+ and operators (arithmetic, logical, comparison).
18
+
19
+ Example:
20
+ expr = Expression()
21
+ expr.add_node(number_node)
22
+ expr.add_node(plus_operator)
23
+ expr.add_node(another_number_node)
24
+ expr.finish()
25
+ """
26
+
27
+ def __init__(self):
28
+ super().__init__()
29
+ self._operators: List[ASTNode] = []
30
+ self._output: List[ASTNode] = []
31
+ self._alias: Optional[str] = None
32
+ self._overridden: Any = None
33
+ self._reducers: Optional[List['AggregateFunction']] = None
34
+ self._patterns: Optional[List['PatternExpression']] = None
35
+
36
+ def add_node(self, node: ASTNode) -> None:
37
+ """Adds a node (operand or operator) to the expression.
38
+
39
+ Uses the Shunting Yard algorithm to maintain correct operator precedence.
40
+
41
+ Args:
42
+ node: The AST node to add (operand or operator)
43
+ """
44
+ # Implements the Shunting Yard algorithm
45
+ if node.is_operand():
46
+ self._output.append(node)
47
+ elif node.is_operator():
48
+ operator1 = node
49
+ while len(self._operators) > 0:
50
+ operator2 = self._operators[-1]
51
+ if (operator2.precedence > operator1.precedence or
52
+ (operator2.precedence == operator1.precedence and operator1.left_associative)):
53
+ self._output.append(operator2)
54
+ self._operators.pop()
55
+ else:
56
+ break
57
+ self._operators.append(operator1)
58
+
59
+ def finish(self) -> None:
60
+ """Finalizes the expression by converting it to a tree structure.
61
+
62
+ Should be called after all nodes have been added.
63
+ """
64
+ while self._operators:
65
+ self._output.append(self._operators.pop())
66
+ self.add_child(self._to_tree())
67
+
68
+ def _to_tree(self) -> ASTNode:
69
+ if not self._output:
70
+ return ASTNode()
71
+ node = self._output.pop()
72
+ if node.is_operator():
73
+ rhs = self._to_tree()
74
+ lhs = self._to_tree()
75
+ node.add_child(lhs)
76
+ node.add_child(rhs)
77
+ return node
78
+
79
+ def nodes_added(self) -> bool:
80
+ return len(self._operators) > 0 or len(self._output) > 0
81
+
82
+ def value(self) -> Any:
83
+ if self._overridden is not None:
84
+ return self._overridden
85
+ if self.child_count() != 1:
86
+ raise ValueError("Expected one child")
87
+ return self.children[0].value()
88
+
89
+ def set_alias(self, alias: str) -> None:
90
+ self._alias = alias
91
+
92
+ @property
93
+ def alias(self) -> Optional[str]:
94
+ from .reference import Reference
95
+ if isinstance(self.first_child(), Reference) and self._alias is None:
96
+ return self.first_child().identifier
97
+ return self._alias
98
+
99
+ @alias.setter
100
+ def alias(self, value: str) -> None:
101
+ self._alias = value
102
+
103
+ def __str__(self) -> str:
104
+ if self._alias is not None:
105
+ return f"Expression ({self._alias})"
106
+ return "Expression"
107
+
108
+ def reducers(self) -> List['AggregateFunction']:
109
+ if self._reducers is None:
110
+ from ..functions.aggregate_function import AggregateFunction
111
+ self._reducers = list(self._extract(self, AggregateFunction))
112
+ return self._reducers
113
+
114
+ def patterns(self) -> List['PatternExpression']:
115
+ if self._patterns is None:
116
+ from ...graph.pattern_expression import PatternExpression
117
+ self._patterns = list(self._extract(self, PatternExpression))
118
+ return self._patterns
119
+
120
+ def _extract(self, node: ASTNode, of_type: type) -> Generator[Any, None, None]:
121
+ if isinstance(node, of_type):
122
+ yield node
123
+ for child in node.get_children():
124
+ yield from self._extract(child, of_type)
125
+
126
+ def mappable(self) -> bool:
127
+ return len(self.reducers()) == 0
128
+
129
+ def has_reducers(self) -> bool:
130
+ return len(self.reducers()) > 0
131
+
132
+ @property
133
+ def overridden(self) -> Any:
134
+ return self._overridden
135
+
136
+ @overridden.setter
137
+ def overridden(self, value: Any) -> None:
138
+ self._overridden = value