simple parser

This commit is contained in:
Elizabeth Hunt 2024-02-23 17:27:16 -07:00
parent d0d6aae1e5
commit e8e9ee18f2
Signed by: simponic
GPG Key ID: 52B3774857EB24B1
6 changed files with 198 additions and 142 deletions

View File

@ -17,7 +17,7 @@ SelectExpression
_? _?
LPAREN LPAREN
_? _?
select:Integer record:Integer
_? _?
COMMA COMMA
_? _?
@ -27,16 +27,18 @@ SelectExpression
_? _?
bind:Identifier bind:Identifier
_? _?
COMMA
_?
continuation:ContinuationExpression continuation:ContinuationExpression
_? _?
RPAREN { return { select, val, bind, continuation }; } RPAREN { return { select: { record, val, bind, continuation } }; }
OffsetExpression OffsetExpression
= OFFSET = OFFSET
_? _?
LPAREN LPAREN
_? _?
offset:Integer index:Integer
_? _?
COMMA COMMA
_? _?
@ -48,31 +50,25 @@ OffsetExpression
_? _?
continuation:ContinuationExpression continuation:ContinuationExpression
_? _?
RPAREN { return { offset, val, bind, continuation }; } RPAREN { return { offset: { index, val, bind, continuation } }; }
IdentifierList IdentifierList
= LBRACKET = LBRACKET
_? _?
identifiers:(ident:Identifier _? COMMA _?)* identifiers:(Identifier _? COMMA _?)*
_? _?
lastIdent:Identifier? lastIdent:Identifier?
_? _?
RBRACKET { RBRACKET {
return identifiers.length || lastIdent return identifiers.length || lastIdent
? [...identifiers.map(x => x.ident), lastIdent] ? [...identifiers.map(x => x[0]), lastIdent]
: []; : [];
} }
ValueList ValueList
= LBRACKET = LBRACKET _? values:(Value _? COMMA _?)* _? lastValue:Value? _? RBRACKET {
_?
values:(value:Value _? COMMA _?)*
_?
lastValue:Value?
_?
RBRACKET {
return values.length || lastValue return values.length || lastValue
? [...values.map(x => x.value), lastValue] ? [...values.map(x => x[0]), lastValue]
: []; : [];
} }
@ -87,11 +83,11 @@ SwitchExpression
_? _?
continuations:ContinuationList continuations:ContinuationList
_? _?
RPAREN { return { switchIndex, continuations }; } RPAREN { return { switch: { switchIndex, continuations } }; }
ApplicationExpression ApplicationExpression
= APP _? LPAREN _? fn:Value _? COMMA _? args:ValueList _? RPAREN { = APP _? LPAREN _? fn:Value _? COMMA _? args:ValueList _? RPAREN {
return { fn, args }; return { application: { fn, args } };
} }
FixBinding FixBinding
@ -111,14 +107,14 @@ FixBinding
FixBindingList FixBindingList
= LBRACKET = LBRACKET
_ _?
bindings:(binding:FixBinding _? COMMA _?)* bindings:(FixBinding _? COMMA _?)*
_? _?
lastBinding:FixBinding? lastBinding:FixBinding?
_? _?
RBRACKET { RBRACKET {
return bindings.length || lastBinding return bindings.length || lastBinding
? [...bindings.map(x => x.binding), lastBinding] ? [...bindings.map(x => x[0]), lastBinding]
: []; : [];
} }
@ -133,18 +129,18 @@ FixExpression
_? _?
continuation:ContinuationExpression continuation:ContinuationExpression
_? _?
RPAREN { return { fixBindings, continuation }; } RPAREN { return { fix: { fixBindings, continuation } }; }
ContinuationList ContinuationList
= LBRACKET = LBRACKET
_? _?
continuations:(continuation:ContinuationExpression _? COMMA _?)* continuations:(ContinuationExpression _? COMMA _?)*
_? _?
lastContinuation:ContinuationExpression? lastContinuation:ContinuationExpression?
_? _?
RBRACKET { RBRACKET {
return lastContinuation || continuations.length return lastContinuation || continuations.length
? [...continuations.map(x => x.continuation), lastContinuation] ? [...continuations.map(x => x[0]), lastContinuation]
: []; : [];
} }
@ -167,7 +163,11 @@ PrimitiveOperationExpression
_? _?
continuations:ContinuationList continuations:ContinuationList
_? _?
RPAREN { return { opr, operands, resultBindings, continuations }; } RPAREN {
return {
primitiveOperation: { opr, operands, resultBindings, continuations },
};
}
RecordExpressionTuple RecordExpressionTuple
= LPAREN = LPAREN
@ -183,13 +183,13 @@ RecordExpressionTuple
RecordExpressionTupleList RecordExpressionTupleList
= LBRACKET = LBRACKET
_? _?
records:(record:RecordExpressionTuple _? COMMA _?)* records:(RecordExpressionTuple _? COMMA _?)*
_? _?
lastRecord:RecordExpressionTuple? lastRecord:RecordExpressionTuple?
_? _?
RBRACKET { RBRACKET {
return records.length || lastRecord return records.length || lastRecord
? [...records.map(x => x.record), lastRecord] ? [...records.map(x => x[0]), lastRecord]
: []; : [];
} }
@ -210,9 +210,11 @@ RecordExpression
_? _?
RPAREN { RPAREN {
return { return {
records, record: {
address, records,
body, address,
body,
},
}; };
} }

View File

@ -408,17 +408,17 @@ function peg$parse(input, options) {
return exprs.filter(x => !Array.isArray(x)); return exprs.filter(x => !Array.isArray(x));
};// @ts-ignore };// @ts-ignore
var peg$f1 = function(select, val, bind, continuation) {// @ts-ignore var peg$f1 = function(record, val, bind, continuation) {// @ts-ignore
return { select, val, bind, continuation }; };// @ts-ignore return { select: { record, val, bind, continuation } }; };// @ts-ignore
var peg$f2 = function(offset, val, bind, continuation) {// @ts-ignore var peg$f2 = function(index, val, bind, continuation) {// @ts-ignore
return { offset, val, bind, continuation }; };// @ts-ignore return { offset: { index, val, bind, continuation } }; };// @ts-ignore
var peg$f3 = function(identifiers, lastIdent) { var peg$f3 = function(identifiers, lastIdent) {
// @ts-ignore // @ts-ignore
return identifiers.length || lastIdent return identifiers.length || lastIdent
// @ts-ignore // @ts-ignore
? [...identifiers.map(x => x.ident), lastIdent] ? [...identifiers.map(x => x[0]), lastIdent]
: []; : [];
};// @ts-ignore };// @ts-ignore
@ -426,39 +426,44 @@ function peg$parse(input, options) {
// @ts-ignore // @ts-ignore
return values.length || lastValue return values.length || lastValue
// @ts-ignore // @ts-ignore
? [...values.map(x => x.value), lastValue] ? [...values.map(x => x[0]), lastValue]
: []; : [];
};// @ts-ignore };// @ts-ignore
var peg$f5 = function(switchIndex, continuations) {// @ts-ignore var peg$f5 = function(switchIndex, continuations) {// @ts-ignore
return { switchIndex, continuations }; };// @ts-ignore return { switch: { switchIndex, continuations } }; };// @ts-ignore
var peg$f6 = function(fn, args) { var peg$f6 = function(fn, args) {
// @ts-ignore // @ts-ignore
return { fn, args }; return { application: { fn, args } };
};// @ts-ignore };// @ts-ignore
var peg$f7 = function(bindings, lastBinding) { var peg$f7 = function(bindings, lastBinding) {
// @ts-ignore // @ts-ignore
return bindings.length || lastBinding return bindings.length || lastBinding
// @ts-ignore // @ts-ignore
? [...bindings.map(x => x.binding), lastBinding] ? [...bindings.map(x => x[0]), lastBinding]
: []; : [];
};// @ts-ignore };// @ts-ignore
var peg$f8 = function(fixBindings, continuation) {// @ts-ignore var peg$f8 = function(fixBindings, continuation) {// @ts-ignore
return { fixBindings, continuation }; };// @ts-ignore return { fix: { fixBindings, continuation } }; };// @ts-ignore
var peg$f9 = function(continuations, lastContinuation) { var peg$f9 = function(continuations, lastContinuation) {
// @ts-ignore // @ts-ignore
return lastContinuation || continuations.length return lastContinuation || continuations.length
// @ts-ignore // @ts-ignore
? [...continuations.map(x => x.continuation), lastContinuation] ? [...continuations.map(x => x[0]), lastContinuation]
: []; : [];
};// @ts-ignore };// @ts-ignore
var peg$f10 = function(opr, operands, resultBindings, continuations) {// @ts-ignore var peg$f10 = function(opr, operands, resultBindings, continuations) {
return { opr, operands, resultBindings, continuations }; };// @ts-ignore // @ts-ignore
return {
// @ts-ignore
primitiveOperation: { opr, operands, resultBindings, continuations },
};
};// @ts-ignore
var peg$f11 = function(variable, offset) {// @ts-ignore var peg$f11 = function(variable, offset) {// @ts-ignore
return { variable, offset }; };// @ts-ignore return { variable, offset }; };// @ts-ignore
@ -467,7 +472,7 @@ function peg$parse(input, options) {
// @ts-ignore // @ts-ignore
return records.length || lastRecord return records.length || lastRecord
// @ts-ignore // @ts-ignore
? [...records.map(x => x.record), lastRecord] ? [...records.map(x => x[0]), lastRecord]
: []; : [];
};// @ts-ignore };// @ts-ignore
@ -475,11 +480,14 @@ function peg$parse(input, options) {
// @ts-ignore // @ts-ignore
return { return {
// @ts-ignore // @ts-ignore
records, record: {
// @ts-ignore // @ts-ignore
address, records,
// @ts-ignore // @ts-ignore
body, address,
// @ts-ignore
body,
},
}; };
};// @ts-ignore };// @ts-ignore
@ -874,7 +882,7 @@ peg$parseContinuationExpression() {
function // @ts-ignore function // @ts-ignore
peg$parseSelectExpression() { peg$parseSelectExpression() {
// @ts-ignore // @ts-ignore
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17; var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19;
// @ts-ignore // @ts-ignore
s0 = peg$currPos; s0 = peg$currPos;
@ -956,7 +964,7 @@ peg$parseSelectExpression() {
s14 = null; s14 = null;
} }
// @ts-ignore // @ts-ignore
s15 = peg$parseContinuationExpression(); s15 = peg$parseCOMMA();
// @ts-ignore // @ts-ignore
if (s15 !== peg$FAILED) { if (s15 !== peg$FAILED) {
// @ts-ignore // @ts-ignore
@ -967,13 +975,31 @@ peg$parseSelectExpression() {
s16 = null; s16 = null;
} }
// @ts-ignore // @ts-ignore
s17 = peg$parseRPAREN(); s17 = peg$parseContinuationExpression();
// @ts-ignore // @ts-ignore
if (s17 !== peg$FAILED) { if (s17 !== peg$FAILED) {
// @ts-ignore // @ts-ignore
peg$savedPos = s0; s18 = peg$parse_();
// @ts-ignore // @ts-ignore
s0 = peg$f1(s5, s9, s13, s15); if (s18 === peg$FAILED) {
// @ts-ignore
s18 = null;
}
// @ts-ignore
s19 = peg$parseRPAREN();
// @ts-ignore
if (s19 !== peg$FAILED) {
// @ts-ignore
peg$savedPos = s0;
// @ts-ignore
s0 = peg$f1(s5, s9, s13, s17);
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s0;
// @ts-ignore
s0 = peg$FAILED;
}
// @ts-ignore // @ts-ignore
} else { } else {
// @ts-ignore // @ts-ignore
@ -1917,9 +1943,58 @@ peg$parseFixBindingList() {
// @ts-ignore // @ts-ignore
s2 = peg$parse_(); s2 = peg$parse_();
// @ts-ignore // @ts-ignore
if (s2 !== peg$FAILED) { if (s2 === peg$FAILED) {
// @ts-ignore // @ts-ignore
s3 = []; s2 = null;
}
// @ts-ignore
s3 = [];
// @ts-ignore
s4 = peg$currPos;
// @ts-ignore
s5 = peg$parseFixBinding();
// @ts-ignore
if (s5 !== peg$FAILED) {
// @ts-ignore
s6 = peg$parse_();
// @ts-ignore
if (s6 === peg$FAILED) {
// @ts-ignore
s6 = null;
}
// @ts-ignore
s7 = peg$parseCOMMA();
// @ts-ignore
if (s7 !== peg$FAILED) {
// @ts-ignore
s8 = peg$parse_();
// @ts-ignore
if (s8 === peg$FAILED) {
// @ts-ignore
s8 = null;
}
// @ts-ignore
s5 = [s5, s6, s7, s8];
// @ts-ignore
s4 = s5;
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s4;
// @ts-ignore
s4 = peg$FAILED;
}
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s4;
// @ts-ignore
s4 = peg$FAILED;
}
// @ts-ignore
while (s4 !== peg$FAILED) {
// @ts-ignore
s3.push(s4);
// @ts-ignore // @ts-ignore
s4 = peg$currPos; s4 = peg$currPos;
// @ts-ignore // @ts-ignore
@ -1962,89 +2037,36 @@ peg$parseFixBindingList() {
// @ts-ignore // @ts-ignore
s4 = peg$FAILED; s4 = peg$FAILED;
} }
}
// @ts-ignore // @ts-ignore
while (s4 !== peg$FAILED) { s4 = peg$parse_();
// @ts-ignore // @ts-ignore
s3.push(s4); if (s4 === peg$FAILED) {
// @ts-ignore // @ts-ignore
s4 = peg$currPos; s4 = null;
}
// @ts-ignore // @ts-ignore
s5 = peg$parseFixBinding(); s5 = peg$parseFixBinding();
// @ts-ignore // @ts-ignore
if (s5 !== peg$FAILED) { if (s5 === peg$FAILED) {
// @ts-ignore // @ts-ignore
s6 = peg$parse_(); s5 = null;
}
// @ts-ignore // @ts-ignore
if (s6 === peg$FAILED) { s6 = peg$parse_();
// @ts-ignore // @ts-ignore
s6 = null; if (s6 === peg$FAILED) {
}
// @ts-ignore // @ts-ignore
s7 = peg$parseCOMMA(); s6 = null;
}
// @ts-ignore // @ts-ignore
if (s7 !== peg$FAILED) { s7 = peg$parseRBRACKET();
// @ts-ignore // @ts-ignore
s8 = peg$parse_(); if (s7 !== peg$FAILED) {
// @ts-ignore // @ts-ignore
if (s8 === peg$FAILED) { peg$savedPos = s0;
// @ts-ignore // @ts-ignore
s8 = null; s0 = peg$f7(s3, s5);
}
// @ts-ignore
s5 = [s5, s6, s7, s8];
// @ts-ignore
s4 = s5;
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s4;
// @ts-ignore
s4 = peg$FAILED;
}
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s4;
// @ts-ignore
s4 = peg$FAILED;
}
}
// @ts-ignore
s4 = peg$parse_();
// @ts-ignore
if (s4 === peg$FAILED) {
// @ts-ignore
s4 = null;
}
// @ts-ignore
s5 = peg$parseFixBinding();
// @ts-ignore
if (s5 === peg$FAILED) {
// @ts-ignore
s5 = null;
}
// @ts-ignore
s6 = peg$parse_();
// @ts-ignore
if (s6 === peg$FAILED) {
// @ts-ignore
s6 = null;
}
// @ts-ignore
s7 = peg$parseRBRACKET();
// @ts-ignore
if (s7 !== peg$FAILED) {
// @ts-ignore
peg$savedPos = s0;
// @ts-ignore
s0 = peg$f7(s3, s5);
// @ts-ignore
} else {
// @ts-ignore
peg$currPos = s0;
// @ts-ignore
s0 = peg$FAILED;
}
// @ts-ignore // @ts-ignore
} else { } else {
// @ts-ignore // @ts-ignore
@ -5112,24 +5134,29 @@ export type ContinuationExpression =
| SwitchExpression | SwitchExpression
| PrimitiveOperationExpression; | PrimitiveOperationExpression;
export type SelectExpression = { export type SelectExpression = {
select: Integer; select: {
val: Value; record: Integer;
bind: Identifier; val: Value;
continuation: ContinuationExpression; bind: Identifier;
continuation: ContinuationExpression;
};
}; };
export type OffsetExpression = { export type OffsetExpression = {
offset: Integer; offset: {
val: Value; index: Integer;
bind: Identifier; val: Value;
continuation: ContinuationExpression; bind: Identifier;
continuation: ContinuationExpression;
};
}; };
export type IdentifierList = any[]; export type IdentifierList = any[];
export type ValueList = any[]; export type ValueList = any[];
export type SwitchExpression = { export type SwitchExpression = {
switchIndex: Value; switch: { switchIndex: Value; continuations: ContinuationList };
continuations: ContinuationList; };
export type ApplicationExpression = {
application: { fn: Value; args: ValueList };
}; };
export type ApplicationExpression = { fn: Value; args: ValueList };
export type FixBinding = [ export type FixBinding = [
LPAREN, LPAREN,
_ | null, _ | null,
@ -5147,15 +5174,16 @@ export type FixBinding = [
]; ];
export type FixBindingList = any[]; export type FixBindingList = any[];
export type FixExpression = { export type FixExpression = {
fixBindings: FixBindingList; fix: { fixBindings: FixBindingList; continuation: ContinuationExpression };
continuation: ContinuationExpression;
}; };
export type ContinuationList = any[]; export type ContinuationList = any[];
export type PrimitiveOperationExpression = { export type PrimitiveOperationExpression = {
opr: PrimitiveOperation; primitiveOperation: {
operands: ValueList; opr: PrimitiveOperation;
resultBindings: IdentifierList; operands: ValueList;
continuations: ContinuationList; resultBindings: IdentifierList;
continuations: ContinuationList;
};
}; };
export type RecordExpressionTuple = { export type RecordExpressionTuple = {
variable: VarStatement; variable: VarStatement;
@ -5163,9 +5191,11 @@ export type RecordExpressionTuple = {
}; };
export type RecordExpressionTupleList = any[]; export type RecordExpressionTupleList = any[];
export type RecordExpression = { export type RecordExpression = {
records: RecordExpressionTupleList; record: {
address: Literal; records: RecordExpressionTupleList;
body: ContinuationExpression; address: Literal;
body: ContinuationExpression;
};
}; };
export type Value = export type Value =
| VarStatement | VarStatement

8
test/logger.ts Normal file
View File

@ -0,0 +1,8 @@
import { ConsoleTracingLogger } from '@/utils';
export const testingLogger = new ConsoleTracingLogger('test', [
'info',
'warn',
'error',
'debug',
]);

7
test/parser.spec.ts Normal file
View File

@ -0,0 +1,7 @@
import { expect, test } from 'bun:test';
import { TestPrograms } from './programs';
import { peggyParse } from '@/parser';
test('Primitive Operations', async () => {
const ast = peggyParse(await TestPrograms.AddOneThree);
});

View File

@ -0,0 +1,2 @@
PRIMOP(+, [INT 1, INT 2], [u],
[APP(LABEL identity, [VAR u])])

7
test/programs/index.ts Normal file
View File

@ -0,0 +1,7 @@
import { join } from 'path';
export namespace TestPrograms {
export const AddOneThree = Bun.file(
join(import.meta.dir + '/add-1-3.cps'),
).text();
}