cloudflare-expression-lint 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +57 -0
- package/LICENSE +21 -0
- package/README.md +375 -0
- package/dist/cli.d.ts +22 -0
- package/dist/cli.js +363 -0
- package/dist/cli.js.map +1 -0
- package/dist/eslint-plugin.d.ts +67 -0
- package/dist/eslint-plugin.js +211 -0
- package/dist/eslint-plugin.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer.d.ts +11 -0
- package/dist/lexer.js +416 -0
- package/dist/lexer.js.map +1 -0
- package/dist/parser.d.ts +16 -0
- package/dist/parser.js +320 -0
- package/dist/parser.js.map +1 -0
- package/dist/schemas/fields.d.ts +44 -0
- package/dist/schemas/fields.js +282 -0
- package/dist/schemas/fields.js.map +1 -0
- package/dist/schemas/functions.d.ts +33 -0
- package/dist/schemas/functions.js +261 -0
- package/dist/schemas/functions.js.map +1 -0
- package/dist/schemas/operators.d.ts +28 -0
- package/dist/schemas/operators.js +37 -0
- package/dist/schemas/operators.js.map +1 -0
- package/dist/types.d.ts +149 -0
- package/dist/types.js +38 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +18 -0
- package/dist/validator.js +420 -0
- package/dist/validator.js.map +1 -0
- package/dist/yaml-scanner.d.ts +97 -0
- package/dist/yaml-scanner.js +175 -0
- package/dist/yaml-scanner.js.map +1 -0
- package/package.json +80 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cloudflare-expression-lint
|
|
3
|
+
*
|
|
4
|
+
* A parser, validator, and linter for Cloudflare Rules Language expressions
|
|
5
|
+
* with phase-aware field and function checking.
|
|
6
|
+
*/
|
|
7
|
+
export { tokenize } from './lexer.js';
|
|
8
|
+
export { parse } from './parser.js';
|
|
9
|
+
export { validate } from './validator.js';
|
|
10
|
+
export type { Token, TokenType, ASTNode, BooleanLiteralNode, StringLiteralNode, IntegerLiteralNode, FloatLiteralNode, IPLiteralNode, FieldAccessNode, NamedListNode, FunctionCallNode, ComparisonNode, LogicalNode, NotNode, InExpressionNode, GroupNode, ArrayUnpackNode, Diagnostic, DiagnosticSeverity, ValidationContext, ExpressionType, LintResult, } from './types.js';
|
|
11
|
+
export { FIELDS, findField, findBaseField } from './schemas/fields.js';
|
|
12
|
+
export type { FieldDef } from './schemas/fields.js';
|
|
13
|
+
export { FUNCTIONS, findFunction } from './schemas/functions.js';
|
|
14
|
+
export type { FunctionDef, ExpressionContext } from './schemas/functions.js';
|
|
15
|
+
export { COMPARISON_OPERATORS, LOGICAL_OPERATORS, findComparisonOperator, findLogicalOperator, } from './schemas/operators.js';
|
|
16
|
+
export type { OperatorDef, FieldType } from './schemas/operators.js';
|
|
17
|
+
export { scanYaml, getDefaultExpressionKeys, getDefaultPhaseMappings, } from './yaml-scanner.js';
|
|
18
|
+
export type { YAMLExpressionLocation, YAMLScanResult, ExpressionKeyMapping, PhaseMapping, ScannerOptions, } from './yaml-scanner.js';
|
|
19
|
+
export { default as eslintPlugin } from './eslint-plugin.js';
|
|
20
|
+
export { plugin as cloudflareExpressionLintPlugin, validateExpressionRule, createValidateExpressionRule, isExpressionKey, inferExpressionType, inferPhaseFromKey, DEFAULT_EXPRESSION_KEYS, } from './eslint-plugin.js';
|
|
21
|
+
export type { ValidateExpressionRuleOptions } from './eslint-plugin.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cloudflare-expression-lint
|
|
3
|
+
*
|
|
4
|
+
* A parser, validator, and linter for Cloudflare Rules Language expressions
|
|
5
|
+
* with phase-aware field and function checking.
|
|
6
|
+
*/
|
|
7
|
+
export { tokenize } from './lexer.js';
|
|
8
|
+
export { parse } from './parser.js';
|
|
9
|
+
export { validate } from './validator.js';
|
|
10
|
+
// Re-export schema types for consumers who want to extend
|
|
11
|
+
export { FIELDS, findField, findBaseField } from './schemas/fields.js';
|
|
12
|
+
export { FUNCTIONS, findFunction } from './schemas/functions.js';
|
|
13
|
+
export { COMPARISON_OPERATORS, LOGICAL_OPERATORS, findComparisonOperator, findLogicalOperator, } from './schemas/operators.js';
|
|
14
|
+
// Re-export YAML scanner
|
|
15
|
+
export { scanYaml, getDefaultExpressionKeys, getDefaultPhaseMappings, } from './yaml-scanner.js';
|
|
16
|
+
// ESLint plugin adapter
|
|
17
|
+
export { default as eslintPlugin } from './eslint-plugin.js';
|
|
18
|
+
export { plugin as cloudflareExpressionLintPlugin, validateExpressionRule, createValidateExpressionRule, isExpressionKey, inferExpressionType, inferPhaseFromKey, DEFAULT_EXPRESSION_KEYS, } from './eslint-plugin.js';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAa1C,0DAA0D;AAC1D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EACL,oBAAoB,EAAE,iBAAiB,EACvC,sBAAsB,EAAE,mBAAmB,GAC5C,MAAM,wBAAwB,CAAC;AAGhC,yBAAyB;AACzB,OAAO,EACL,QAAQ,EACR,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAS3B,wBAAwB;AACxB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EACL,MAAM,IAAI,8BAA8B,EACxC,sBAAsB,EACtB,4BAA4B,EAC5B,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
package/dist/lexer.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lexer (tokenizer) for Cloudflare expressions.
|
|
3
|
+
*
|
|
4
|
+
* Converts a raw expression string into a sequence of tokens.
|
|
5
|
+
*/
|
|
6
|
+
import { Token } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Tokenize a Cloudflare expression string.
|
|
9
|
+
* @throws Error on unterminated strings or unrecognized characters
|
|
10
|
+
*/
|
|
11
|
+
export declare function tokenize(input: string): Token[];
|
package/dist/lexer.js
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lexer (tokenizer) for Cloudflare expressions.
|
|
3
|
+
*
|
|
4
|
+
* Converts a raw expression string into a sequence of tokens.
|
|
5
|
+
*/
|
|
6
|
+
import { TokenType } from './types.js';
|
|
7
|
+
import { FUNCTIONS } from './schemas/functions.js';
|
|
8
|
+
const FUNCTION_NAMES = new Set(FUNCTIONS.map(f => f.name));
|
|
9
|
+
// Keywords that are comparison operators (english form)
|
|
10
|
+
const COMPARISON_KEYWORDS = new Set([
|
|
11
|
+
'eq', 'ne', 'lt', 'le', 'gt', 'ge', 'contains', 'matches', 'in', 'wildcard',
|
|
12
|
+
]);
|
|
13
|
+
// Keywords that are logical operators (english form)
|
|
14
|
+
const LOGICAL_KEYWORDS = new Set(['and', 'or', 'not', 'xor']);
|
|
15
|
+
// Known field prefixes for disambiguation
|
|
16
|
+
const FIELD_PREFIXES = [
|
|
17
|
+
'http.', 'ip.', 'cf.', 'ssl', 'raw.', 'tcp.', 'udp.',
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Tokenize a Cloudflare expression string.
|
|
21
|
+
* @throws Error on unterminated strings or unrecognized characters
|
|
22
|
+
*/
|
|
23
|
+
export function tokenize(input) {
|
|
24
|
+
const tokens = [];
|
|
25
|
+
let pos = 0;
|
|
26
|
+
let line = 1;
|
|
27
|
+
let lineStart = 0;
|
|
28
|
+
function col() {
|
|
29
|
+
return pos - lineStart + 1;
|
|
30
|
+
}
|
|
31
|
+
function peek() {
|
|
32
|
+
return pos < input.length ? input[pos] : '\0';
|
|
33
|
+
}
|
|
34
|
+
function peekAt(offset) {
|
|
35
|
+
const idx = pos + offset;
|
|
36
|
+
return idx < input.length ? input[idx] : '\0';
|
|
37
|
+
}
|
|
38
|
+
function advance() {
|
|
39
|
+
const ch = input[pos++];
|
|
40
|
+
if (ch === '\n') {
|
|
41
|
+
line++;
|
|
42
|
+
lineStart = pos;
|
|
43
|
+
}
|
|
44
|
+
return ch;
|
|
45
|
+
}
|
|
46
|
+
function skipWhitespace() {
|
|
47
|
+
while (pos < input.length && /\s/.test(input[pos])) {
|
|
48
|
+
advance();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function readString() {
|
|
52
|
+
const startPos = pos;
|
|
53
|
+
advance(); // consume opening quote
|
|
54
|
+
let value = '';
|
|
55
|
+
while (pos < input.length && input[pos] !== '"') {
|
|
56
|
+
if (input[pos] === '\\') {
|
|
57
|
+
advance(); // consume backslash
|
|
58
|
+
const escaped = advance();
|
|
59
|
+
switch (escaped) {
|
|
60
|
+
case '"':
|
|
61
|
+
value += '"';
|
|
62
|
+
break;
|
|
63
|
+
case '\\':
|
|
64
|
+
value += '\\';
|
|
65
|
+
break;
|
|
66
|
+
case 'n':
|
|
67
|
+
value += '\n';
|
|
68
|
+
break;
|
|
69
|
+
case 't':
|
|
70
|
+
value += '\t';
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
value += escaped;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
value += advance();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (pos >= input.length) {
|
|
82
|
+
throw new Error(`Unterminated string starting at position ${startPos}`);
|
|
83
|
+
}
|
|
84
|
+
advance(); // consume closing quote
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
function readIdentifier() {
|
|
88
|
+
let ident = '';
|
|
89
|
+
while (pos < input.length && /[a-zA-Z0-9_.]/.test(input[pos])) {
|
|
90
|
+
ident += advance();
|
|
91
|
+
}
|
|
92
|
+
// Remove trailing dot if any (shouldn't normally happen)
|
|
93
|
+
if (ident.endsWith('.')) {
|
|
94
|
+
pos--;
|
|
95
|
+
ident = ident.slice(0, -1);
|
|
96
|
+
}
|
|
97
|
+
return ident;
|
|
98
|
+
}
|
|
99
|
+
function readNumber() {
|
|
100
|
+
let num = '';
|
|
101
|
+
while (pos < input.length && /[0-9]/.test(input[pos])) {
|
|
102
|
+
num += advance();
|
|
103
|
+
}
|
|
104
|
+
return num;
|
|
105
|
+
}
|
|
106
|
+
function isIPChar(ch) {
|
|
107
|
+
return /[0-9.:]/.test(ch);
|
|
108
|
+
}
|
|
109
|
+
/** Check if the upcoming characters look like an IP address or CIDR */
|
|
110
|
+
function looksLikeIP() {
|
|
111
|
+
// Save position
|
|
112
|
+
let tempPos = pos;
|
|
113
|
+
let dotCount = 0;
|
|
114
|
+
let hasDigit = false;
|
|
115
|
+
while (tempPos < input.length && /[0-9.]/.test(input[tempPos])) {
|
|
116
|
+
if (input[tempPos] === '.')
|
|
117
|
+
dotCount++;
|
|
118
|
+
else
|
|
119
|
+
hasDigit = true;
|
|
120
|
+
tempPos++;
|
|
121
|
+
}
|
|
122
|
+
// IP addresses have exactly 3 dots (a.b.c.d)
|
|
123
|
+
return dotCount === 3 && hasDigit;
|
|
124
|
+
}
|
|
125
|
+
function addToken(type, value, startPos, startLine, startCol) {
|
|
126
|
+
tokens.push({ type, value, position: startPos, line: startLine, column: startCol });
|
|
127
|
+
}
|
|
128
|
+
while (pos < input.length) {
|
|
129
|
+
skipWhitespace();
|
|
130
|
+
if (pos >= input.length)
|
|
131
|
+
break;
|
|
132
|
+
const startPos = pos;
|
|
133
|
+
const startLine = line;
|
|
134
|
+
const startCol = col();
|
|
135
|
+
const ch = peek();
|
|
136
|
+
// ── Raw String Literal (r"...", r#"..."#, r##"..."##, etc.) ─────
|
|
137
|
+
if (ch === 'r' && (peekAt(1) === '"' || peekAt(1) === '#')) {
|
|
138
|
+
advance(); // consume 'r'
|
|
139
|
+
let hashCount = 0;
|
|
140
|
+
while (peek() === '#') {
|
|
141
|
+
advance();
|
|
142
|
+
hashCount++;
|
|
143
|
+
}
|
|
144
|
+
if (peek() !== '"') {
|
|
145
|
+
throw new Error(`Expected '"' after r${'#'.repeat(hashCount)} at position ${pos}`);
|
|
146
|
+
}
|
|
147
|
+
advance(); // consume opening "
|
|
148
|
+
let value = '';
|
|
149
|
+
const closingDelim = '"' + '#'.repeat(hashCount);
|
|
150
|
+
while (pos < input.length) {
|
|
151
|
+
if (input[pos] === '"') {
|
|
152
|
+
// Check if followed by the right number of #'s
|
|
153
|
+
let matched = true;
|
|
154
|
+
for (let h = 0; h < hashCount; h++) {
|
|
155
|
+
if (input[pos + 1 + h] !== '#') {
|
|
156
|
+
matched = false;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (matched) {
|
|
161
|
+
advance(); // consume closing "
|
|
162
|
+
for (let h = 0; h < hashCount; h++)
|
|
163
|
+
advance(); // consume #'s
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
value += advance();
|
|
168
|
+
}
|
|
169
|
+
addToken(TokenType.RawString, value, startPos, startLine, startCol);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// ── String Literal ───────────────────────────────────────────────
|
|
173
|
+
if (ch === '"') {
|
|
174
|
+
const value = readString();
|
|
175
|
+
addToken(TokenType.String, value, startPos, startLine, startCol);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
// ── Parentheses ──────────────────────────────────────────────────
|
|
179
|
+
if (ch === '(') {
|
|
180
|
+
advance();
|
|
181
|
+
addToken(TokenType.LeftParen, '(', startPos, startLine, startCol);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (ch === ')') {
|
|
185
|
+
advance();
|
|
186
|
+
addToken(TokenType.RightParen, ')', startPos, startLine, startCol);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
// ── Curly Braces ─────────────────────────────────────────────────
|
|
190
|
+
if (ch === '{') {
|
|
191
|
+
advance();
|
|
192
|
+
addToken(TokenType.LeftBrace, '{', startPos, startLine, startCol);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (ch === '}') {
|
|
196
|
+
advance();
|
|
197
|
+
addToken(TokenType.RightBrace, '}', startPos, startLine, startCol);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
// ── Square Brackets ──────────────────────────────────────────────
|
|
201
|
+
if (ch === '[') {
|
|
202
|
+
// Check for [*] array unpack
|
|
203
|
+
if (peekAt(1) === '*' && peekAt(2) === ']') {
|
|
204
|
+
advance();
|
|
205
|
+
advance();
|
|
206
|
+
advance();
|
|
207
|
+
addToken(TokenType.ArrayUnpack, '[*]', startPos, startLine, startCol);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
advance();
|
|
211
|
+
addToken(TokenType.LeftBracket, '[', startPos, startLine, startCol);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (ch === ']') {
|
|
215
|
+
advance();
|
|
216
|
+
addToken(TokenType.RightBracket, ']', startPos, startLine, startCol);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// ── Comma ────────────────────────────────────────────────────────
|
|
220
|
+
if (ch === ',') {
|
|
221
|
+
advance();
|
|
222
|
+
addToken(TokenType.Comma, ',', startPos, startLine, startCol);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// ── Range (..) ───────────────────────────────────────────────────
|
|
226
|
+
if (ch === '.' && peekAt(1) === '.') {
|
|
227
|
+
advance();
|
|
228
|
+
advance();
|
|
229
|
+
addToken(TokenType.DotDot, '..', startPos, startLine, startCol);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
// ── Slash (for CIDR) ─────────────────────────────────────────────
|
|
233
|
+
if (ch === '/') {
|
|
234
|
+
advance();
|
|
235
|
+
addToken(TokenType.Slash, '/', startPos, startLine, startCol);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
// ── Named List ($...) ────────────────────────────────────────────
|
|
239
|
+
if (ch === '$') {
|
|
240
|
+
advance(); // consume $
|
|
241
|
+
const name = readIdentifier();
|
|
242
|
+
addToken(TokenType.NamedList, '$' + name, startPos, startLine, startCol);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
// ── Symbol Operators ─────────────────────────────────────────────
|
|
246
|
+
if (ch === '=' && peekAt(1) === '=') {
|
|
247
|
+
advance();
|
|
248
|
+
advance();
|
|
249
|
+
addToken(TokenType.ComparisonOp, '==', startPos, startLine, startCol);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (ch === '!' && peekAt(1) === '=') {
|
|
253
|
+
advance();
|
|
254
|
+
advance();
|
|
255
|
+
addToken(TokenType.ComparisonOp, '!=', startPos, startLine, startCol);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (ch === '<' && peekAt(1) === '=') {
|
|
259
|
+
advance();
|
|
260
|
+
advance();
|
|
261
|
+
addToken(TokenType.ComparisonOp, '<=', startPos, startLine, startCol);
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (ch === '>' && peekAt(1) === '=') {
|
|
265
|
+
advance();
|
|
266
|
+
advance();
|
|
267
|
+
addToken(TokenType.ComparisonOp, '>=', startPos, startLine, startCol);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (ch === '<') {
|
|
271
|
+
advance();
|
|
272
|
+
addToken(TokenType.ComparisonOp, '<', startPos, startLine, startCol);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (ch === '>') {
|
|
276
|
+
advance();
|
|
277
|
+
addToken(TokenType.ComparisonOp, '>', startPos, startLine, startCol);
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (ch === '~') {
|
|
281
|
+
advance();
|
|
282
|
+
addToken(TokenType.ComparisonOp, '~', startPos, startLine, startCol);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (ch === '&' && peekAt(1) === '&') {
|
|
286
|
+
advance();
|
|
287
|
+
advance();
|
|
288
|
+
addToken(TokenType.LogicalOp, '&&', startPos, startLine, startCol);
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (ch === '|' && peekAt(1) === '|') {
|
|
292
|
+
advance();
|
|
293
|
+
advance();
|
|
294
|
+
addToken(TokenType.LogicalOp, '||', startPos, startLine, startCol);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (ch === '^' && peekAt(1) === '^') {
|
|
298
|
+
advance();
|
|
299
|
+
advance();
|
|
300
|
+
addToken(TokenType.LogicalOp, '^^', startPos, startLine, startCol);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (ch === '!') {
|
|
304
|
+
advance();
|
|
305
|
+
addToken(TokenType.LogicalOp, '!', startPos, startLine, startCol);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
// ── Numbers / IP Addresses ───────────────────────────────────────
|
|
309
|
+
if (/[0-9]/.test(ch)) {
|
|
310
|
+
// Check if this looks like an IP address (inside { } list context)
|
|
311
|
+
// We determine context by checking if we're inside braces
|
|
312
|
+
let lastOpenBrace = -1;
|
|
313
|
+
let lastCloseBrace = -1;
|
|
314
|
+
for (let idx = tokens.length - 1; idx >= 0; idx--) {
|
|
315
|
+
if (lastOpenBrace === -1 && tokens[idx].type === TokenType.LeftBrace)
|
|
316
|
+
lastOpenBrace = idx;
|
|
317
|
+
if (lastCloseBrace === -1 && tokens[idx].type === TokenType.RightBrace)
|
|
318
|
+
lastCloseBrace = idx;
|
|
319
|
+
}
|
|
320
|
+
const inBraces = lastOpenBrace >= 0 && lastOpenBrace > lastCloseBrace;
|
|
321
|
+
if (inBraces && looksLikeIP()) {
|
|
322
|
+
// Read full IP address
|
|
323
|
+
let ip = '';
|
|
324
|
+
while (pos < input.length && /[0-9.:]/.test(input[pos])) {
|
|
325
|
+
ip += advance();
|
|
326
|
+
}
|
|
327
|
+
addToken(TokenType.IPAddress, ip, startPos, startLine, startCol);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const num = readNumber();
|
|
331
|
+
// Check if followed by dots (could be IP outside braces, or just an integer)
|
|
332
|
+
if (peek() === '.' && /[0-9]/.test(peekAt(1)) && peekAt(1) !== '.') {
|
|
333
|
+
// Could be IP address - peek ahead
|
|
334
|
+
const savedPos = pos;
|
|
335
|
+
let maybeIP = num;
|
|
336
|
+
let dotCount = 0;
|
|
337
|
+
let tempPos = pos;
|
|
338
|
+
while (tempPos < input.length && /[0-9.]/.test(input[tempPos])) {
|
|
339
|
+
if (input[tempPos] === '.')
|
|
340
|
+
dotCount++;
|
|
341
|
+
tempPos++;
|
|
342
|
+
}
|
|
343
|
+
if (dotCount === 3) {
|
|
344
|
+
// Looks like an IP
|
|
345
|
+
while (pos < input.length && /[0-9.]/.test(input[pos])) {
|
|
346
|
+
maybeIP += advance();
|
|
347
|
+
}
|
|
348
|
+
addToken(TokenType.IPAddress, maybeIP, startPos, startLine, startCol);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
addToken(TokenType.Integer, num, startPos, startLine, startCol);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
// ── Identifiers / Keywords / Fields / Functions ──────────────────
|
|
356
|
+
if (/[a-zA-Z_]/.test(ch)) {
|
|
357
|
+
const ident = readIdentifier();
|
|
358
|
+
// Check for "strict wildcard" (two-word operator)
|
|
359
|
+
if (ident === 'strict') {
|
|
360
|
+
const savedPos = pos;
|
|
361
|
+
const savedLine = line;
|
|
362
|
+
const savedLineStart = lineStart;
|
|
363
|
+
skipWhitespace();
|
|
364
|
+
if (pos < input.length) {
|
|
365
|
+
const nextStart = pos;
|
|
366
|
+
const peek = readIdentifier();
|
|
367
|
+
if (peek === 'wildcard') {
|
|
368
|
+
addToken(TokenType.ComparisonOp, 'strict wildcard', startPos, startLine, startCol);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
// Not "strict wildcard" — backtrack
|
|
372
|
+
pos = savedPos;
|
|
373
|
+
line = savedLine;
|
|
374
|
+
lineStart = savedLineStart;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// Boolean literals
|
|
378
|
+
if (ident === 'true' || ident === 'false') {
|
|
379
|
+
addToken(TokenType.Boolean, ident, startPos, startLine, startCol);
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
// Comparison operator keywords
|
|
383
|
+
if (COMPARISON_KEYWORDS.has(ident)) {
|
|
384
|
+
addToken(TokenType.ComparisonOp, ident, startPos, startLine, startCol);
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
// Logical operator keywords
|
|
388
|
+
if (LOGICAL_KEYWORDS.has(ident)) {
|
|
389
|
+
addToken(TokenType.LogicalOp, ident, startPos, startLine, startCol);
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
// Check if this is a function call (followed by '(')
|
|
393
|
+
skipWhitespace();
|
|
394
|
+
if (peek() === '(' && (FUNCTION_NAMES.has(ident) || isLikelyFunction(ident))) {
|
|
395
|
+
addToken(TokenType.Function, ident, startPos, startLine, startCol);
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
// Otherwise it's a field
|
|
399
|
+
addToken(TokenType.Field, ident, startPos, startLine, startCol);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
// ── Unknown Character ────────────────────────────────────────────
|
|
403
|
+
throw new Error(`Unexpected character '${ch}' at position ${pos} (line ${line}, col ${col()})`);
|
|
404
|
+
}
|
|
405
|
+
addToken(TokenType.EOF, '', pos, line, col());
|
|
406
|
+
return tokens;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Heuristic: treat identifier-followed-by-paren as a function even if not
|
|
410
|
+
* in the known registry (we'll catch unknown functions in the validator).
|
|
411
|
+
*/
|
|
412
|
+
function isLikelyFunction(name) {
|
|
413
|
+
// All Cloudflare functions use snake_case and are lowercase
|
|
414
|
+
return /^[a-z][a-z0-9_]*$/.test(name) && !name.includes('.');
|
|
415
|
+
}
|
|
416
|
+
//# sourceMappingURL=lexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.js","sourceRoot":"","sources":["../src/lexer.ts"],"names":[],"mappings":"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"}
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for Cloudflare expressions.
|
|
3
|
+
*
|
|
4
|
+
* Converts a token stream into an AST using recursive descent parsing.
|
|
5
|
+
* Handles operator precedence for logical operators:
|
|
6
|
+
* 1. not / ! (highest, unary)
|
|
7
|
+
* 2. and / &&
|
|
8
|
+
* 3. xor / ^^
|
|
9
|
+
* 4. or / || (lowest)
|
|
10
|
+
*/
|
|
11
|
+
import { ASTNode } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Parse a Cloudflare expression string into an AST.
|
|
14
|
+
* @throws Error on syntax errors
|
|
15
|
+
*/
|
|
16
|
+
export declare function parse(input: string): ASTNode;
|