rawsql-ts 0.1.1-beta.1 → 0.1.1-beta.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 (199) hide show
  1. package/dist/esm/index.js +17 -0
  2. package/dist/esm/index.js.map +1 -0
  3. package/dist/esm/models/BinarySelectQuery.js +137 -0
  4. package/dist/esm/models/BinarySelectQuery.js.map +1 -0
  5. package/dist/esm/models/Clause.js +289 -0
  6. package/dist/esm/models/Clause.js.map +1 -0
  7. package/dist/esm/models/KeywordTrie.js +48 -0
  8. package/dist/esm/models/KeywordTrie.js.map +1 -0
  9. package/dist/esm/models/Lexeme.js +18 -0
  10. package/dist/esm/models/Lexeme.js.map +1 -0
  11. package/dist/esm/models/SelectQuery.js +5 -0
  12. package/dist/esm/models/SelectQuery.js.map +1 -0
  13. package/dist/esm/models/SimpleSelectQuery.js +288 -0
  14. package/dist/esm/models/SimpleSelectQuery.js.map +1 -0
  15. package/dist/esm/models/SqlComponent.js +22 -0
  16. package/dist/esm/models/SqlComponent.js.map +1 -0
  17. package/dist/esm/models/ValueComponent.js +223 -0
  18. package/dist/esm/models/ValueComponent.js.map +1 -0
  19. package/dist/esm/models/ValuesQuery.js +12 -0
  20. package/dist/esm/models/ValuesQuery.js.map +1 -0
  21. package/dist/esm/parsers/CommandExpressionParser.js +120 -0
  22. package/dist/esm/parsers/CommandExpressionParser.js.map +1 -0
  23. package/dist/esm/parsers/CommonTableParser.js +58 -0
  24. package/dist/esm/parsers/CommonTableParser.js.map +1 -0
  25. package/dist/esm/parsers/ForClauseParser.js +54 -0
  26. package/dist/esm/parsers/ForClauseParser.js.map +1 -0
  27. package/dist/esm/parsers/FromClauseParser.js +43 -0
  28. package/dist/esm/parsers/FromClauseParser.js.map +1 -0
  29. package/dist/esm/parsers/FunctionExpressionParser.js +174 -0
  30. package/dist/esm/parsers/FunctionExpressionParser.js.map +1 -0
  31. package/dist/esm/parsers/GroupByParser.js +54 -0
  32. package/dist/esm/parsers/GroupByParser.js.map +1 -0
  33. package/dist/esm/parsers/HavingParser.js +32 -0
  34. package/dist/esm/parsers/HavingParser.js.map +1 -0
  35. package/dist/esm/parsers/IdentifierParser.js +35 -0
  36. package/dist/esm/parsers/IdentifierParser.js.map +1 -0
  37. package/dist/esm/parsers/JoinClauseParser.js +101 -0
  38. package/dist/esm/parsers/JoinClauseParser.js.map +1 -0
  39. package/dist/esm/parsers/KeywordParser.js +87 -0
  40. package/dist/esm/parsers/KeywordParser.js.map +1 -0
  41. package/dist/esm/parsers/LimitClauseParser.js +46 -0
  42. package/dist/esm/parsers/LimitClauseParser.js.map +1 -0
  43. package/dist/esm/parsers/LiteralParser.js +34 -0
  44. package/dist/esm/parsers/LiteralParser.js.map +1 -0
  45. package/dist/esm/parsers/OrderByClauseParser.js +73 -0
  46. package/dist/esm/parsers/OrderByClauseParser.js.map +1 -0
  47. package/dist/esm/parsers/OverExpressionParser.js +40 -0
  48. package/dist/esm/parsers/OverExpressionParser.js.map +1 -0
  49. package/dist/esm/parsers/ParameterExpressionParser.js +11 -0
  50. package/dist/esm/parsers/ParameterExpressionParser.js.map +1 -0
  51. package/dist/esm/parsers/ParenExpressionParser.js +29 -0
  52. package/dist/esm/parsers/ParenExpressionParser.js.map +1 -0
  53. package/dist/esm/parsers/PartitionByParser.js +49 -0
  54. package/dist/esm/parsers/PartitionByParser.js.map +1 -0
  55. package/dist/esm/parsers/SelectClauseParser.js +80 -0
  56. package/dist/esm/parsers/SelectClauseParser.js.map +1 -0
  57. package/dist/esm/parsers/SelectQueryParser.js +149 -0
  58. package/dist/esm/parsers/SelectQueryParser.js.map +1 -0
  59. package/dist/esm/parsers/SourceAliasExpressionParser.js +45 -0
  60. package/dist/esm/parsers/SourceAliasExpressionParser.js.map +1 -0
  61. package/dist/esm/parsers/SourceExpressionParser.js +31 -0
  62. package/dist/esm/parsers/SourceExpressionParser.js.map +1 -0
  63. package/dist/esm/parsers/SourceParser.js +115 -0
  64. package/dist/esm/parsers/SourceParser.js.map +1 -0
  65. package/dist/esm/parsers/SqlTokenizer.js +170 -0
  66. package/dist/esm/parsers/SqlTokenizer.js.map +1 -0
  67. package/dist/esm/parsers/StringSpecifierExpressionParser.js +18 -0
  68. package/dist/esm/parsers/StringSpecifierExpressionParser.js.map +1 -0
  69. package/dist/esm/parsers/UnaryExpressionParser.js +26 -0
  70. package/dist/esm/parsers/UnaryExpressionParser.js.map +1 -0
  71. package/dist/esm/parsers/ValueParser.js +132 -0
  72. package/dist/esm/parsers/ValueParser.js.map +1 -0
  73. package/dist/esm/parsers/ValuesQueryParser.js +82 -0
  74. package/dist/esm/parsers/ValuesQueryParser.js.map +1 -0
  75. package/dist/esm/parsers/WhereClauseParser.js +32 -0
  76. package/dist/esm/parsers/WhereClauseParser.js.map +1 -0
  77. package/dist/esm/parsers/WindowClauseParser.js +41 -0
  78. package/dist/esm/parsers/WindowClauseParser.js.map +1 -0
  79. package/dist/esm/parsers/WindowExpressionParser.js +159 -0
  80. package/dist/esm/parsers/WindowExpressionParser.js.map +1 -0
  81. package/dist/esm/parsers/WithClauseParser.js +53 -0
  82. package/dist/esm/parsers/WithClauseParser.js.map +1 -0
  83. package/dist/esm/tokenReaders/BaseTokenReader.js +78 -0
  84. package/dist/esm/tokenReaders/BaseTokenReader.js.map +1 -0
  85. package/dist/esm/tokenReaders/CommandTokenReader.js +141 -0
  86. package/dist/esm/tokenReaders/CommandTokenReader.js.map +1 -0
  87. package/dist/esm/tokenReaders/FunctionTokenReader.js +41 -0
  88. package/dist/esm/tokenReaders/FunctionTokenReader.js.map +1 -0
  89. package/dist/esm/tokenReaders/IdentifierTokenReader.js +66 -0
  90. package/dist/esm/tokenReaders/IdentifierTokenReader.js.map +1 -0
  91. package/dist/esm/tokenReaders/LiteralTokenReader.js +185 -0
  92. package/dist/esm/tokenReaders/LiteralTokenReader.js.map +1 -0
  93. package/dist/esm/tokenReaders/OperatorTokenReader.js +94 -0
  94. package/dist/esm/tokenReaders/OperatorTokenReader.js.map +1 -0
  95. package/dist/esm/tokenReaders/ParameterTokenReader.js +40 -0
  96. package/dist/esm/tokenReaders/ParameterTokenReader.js.map +1 -0
  97. package/dist/esm/tokenReaders/StringSpecifierTokenReader.js +27 -0
  98. package/dist/esm/tokenReaders/StringSpecifierTokenReader.js.map +1 -0
  99. package/dist/esm/tokenReaders/SymbolTokenReader.js +31 -0
  100. package/dist/esm/tokenReaders/SymbolTokenReader.js.map +1 -0
  101. package/dist/esm/tokenReaders/TokenReaderManager.js +106 -0
  102. package/dist/esm/tokenReaders/TokenReaderManager.js.map +1 -0
  103. package/dist/esm/tokenReaders/TypeTokenReader.js +55 -0
  104. package/dist/esm/tokenReaders/TypeTokenReader.js.map +1 -0
  105. package/dist/esm/transformers/CTEBuilder.js +184 -0
  106. package/dist/esm/transformers/CTEBuilder.js.map +1 -0
  107. package/dist/esm/transformers/CTECollector.js +384 -0
  108. package/dist/esm/transformers/CTECollector.js.map +1 -0
  109. package/dist/esm/transformers/CTEDisabler.js +321 -0
  110. package/dist/esm/transformers/CTEDisabler.js.map +1 -0
  111. package/dist/esm/transformers/CTEInjector.js +79 -0
  112. package/dist/esm/transformers/CTEInjector.js.map +1 -0
  113. package/dist/esm/transformers/CTENormalizer.js +42 -0
  114. package/dist/esm/transformers/CTENormalizer.js.map +1 -0
  115. package/dist/esm/transformers/Formatter.js +463 -0
  116. package/dist/esm/transformers/Formatter.js.map +1 -0
  117. package/dist/esm/transformers/QueryConverter.js +115 -0
  118. package/dist/esm/transformers/QueryConverter.js.map +1 -0
  119. package/dist/esm/transformers/SelectValueCollector.js +245 -0
  120. package/dist/esm/transformers/SelectValueCollector.js.map +1 -0
  121. package/dist/esm/transformers/SelectableColumnCollector.js +318 -0
  122. package/dist/esm/transformers/SelectableColumnCollector.js.map +1 -0
  123. package/dist/esm/transformers/TableColumnResolver.js +2 -0
  124. package/dist/esm/transformers/TableColumnResolver.js.map +1 -0
  125. package/dist/esm/transformers/TableSourceCollector.js +380 -0
  126. package/dist/esm/transformers/TableSourceCollector.js.map +1 -0
  127. package/dist/esm/transformers/UpstreamSelectQueryFinder.js +125 -0
  128. package/dist/esm/transformers/UpstreamSelectQueryFinder.js.map +1 -0
  129. package/dist/esm/types/index.d.ts +14 -0
  130. package/dist/esm/types/models/BinarySelectQuery.d.ts +91 -0
  131. package/dist/esm/types/models/Clause.d.ts +189 -0
  132. package/dist/esm/types/models/KeywordTrie.d.ts +11 -0
  133. package/dist/esm/types/models/Lexeme.d.ts +25 -0
  134. package/dist/esm/types/models/SelectQuery.d.ts +5 -0
  135. package/dist/esm/types/models/SimpleSelectQuery.d.ts +167 -0
  136. package/dist/esm/types/models/SqlComponent.d.ts +18 -0
  137. package/dist/esm/types/models/ValueComponent.d.ts +158 -0
  138. package/dist/esm/types/models/ValuesQuery.d.ts +10 -0
  139. package/dist/esm/types/parsers/CommandExpressionParser.d.ts +15 -0
  140. package/dist/esm/types/parsers/CommonTableParser.d.ts +9 -0
  141. package/dist/esm/types/parsers/ForClauseParser.d.ts +9 -0
  142. package/dist/esm/types/parsers/FromClauseParser.d.ts +9 -0
  143. package/dist/esm/types/parsers/FunctionExpressionParser.d.ts +22 -0
  144. package/dist/esm/types/parsers/GroupByParser.d.ts +10 -0
  145. package/dist/esm/types/parsers/HavingParser.d.ts +9 -0
  146. package/dist/esm/types/parsers/IdentifierParser.d.ts +8 -0
  147. package/dist/esm/types/parsers/JoinClauseParser.d.ts +14 -0
  148. package/dist/esm/types/parsers/KeywordParser.d.ts +17 -0
  149. package/dist/esm/types/parsers/LimitClauseParser.d.ts +9 -0
  150. package/dist/esm/types/parsers/LiteralParser.d.ts +8 -0
  151. package/dist/esm/types/parsers/OrderByClauseParser.d.ts +10 -0
  152. package/dist/esm/types/parsers/OverExpressionParser.d.ts +9 -0
  153. package/dist/esm/types/parsers/ParameterExpressionParser.d.ts +8 -0
  154. package/dist/esm/types/parsers/ParenExpressionParser.d.ts +8 -0
  155. package/dist/esm/types/parsers/PartitionByParser.d.ts +9 -0
  156. package/dist/esm/types/parsers/SelectClauseParser.d.ts +10 -0
  157. package/dist/esm/types/parsers/SelectQueryParser.d.ts +13 -0
  158. package/dist/esm/types/parsers/SourceAliasExpressionParser.d.ts +8 -0
  159. package/dist/esm/types/parsers/SourceExpressionParser.d.ts +8 -0
  160. package/dist/esm/types/parsers/SourceParser.d.ts +13 -0
  161. package/dist/esm/types/parsers/SqlTokenizer.d.ts +64 -0
  162. package/dist/esm/types/parsers/StringSpecifierExpressionParser.d.ts +8 -0
  163. package/dist/esm/types/parsers/UnaryExpressionParser.d.ts +8 -0
  164. package/dist/esm/types/parsers/ValueParser.d.ts +14 -0
  165. package/dist/esm/types/parsers/ValuesQueryParser.d.ts +10 -0
  166. package/dist/esm/types/parsers/WhereClauseParser.d.ts +9 -0
  167. package/dist/esm/types/parsers/WindowClauseParser.d.ts +9 -0
  168. package/dist/esm/types/parsers/WindowExpressionParser.d.ts +12 -0
  169. package/dist/esm/types/parsers/WithClauseParser.d.ts +9 -0
  170. package/dist/esm/types/tokenReaders/BaseTokenReader.d.ts +43 -0
  171. package/dist/esm/types/tokenReaders/CommandTokenReader.d.ts +7 -0
  172. package/dist/esm/types/tokenReaders/FunctionTokenReader.d.ts +11 -0
  173. package/dist/esm/types/tokenReaders/IdentifierTokenReader.d.ts +15 -0
  174. package/dist/esm/types/tokenReaders/LiteralTokenReader.d.ts +23 -0
  175. package/dist/esm/types/tokenReaders/OperatorTokenReader.d.ts +5 -0
  176. package/dist/esm/types/tokenReaders/ParameterTokenReader.d.ts +11 -0
  177. package/dist/esm/types/tokenReaders/StringSpecifierTokenReader.d.ts +8 -0
  178. package/dist/esm/types/tokenReaders/SymbolTokenReader.d.ts +12 -0
  179. package/dist/esm/types/tokenReaders/TokenReaderManager.d.ts +53 -0
  180. package/dist/esm/types/tokenReaders/TypeTokenReader.d.ts +11 -0
  181. package/dist/esm/types/transformers/CTEBuilder.d.ts +52 -0
  182. package/dist/esm/types/transformers/CTECollector.d.ts +82 -0
  183. package/dist/esm/types/transformers/CTEDisabler.d.ts +77 -0
  184. package/dist/esm/types/transformers/CTEInjector.d.ts +40 -0
  185. package/dist/esm/types/transformers/CTENormalizer.d.ts +25 -0
  186. package/dist/esm/types/transformers/Formatter.d.ts +82 -0
  187. package/dist/esm/types/transformers/QueryConverter.d.ts +41 -0
  188. package/dist/esm/types/transformers/SelectValueCollector.d.ts +60 -0
  189. package/dist/esm/types/transformers/SelectableColumnCollector.d.ts +72 -0
  190. package/dist/esm/types/transformers/TableColumnResolver.d.ts +10 -0
  191. package/dist/esm/types/transformers/TableSourceCollector.d.ts +92 -0
  192. package/dist/esm/types/transformers/UpstreamSelectQueryFinder.d.ts +27 -0
  193. package/dist/esm/types/utils/charLookupTable.d.ts +11 -0
  194. package/dist/esm/types/utils/stringUtils.d.ts +43 -0
  195. package/dist/esm/utils/charLookupTable.js +69 -0
  196. package/dist/esm/utils/charLookupTable.js.map +1 -0
  197. package/dist/esm/utils/stringUtils.js +164 -0
  198. package/dist/esm/utils/stringUtils.js.map +1 -0
  199. package/package.json +1 -1
@@ -0,0 +1,132 @@
1
+ import { TokenType } from "../models/Lexeme";
2
+ import { ColumnReference, ValueList } from "../models/ValueComponent";
3
+ import { SqlTokenizer } from "./SqlTokenizer";
4
+ import { IdentifierParser } from "./IdentifierParser";
5
+ import { LiteralParser } from "./LiteralParser";
6
+ import { ParenExpressionParser } from "./ParenExpressionParser";
7
+ import { UnaryExpressionParser } from "./UnaryExpressionParser";
8
+ import { ParameterExpressionParser } from "./ParameterExpressionParser";
9
+ import { StringSpecifierExpressionParser } from "./StringSpecifierExpressionParser";
10
+ import { CommandExpressionParser } from "./CommandExpressionParser";
11
+ import { FunctionExpressionParser } from "./FunctionExpressionParser";
12
+ export class ValueParser {
13
+ // Parse SQL string to AST (was: parse)
14
+ static parse(query) {
15
+ const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
16
+ const lexemes = tokenizer.readLexmes(); // Get tokens
17
+ // Parse
18
+ const result = this.parseFromLexeme(lexemes, 0);
19
+ // Error if there are remaining tokens
20
+ if (result.newIndex < lexemes.length) {
21
+ throw new Error(`Unexpected token at index ${result.newIndex}: ${lexemes[result.newIndex].value}`);
22
+ }
23
+ return result.value;
24
+ }
25
+ // Parse from lexeme array (was: parse)
26
+ static parseFromLexeme(lexemes, index, allowAndOperator = true) {
27
+ let idx = index;
28
+ // support comments
29
+ const comment = lexemes[index].comments;
30
+ const left = this.parseItem(lexemes, index);
31
+ left.value.comments = comment;
32
+ idx = left.newIndex;
33
+ while (idx < lexemes.length && lexemes[idx].type === TokenType.Operator) {
34
+ const binaryResult = FunctionExpressionParser.tryParseBinaryExpression(lexemes, idx, left.value, allowAndOperator);
35
+ if (binaryResult) {
36
+ left.value = binaryResult.value;
37
+ idx = binaryResult.newIndex;
38
+ }
39
+ else {
40
+ // If no binary expression is found, break the loop
41
+ break;
42
+ }
43
+ }
44
+ return { value: left.value, newIndex: idx };
45
+ }
46
+ static parseItem(lexemes, index) {
47
+ let idx = index;
48
+ // Range check
49
+ if (idx >= lexemes.length) {
50
+ throw new Error(`Unexpected end of lexemes at index ${index}`);
51
+ }
52
+ const current = lexemes[idx];
53
+ if (current.type === TokenType.Identifier) {
54
+ return IdentifierParser.parseFromLexeme(lexemes, idx);
55
+ }
56
+ else if (current.type === TokenType.Literal) {
57
+ return LiteralParser.parseFromLexeme(lexemes, idx);
58
+ }
59
+ else if (current.type === TokenType.OpenParen) {
60
+ return ParenExpressionParser.parseFromLexeme(lexemes, idx);
61
+ }
62
+ else if (current.type === TokenType.Function) {
63
+ return FunctionExpressionParser.parseFromLexeme(lexemes, idx);
64
+ }
65
+ else if (current.type === TokenType.Operator) {
66
+ return UnaryExpressionParser.parseFromLexeme(lexemes, idx);
67
+ }
68
+ else if (current.type === TokenType.Parameter) {
69
+ return ParameterExpressionParser.parseFromLexeme(lexemes, idx);
70
+ }
71
+ else if (current.type === TokenType.StringSpecifier) {
72
+ return StringSpecifierExpressionParser.parseFromLexeme(lexemes, idx);
73
+ }
74
+ else if (current.type === TokenType.Command) {
75
+ return CommandExpressionParser.parseFromLexeme(lexemes, idx);
76
+ }
77
+ throw new Error(`Invalid lexeme. index: ${idx}, type: ${lexemes[idx].type}, value: ${lexemes[idx].value}`);
78
+ }
79
+ static parseArgument(openToken, closeToken, lexemes, index) {
80
+ let idx = index;
81
+ const args = [];
82
+ // Check for opening parenthesis
83
+ if (idx < lexemes.length && lexemes[idx].type === openToken) {
84
+ idx++;
85
+ if (idx < lexemes.length && lexemes[idx].type === closeToken) {
86
+ // If there are no arguments, return an empty ValueList
87
+ idx++;
88
+ return { value: new ValueList([]), newIndex: idx };
89
+ }
90
+ // If the next element is `*`, treat `*` as an Identifier
91
+ if (idx < lexemes.length && lexemes[idx].value === "*") {
92
+ const wildcard = new ColumnReference(null, "*");
93
+ idx++;
94
+ // The next element must be closeToken
95
+ if (idx < lexemes.length && lexemes[idx].type === closeToken) {
96
+ idx++;
97
+ return { value: wildcard, newIndex: idx };
98
+ }
99
+ else {
100
+ throw new Error(`Expected closing parenthesis at index ${idx}`);
101
+ }
102
+ }
103
+ // Parse the value inside
104
+ const result = this.parseFromLexeme(lexemes, idx);
105
+ idx = result.newIndex;
106
+ args.push(result.value);
107
+ // Continue reading if the next element is a comma
108
+ while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
109
+ idx++;
110
+ const argResult = this.parseFromLexeme(lexemes, idx);
111
+ idx = argResult.newIndex;
112
+ args.push(argResult.value);
113
+ }
114
+ // Check for closing parenthesis
115
+ if (idx < lexemes.length && lexemes[idx].type === closeToken) {
116
+ idx++;
117
+ if (args.length === 1) {
118
+ // Return as is if there is only one argument
119
+ return { value: args[0], newIndex: idx };
120
+ }
121
+ // Create ValueCollection if there are multiple arguments
122
+ const value = new ValueList(args);
123
+ return { value, newIndex: idx };
124
+ }
125
+ else {
126
+ throw new Error(`Missing closing parenthesis at index ${idx}`);
127
+ }
128
+ }
129
+ throw new Error(`Expected opening parenthesis at index ${index}`);
130
+ }
131
+ }
132
+ //# sourceMappingURL=ValueParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValueParser.js","sourceRoot":"","sources":["../../../src/parsers/ValueParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { TokenType } from "../models/Lexeme";
2
+ import { ValuesQuery } from "../models/SelectQuery";
3
+ import { TupleExpression } from "../models/ValueComponent";
4
+ import { SqlTokenizer } from "./SqlTokenizer";
5
+ import { ValueParser } from "./ValueParser";
6
+ export class ValuesQueryParser {
7
+ static parse(query) {
8
+ const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
9
+ const lexemes = tokenizer.readLexmes(); // Get tokens
10
+ // Parse
11
+ const result = this.parseFromLexeme(lexemes, 0);
12
+ // Error if there are remaining tokens
13
+ if (result.newIndex < lexemes.length) {
14
+ throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The VALUES clause is complete but there are additional tokens.`);
15
+ }
16
+ return result.value;
17
+ }
18
+ static parseFromLexeme(lexemes, index) {
19
+ let idx = index;
20
+ if (lexemes[idx].value.toLowerCase() !== 'values') {
21
+ throw new Error(`Syntax error at position ${idx}: Expected 'VALUES' keyword but found "${lexemes[idx].value}". VALUES clauses must start with the VALUES keyword.`);
22
+ }
23
+ idx++;
24
+ if (idx >= lexemes.length) {
25
+ throw new Error(`Syntax error: Unexpected end of input after 'VALUES' keyword. The VALUES clause requires at least one tuple expression.`);
26
+ }
27
+ const tuples = [];
28
+ // Parse the first tuple
29
+ const firstTuple = this.parseTuple(lexemes, idx);
30
+ tuples.push(firstTuple.value);
31
+ idx = firstTuple.newIndex;
32
+ // Parse additional tuples if they exist
33
+ while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
34
+ idx++; // Skip comma
35
+ const tuple = this.parseTuple(lexemes, idx);
36
+ tuples.push(tuple.value);
37
+ idx = tuple.newIndex;
38
+ }
39
+ const query = new ValuesQuery(tuples);
40
+ return { value: query, newIndex: idx };
41
+ }
42
+ static parseTuple(lexemes, index) {
43
+ let idx = index;
44
+ // Check for opening parenthesis
45
+ if (idx >= lexemes.length || lexemes[idx].type !== TokenType.OpenParen) {
46
+ throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis but found "${idx < lexemes.length ? lexemes[idx].value : "end of input"}". Tuple expressions in VALUES clause must be enclosed in parentheses.`);
47
+ }
48
+ idx++;
49
+ // Parse values inside the tuple
50
+ const values = [];
51
+ // Parse first value
52
+ if (idx >= lexemes.length) {
53
+ throw new Error(`Syntax error: Unexpected end of input after opening parenthesis in tuple expression.`);
54
+ }
55
+ // Check for empty tuple case
56
+ if (lexemes[idx].type === TokenType.CloseParen) {
57
+ idx++; // Skip closing parenthesis
58
+ return { value: new TupleExpression([]), newIndex: idx };
59
+ }
60
+ // Parse the first value
61
+ const firstValue = ValueParser.parseFromLexeme(lexemes, idx);
62
+ values.push(firstValue.value);
63
+ idx = firstValue.newIndex;
64
+ // Parse additional values
65
+ while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
66
+ idx++; // Skip comma
67
+ if (idx >= lexemes.length) {
68
+ throw new Error(`Syntax error: Unexpected end of input after comma in tuple expression.`);
69
+ }
70
+ const value = ValueParser.parseFromLexeme(lexemes, idx);
71
+ values.push(value.value);
72
+ idx = value.newIndex;
73
+ }
74
+ // Check for closing parenthesis
75
+ if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {
76
+ throw new Error(`Syntax error at position ${idx}: Expected closing parenthesis but found "${idx < lexemes.length ? lexemes[idx].value : "end of input"}". Tuple expressions in VALUES clause must be enclosed in parentheses.`);
77
+ }
78
+ idx++; // Skip closing parenthesis
79
+ return { value: new TupleExpression(values), newIndex: idx };
80
+ }
81
+ }
82
+ //# sourceMappingURL=ValuesQueryParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValuesQueryParser.js","sourceRoot":"","sources":["../../../src/parsers/ValuesQueryParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { WhereClause } from "../models/Clause";
2
+ import { SqlTokenizer } from "./SqlTokenizer";
3
+ import { ValueParser } from "./ValueParser";
4
+ export class WhereClauseParser {
5
+ // Parse SQL string to AST (was: parse)
6
+ static parse(query) {
7
+ const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
8
+ const lexemes = tokenizer.readLexmes(); // Get tokens
9
+ // Parse
10
+ const result = this.parseFromLexeme(lexemes, 0);
11
+ // Error if there are remaining tokens
12
+ if (result.newIndex < lexemes.length) {
13
+ throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The WHERE clause is complete but there are additional tokens.`);
14
+ }
15
+ return result.value;
16
+ }
17
+ // Parse from lexeme array (was: parse)
18
+ static parseFromLexeme(lexemes, index) {
19
+ let idx = index;
20
+ if (lexemes[idx].value !== 'where') {
21
+ throw new Error(`Syntax error at position ${idx}: Expected 'WHERE' keyword but found "${lexemes[idx].value}". WHERE clauses must start with the WHERE keyword.`);
22
+ }
23
+ idx++;
24
+ if (idx >= lexemes.length) {
25
+ throw new Error(`Syntax error: Unexpected end of input after 'WHERE' keyword. The WHERE clause requires a condition expression.`);
26
+ }
27
+ const item = ValueParser.parseFromLexeme(lexemes, idx);
28
+ const clause = new WhereClause(item.value);
29
+ return { value: clause, newIndex: item.newIndex };
30
+ }
31
+ }
32
+ //# sourceMappingURL=WhereClauseParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WhereClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/WhereClauseParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,OAAO,iBAAiB;IAC1B,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB;QAClE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,aAAa;QAErD,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,iEAAiE,CAAC,CAAC;QACxL,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,yCAAyC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,qDAAqD,CAAC,CAAC;QACrK,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,gHAAgH,CAAC,CAAC;QACtI,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IACtD,CAAC;CACJ"}
@@ -0,0 +1,41 @@
1
+ import { WindowFrameClause } from "../models/Clause";
2
+ import { TokenType } from "../models/Lexeme";
3
+ import { SqlTokenizer } from "./SqlTokenizer";
4
+ import { WindowExpressionParser } from "./WindowExpressionParser";
5
+ export class WindowClauseParser {
6
+ // Parse SQL string to AST (was: parse)
7
+ static parse(query) {
8
+ const tokenizer = new SqlTokenizer(query);
9
+ const lexemes = tokenizer.readLexmes();
10
+ // Parse
11
+ const result = this.parseFromLexeme(lexemes, 0);
12
+ // Error if there are remaining tokens
13
+ if (result.newIndex < lexemes.length) {
14
+ throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The WINDOW clause is complete but there are additional tokens.`);
15
+ }
16
+ return result.value;
17
+ }
18
+ // Parse from lexeme array (was: parse)
19
+ static parseFromLexeme(lexemes, index) {
20
+ let idx = index;
21
+ if (lexemes[idx].value !== 'window') {
22
+ throw new Error(`Syntax error at position ${idx}: Expected 'WINDOW' keyword but found "${lexemes[idx].value}". WINDOW clauses must start with the WINDOW keyword.`);
23
+ }
24
+ idx++;
25
+ if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Identifier) {
26
+ throw new Error(`Syntax error: Expected window name after 'WINDOW' keyword.`);
27
+ }
28
+ // Get the window name
29
+ const name = lexemes[idx].value;
30
+ idx++;
31
+ if (idx >= lexemes.length || lexemes[idx].value !== 'as') {
32
+ throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after window name.`);
33
+ }
34
+ idx++;
35
+ const expr = WindowExpressionParser.parseFromLexeme(lexemes, idx);
36
+ idx = expr.newIndex;
37
+ const windowFrame = new WindowFrameClause(name, expr.value);
38
+ return { value: windowFrame, newIndex: idx };
39
+ }
40
+ }
41
+ //# sourceMappingURL=WindowClauseParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WindowClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/WindowClauseParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,OAAO,kBAAkB;IAC3B,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;QAEvC,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,kEAAkE,CAAC,CAAC;QACzL,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,0CAA0C,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,uDAAuD,CAAC,CAAC;QACxK,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAClF,CAAC;QAED,sBAAsB;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QAChC,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,4CAA4C,CAAC,CAAC;QACjG,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,MAAM,IAAI,GAAG,sBAAsB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClE,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEpB,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IACjD,CAAC;CACJ"}
@@ -0,0 +1,159 @@
1
+ import { TokenType } from "../models/Lexeme";
2
+ import { WindowFrameBound, WindowFrameBoundaryValue, WindowFrameExpression, WindowFrameSpec, WindowFrameType, WindowFrameBoundStatic } from "../models/ValueComponent";
3
+ import { OrderByClauseParser } from "./OrderByClauseParser";
4
+ import { PartitionByParser } from "./PartitionByParser";
5
+ import { SqlTokenizer } from "./SqlTokenizer";
6
+ import { ValueParser } from "./ValueParser";
7
+ export class WindowExpressionParser {
8
+ // Parse SQL string to AST (was: parse)
9
+ static parse(query) {
10
+ const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
11
+ const lexemes = tokenizer.readLexmes(); // Get tokens
12
+ // Parse
13
+ const result = this.parseFromLexeme(lexemes, 0);
14
+ // Error if there are remaining tokens
15
+ if (result.newIndex < lexemes.length) {
16
+ throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The window frame expression is complete but there are additional tokens.`);
17
+ }
18
+ return result.value;
19
+ }
20
+ // Parse from lexeme array (was: parse)
21
+ static parseFromLexeme(lexemes, index) {
22
+ let idx = index;
23
+ if (lexemes[idx].type !== TokenType.OpenParen) {
24
+ throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis '(' but found "${lexemes[idx].value}".`);
25
+ }
26
+ idx++;
27
+ let partition = null;
28
+ let order = null;
29
+ let frameSpec = null;
30
+ if (idx < lexemes.length && lexemes[idx].value === 'partition by') {
31
+ const partitionResult = PartitionByParser.parseFromLexeme(lexemes, idx);
32
+ partition = partitionResult.value;
33
+ idx = partitionResult.newIndex;
34
+ }
35
+ if (idx < lexemes.length && lexemes[idx].value === 'order by') {
36
+ const orderResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);
37
+ order = orderResult.value;
38
+ idx = orderResult.newIndex;
39
+ }
40
+ // Parse frame clause (ROWS/RANGE/GROUPS)
41
+ if (idx < lexemes.length && this.isFrameTypeKeyword(lexemes[idx].value)) {
42
+ const frameSpecResult = this.parseFrameSpec(lexemes, idx);
43
+ frameSpec = frameSpecResult.value;
44
+ idx = frameSpecResult.newIndex;
45
+ }
46
+ if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {
47
+ throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for window frame. Each opening parenthesis must have a matching closing parenthesis.`);
48
+ }
49
+ // Read close paren
50
+ idx++;
51
+ return { value: new WindowFrameExpression(partition, order, frameSpec), newIndex: idx };
52
+ }
53
+ static isFrameTypeKeyword(value) {
54
+ const lowerValue = value;
55
+ return lowerValue === 'rows' || lowerValue === 'range' || lowerValue === 'groups';
56
+ }
57
+ static parseFrameSpec(lexemes, index) {
58
+ let idx = index;
59
+ // Determine frame type (ROWS/RANGE/GROUPS)
60
+ const frameTypeStr = lexemes[idx].value;
61
+ let frameType;
62
+ switch (frameTypeStr) {
63
+ case 'rows':
64
+ frameType = WindowFrameType.Rows;
65
+ break;
66
+ case 'range':
67
+ frameType = WindowFrameType.Range;
68
+ break;
69
+ case 'groups':
70
+ frameType = WindowFrameType.Groups;
71
+ break;
72
+ default:
73
+ throw new Error(`Syntax error at position ${idx}: Invalid frame type "${lexemes[idx].value}". Expected one of: ROWS, RANGE, GROUPS.`);
74
+ }
75
+ idx++;
76
+ // Check for BETWEEN ... AND ... syntax
77
+ if (idx < lexemes.length && lexemes[idx].value === 'between') {
78
+ // BETWEEN ... AND ... syntax
79
+ idx++;
80
+ // Parse start boundary
81
+ const startBoundResult = this.parseFrameBoundary(lexemes, idx);
82
+ const startBound = startBoundResult.value;
83
+ idx = startBoundResult.newIndex;
84
+ // Check for AND keyword - may be recognized as a separate token or part of a compound token
85
+ if (idx >= lexemes.length || (lexemes[idx].value !== 'and')) {
86
+ throw new Error(`Syntax error at position ${idx}: Expected 'AND' keyword in BETWEEN clause.`);
87
+ }
88
+ idx++; // Skip AND
89
+ // Parse end boundary
90
+ const endBoundResult = this.parseFrameBoundary(lexemes, idx);
91
+ const endBound = endBoundResult.value;
92
+ idx = endBoundResult.newIndex;
93
+ return {
94
+ value: new WindowFrameSpec(frameType, startBound, endBound),
95
+ newIndex: idx
96
+ };
97
+ }
98
+ else {
99
+ // Single boundary specification
100
+ const boundaryResult = this.parseFrameBoundary(lexemes, idx);
101
+ const startBound = boundaryResult.value;
102
+ idx = boundaryResult.newIndex;
103
+ return {
104
+ value: new WindowFrameSpec(frameType, startBound, null),
105
+ newIndex: idx
106
+ };
107
+ }
108
+ }
109
+ static parseFrameBoundary(lexemes, index) {
110
+ let idx = index;
111
+ // Check for predefined boundaries
112
+ if (idx < lexemes.length && lexemes[idx].type === TokenType.Command) {
113
+ const currentValue = lexemes[idx].value;
114
+ let frameBound;
115
+ switch (currentValue) {
116
+ case 'current row':
117
+ frameBound = WindowFrameBound.CurrentRow;
118
+ break;
119
+ case 'unbounded preceding':
120
+ frameBound = WindowFrameBound.UnboundedPreceding;
121
+ break;
122
+ case 'unbounded following':
123
+ frameBound = WindowFrameBound.UnboundedFollowing;
124
+ break;
125
+ default:
126
+ throw new Error(`Syntax error at position ${idx}: Invalid frame type "${lexemes[idx].value}". Expected one of: ROWS, RANGE, GROUPS.`);
127
+ }
128
+ const bound = new WindowFrameBoundStatic(frameBound);
129
+ return { value: bound, newIndex: idx + 1 };
130
+ }
131
+ else if (idx < lexemes.length && lexemes[idx].type === TokenType.Literal) {
132
+ // Parse the numeric/literal value
133
+ const valueResult = ValueParser.parseFromLexeme(lexemes, idx);
134
+ idx = valueResult.newIndex;
135
+ // Next token must be 'preceding' or 'following'
136
+ if (idx < lexemes.length && lexemes[idx].type === TokenType.Command) {
137
+ const direction = lexemes[idx].value;
138
+ let isFollowing;
139
+ if (direction === 'preceding') {
140
+ isFollowing = false;
141
+ }
142
+ else if (direction === 'following') {
143
+ isFollowing = true;
144
+ }
145
+ else {
146
+ throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);
147
+ }
148
+ idx++;
149
+ const bound = new WindowFrameBoundaryValue(valueResult.value, isFollowing);
150
+ return { value: bound, newIndex: idx };
151
+ }
152
+ else {
153
+ throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);
154
+ }
155
+ }
156
+ throw new Error(`Syntax error at position ${idx}: Expected a valid frame boundary component.`);
157
+ }
158
+ }
159
+ //# sourceMappingURL=WindowExpressionParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WindowExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/WindowExpressionParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { WithClause } from "../models/Clause";
2
+ import { TokenType } from "../models/Lexeme";
3
+ import { SqlTokenizer } from "./SqlTokenizer";
4
+ import { CommonTableParser } from "./CommonTableParser";
5
+ export class WithClauseParser {
6
+ // Parse SQL string to AST (was: parse)
7
+ static parse(query) {
8
+ const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
9
+ const lexemes = tokenizer.readLexmes(); // Get tokens
10
+ // Parse
11
+ const result = this.parseFromLexeme(lexemes, 0);
12
+ // Error if there are remaining tokens
13
+ if (result.newIndex < lexemes.length) {
14
+ throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The WITH clause is complete but there are additional tokens.`);
15
+ }
16
+ return result.value;
17
+ }
18
+ // Parse from lexeme array (was: parse)
19
+ static parseFromLexeme(lexemes, index) {
20
+ let idx = index;
21
+ // Expect WITH keyword
22
+ if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === "with") {
23
+ idx++;
24
+ }
25
+ else {
26
+ throw new Error(`Syntax error at position ${idx}: Expected WITH keyword.`);
27
+ }
28
+ // Check for RECURSIVE keyword
29
+ const recursive = idx < lexemes.length && lexemes[idx].value.toLowerCase() === "recursive";
30
+ if (recursive) {
31
+ idx++;
32
+ }
33
+ // Parse CTEs
34
+ const tables = [];
35
+ // Parse first CTE (required)
36
+ const firstCte = CommonTableParser.parseFromLexeme(lexemes, idx);
37
+ tables.push(firstCte.value);
38
+ idx = firstCte.newIndex;
39
+ // Parse additional CTEs (optional)
40
+ while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
41
+ idx++; // Skip comma
42
+ const cteResult = CommonTableParser.parseFromLexeme(lexemes, idx);
43
+ tables.push(cteResult.value);
44
+ idx = cteResult.newIndex;
45
+ }
46
+ // Create WITH clause
47
+ return {
48
+ value: new WithClause(recursive, tables),
49
+ newIndex: idx
50
+ };
51
+ }
52
+ }
53
+ //# sourceMappingURL=WithClauseParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WithClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/WithClauseParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,OAAO,gBAAgB;IACzB,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB;QAClE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,aAAa;QAErD,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,gEAAgE,CAAC,CAAC;QACvL,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,sBAAsB;QACtB,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YACtE,GAAG,EAAE,CAAC;QACV,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,0BAA0B,CAAC,CAAC;QAC/E,CAAC;QAED,8BAA8B;QAC9B,MAAM,SAAS,GAAG,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC;QAC3F,IAAI,SAAS,EAAE,CAAC;YACZ,GAAG,EAAE,CAAC;QACV,CAAC;QAED,aAAa;QACb,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5B,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAExB,mCAAmC;QACnC,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;YACnE,GAAG,EAAE,CAAC,CAAC,aAAa;YACpB,MAAM,SAAS,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC7B,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC;QAC7B,CAAC;QAED,qBAAqB;QACrB,OAAO;YACH,KAAK,EAAE,IAAI,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;YACxC,QAAQ,EAAE,GAAG;SAChB,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,78 @@
1
+ import { TokenType } from '../models/Lexeme';
2
+ import { StringUtils } from '../utils/stringUtils';
3
+ /**
4
+ * Base class for token readers
5
+ */
6
+ export class BaseTokenReader {
7
+ constructor(input, position = 0) {
8
+ this.input = input;
9
+ this.position = position;
10
+ }
11
+ /**
12
+ * Get the current position in the input
13
+ */
14
+ getPosition() {
15
+ return this.position;
16
+ }
17
+ /**
18
+ * Set the position in the input
19
+ */
20
+ setPosition(position) {
21
+ this.position = position;
22
+ }
23
+ /**
24
+ * Check if we've reached the end of input
25
+ */
26
+ isEndOfInput(shift = 0) {
27
+ return this.position + shift >= this.input.length;
28
+ }
29
+ /**
30
+ * Check if we can read more characters
31
+ */
32
+ canRead(shift = 0) {
33
+ return !this.isEndOfInput(shift);
34
+ }
35
+ /**
36
+ * Read an expected character
37
+ */
38
+ read(expectChar) {
39
+ if (this.isEndOfInput()) {
40
+ throw new Error(`Unexpected character. expect: ${expectChar}, actual: EndOfInput, position: ${this.position}`);
41
+ }
42
+ if (this.input[this.position] !== expectChar) {
43
+ throw new Error(`Unexpected character. expect: ${expectChar}, actual: ${this.input[this.position]}, position: ${this.position}`);
44
+ }
45
+ const char = this.input[this.position];
46
+ this.position++;
47
+ return char;
48
+ }
49
+ /**
50
+ * Create a lexeme with the specified type and value
51
+ */
52
+ createLexeme(type, value, maybeType = null, comments = null) {
53
+ if (type === TokenType.Command || type === TokenType.Operator || type === TokenType.Function) {
54
+ // Benchmark tests showed that directly calling toLowerCase() is ~5x faster
55
+ // than first checking if the string is already lowercase.
56
+ // See benchmarks/lowercase-benchmark.js for detailed performance analysis.
57
+ return {
58
+ type,
59
+ value: value.toLowerCase(),
60
+ comments: comments,
61
+ maybeType: maybeType,
62
+ };
63
+ }
64
+ return {
65
+ type,
66
+ value,
67
+ comments: comments,
68
+ maybeType: maybeType,
69
+ };
70
+ }
71
+ /**
72
+ * Get debug info for error reporting
73
+ */
74
+ getDebugPositionInfo(errPosition) {
75
+ return StringUtils.getDebugPositionInfo(this.input, errPosition);
76
+ }
77
+ }
78
+ //# sourceMappingURL=BaseTokenReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseTokenReader.js","sourceRoot":"","sources":["../../../src/tokenReaders/BaseTokenReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;GAEG;AACH,MAAM,OAAgB,eAAe;IAIjC,YAAY,KAAa,EAAE,WAAmB,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,WAAW;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,WAAW,CAAC,QAAgB;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,QAAgB,CAAC;QACpC,OAAO,IAAI,CAAC,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IACtD,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,QAAgB,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACO,IAAI,CAAC,UAAkB;QAC7B,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,UAAU,mCAAmC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnH,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,iCAAiC,UAAU,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrI,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,IAAe,EAAE,KAAa,EAAE,YAA4B,IAAI,EAAE,WAA4B,IAAI;QACrH,IAAI,IAAI,KAAK,SAAS,CAAC,OAAO,IAAI,IAAI,KAAK,SAAS,CAAC,QAAQ,IAAI,IAAI,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3F,2EAA2E;YAC3E,0DAA0D;YAC1D,2EAA2E;YAC3E,OAAO;gBACH,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE;gBAC1B,QAAQ,EAAE,QAAQ;gBAClB,SAAS,EAAE,SAAS;aACvB,CAAC;QACN,CAAC;QACD,OAAO;YACH,IAAI;YACJ,KAAK;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,SAAS;SACvB,CAAC;IACN,CAAC;IAED;;OAEG;IACO,oBAAoB,CAAC,WAAmB;QAC9C,OAAO,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACrE,CAAC;CAQJ"}