Skip to content

Commit 9745007

Browse files
committed
fix: error messages
1 parent 71debba commit 9745007

32 files changed

+1064
-1018
lines changed

packages/pgen/compile.ts

+39-17
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type Context = {
3939
}
4040
type Compiler<T> = (ctx: Context) => T;
4141

42-
const compileRule = ({ name, formals, body }: g.Rule): Compiler<{
42+
const compileRule = ({ name, formals, body, display }: g.Rule): Compiler<{
4343
name: string | undefined,
4444
expr: t.Statement,
4545
type: t.Statement,
@@ -50,7 +50,7 @@ const compileRule = ({ name, formals, body }: g.Rule): Compiler<{
5050

5151
const { expr: exprCode, type: typeCode } = compileExpr(body)(ctx);
5252

53-
const bodyCode = compileFormals(name, formals, exprCode);
53+
const bodyCode = compileFormals(name, formals, compileDisplay(display, exprCode));
5454

5555
return {
5656
name: formals.length > 0 ? undefined : name,
@@ -69,6 +69,15 @@ const compileRule = ({ name, formals, body }: g.Rule): Compiler<{
6969
};
7070
};
7171

72+
const compileDisplay = (display: g.Rule["display"], expr: t.Expression): t.Expression => {
73+
if (!display) {
74+
return expr;
75+
}
76+
const body = display.map(char => compileChar(char)).join('');
77+
const value = JSON.parse(`"${body}"`);
78+
return emitCall('named', [t.stringLiteral(value), expr]);
79+
};
80+
7281
const compileFormals = (name: string, formals: readonly string[], bodyCode: t.Expression): t.Expression => {
7382
if (formals.length === 0) {
7483
return bodyCode;
@@ -216,10 +225,17 @@ const compileClass = ({ insensitive, negated, seqs }: g.Class): Compiler<ExprWit
216225
const children = seqs.map(seq => compileSeq(seq));
217226
const body = children.map(child => child.expr).join('');
218227
const types = children.map(child => child.type);
228+
const expectables = t.arrayExpression(children.map(child => child.exp));
219229
return ewt(
220230
emitCall(
221231
'regex',
222-
[t.stringLiteral(prefix + body), t.booleanLiteral(insensitive)],
232+
[
233+
t.stringLiteral(prefix + body),
234+
negated
235+
? emitCall('negateExps', [expectables])
236+
: expectables,
237+
// t.booleanLiteral(insensitive)
238+
],
223239
[t.tsUnionType(types)]
224240
),
225241
t.tsUnionType(types),
@@ -295,7 +311,7 @@ const compileCall = (node: g.Call): Compiler<ExprWithType> => ctx => {
295311
return ewt(wrapInRef(node.name, body), type);
296312
};
297313

298-
type TypedString = { expr: string, type: t.TSType };
314+
type TypedString = { expr: string, type: t.TSType, exp: t.Expression };
299315

300316
const compileChar = (node: g.Escape | g.Special | g.Char): string => {
301317
switch (node.$) {
@@ -309,16 +325,20 @@ const compileChar = (node: g.Escape | g.Special | g.Char): string => {
309325
const compileSeq = (node: g.Group | g.ClassChar | g.SpecialClass | g.Escape): TypedString => {
310326
switch (node.$) {
311327
case 'Group':
328+
const from = compileSeq(node.from).expr;
329+
const to = compileSeq(node.to).expr;
312330
return {
313-
expr: compileSeq(node.from).expr + '-' + compileSeq(node.to).expr,
331+
expr: from + '-' + to,
314332
type: t.tsStringKeyword(),
333+
exp: emitCall('ExpRange', [t.stringLiteral(from), t.stringLiteral(to)])
315334
};
316335
case 'ClassChar':
317336
return {
318337
expr: node.value === '\\' || node.value === '\]'
319338
? `\\${node.value}`
320339
: node.value,
321340
type: t.tsLiteralType(t.stringLiteral(node.value)),
341+
exp: emitCall('ExpString', [t.stringLiteral(node.value)])
322342
};
323343
default:
324344
return compileEscape(node);
@@ -330,18 +350,20 @@ const compileEscape = (node: g.Escape | g.Special | g.SpecialClass): TypedString
330350

331351
const str = `"${expr}"`;
332352

333-
const type = (() => {
334-
try {
335-
return t.tsLiteralType(t.stringLiteral(JSON.parse(str)));
336-
} catch (e) {
337-
return t.tsStringKeyword();
338-
}
339-
})();
340-
341-
return {
342-
expr,
343-
type,
344-
};
353+
try {
354+
const parsed = JSON.parse(str);
355+
return {
356+
expr,
357+
type: t.tsLiteralType(t.stringLiteral(parsed)),
358+
exp: emitCall('ExpString', [t.stringLiteral(parsed)])
359+
};
360+
} catch (e) {
361+
return {
362+
expr,
363+
type: t.tsStringKeyword(),
364+
exp: emitCall('ExpString', [t.stringLiteral(str)])
365+
};
366+
}
345367
};
346368

347369
const compileEscapeToString = (node: g.Escape | g.Special | g.SpecialClass): string => {

packages/pgen/grammar.gg

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
Grammar = rules:Rule*;
2-
Rule = name:ident formals:formals? "=" body:ruleBody ";";
2+
Rule = name:ident display:string? formals:formals? "=" body:ruleBody ";";
33
formals = "<" @(head:ident tail:("," @ident)*)? ">";
4-
ruleBody = @Alt;
4+
ruleBody = Alt;
55
Alt = head:Seq tail:("/" @Seq)*;
66
Seq = exprs:Sel*;
77
Sel = selector:selector? expr:Iter;
8-
selector = @Name / @Choose;
8+
selector = Name / Choose;
99
Name = name:ident ":";
1010
Choose = "@";
1111
Iter = prefix:(@[!&#$])* expr:base suffix:(@[*+?])?;
12-
base = @Apply / @#Class / @#Terminal / @paren / @Any;
12+
base = Apply / #Class / Terminal / paren / Any;
1313
Apply = name:ident params:params?;
14-
params = "<" @(head:Seq tail:("," @Seq)*)? ">";
15-
Class = "[" negated:"^"? seqs:classSeq* "]" insensitive:"i"?;
14+
params = "<" @(head:Alt tail:("," @Alt)*)? ">";
15+
Class = "[" negated:"^"? seqs:classSeq* "]";
1616
classSeq = @Group / @classChar;
1717
Group = from:classChar "-" to:classChar;
1818
classChar = "\\" @(@SpecialClass / @escape) / @ClassChar;
1919
SpecialClass = value:[\\\]];
2020
ClassChar = value:[^\\\]];
21-
Terminal = "\"" value:char* "\"";
21+
Terminal = value:string;
22+
string = #("\"" @char* "\"");
2223
paren = "(" @Alt ")";
2324
Any = ".";
24-
ident = @$#([a-z_]i [a-z0-9_]i*);
25+
ident = @#$([a-zA-Z_] [a-zA-Z0-9_]*);
2526
char = "\\" @(@Special / @escape) / @Char;
2627
Char = value:[^\\"];
2728
escape = @Named / @unicode / @Ascii;
@@ -31,7 +32,7 @@ unicode = "u" @(@Short / @Long);
3132
Short = value:$(hexDigit hexDigit hexDigit hexDigit);
3233
Long = "{" value:$hexDigit+ "}";
3334
Ascii = "x" value:$(hexDigit hexDigit);
34-
hexDigit = [0-9a-f]i;
35+
hexDigit = [0-9a-fA-F];
3536
space = [ \t\n\r] / Single / Multi;
3637
Single = "//" value:$[^\n\r]*;
3738
Multi = "/*" value:$(!"*/" .)* "*/";

0 commit comments

Comments
 (0)