Finish concept JSON parser

This now can parse JSON correctly in various configurations.
This commit is contained in:
Sam Atkins 2024-05-24 12:06:10 +01:00
parent 7fccf79591
commit 03123faa8a

View File

@ -172,15 +172,13 @@ export default {
}, },
execute: async ctx => { execute: async ctx => {
const { in_, out, err } = ctx.externs; const { in_, out, err } = ctx.externs;
await out.write("STARTING CONCEPT PARSER\n");
const grammar_context = new GrammarContext(standard_parsers()); const grammar_context = new GrammarContext(standard_parsers());
await out.write("Constructed a grammar context\n");
const parser = grammar_context.define_parser({ const parser = grammar_context.define_parser({
element: a => a.sequence( element: a => a.sequence(
a.symbol('whitespace'), a.optional(a.symbol('whitespace')),
a.symbol('value'), a.symbol('value'),
a.symbol('whitespace'), a.optional(a.symbol('whitespace')),
), ),
value: a => a.firstMatch( value: a => a.firstMatch(
a.symbol('object'), a.symbol('object'),
@ -193,37 +191,33 @@ export default {
), ),
array: a => a.sequence( array: a => a.sequence(
a.literal('['), a.literal('['),
a.symbol('whitespace'), a.firstMatch(
a.optional(
a.repeat( a.repeat(
a.symbol('element'), a.symbol('element'),
a.literal(','), a.literal(','),
{ trailing: true }, { trailing: false },
), ),
a.optional(a.symbol('whitespace')),
), ),
a.symbol('whitespace'),
a.literal(']'), a.literal(']'),
), ),
member: a => a.sequence( member: a => a.sequence(
a.symbol('whitespace'), a.optional(a.symbol('whitespace')),
a.symbol('string'), a.symbol('string'),
a.symbol('whitespace'), a.optional(a.symbol('whitespace')),
a.literal(':'), a.literal(':'),
a.symbol('whitespace'), a.symbol('element'),
a.symbol('value'),
a.symbol('whitespace'),
), ),
object: a => a.sequence( object: a => a.sequence(
a.literal('{'), a.literal('{'),
a.symbol('whitespace'), a.firstMatch(
a.optional(
a.repeat( a.repeat(
a.symbol('member'), a.symbol('member'),
a.literal(','), a.literal(','),
{ trailing: true }, { trailing: false },
), ),
a.optional(a.symbol('whitespace')),
), ),
a.symbol('whitespace'),
a.literal('}'), a.literal('}'),
), ),
true: a => a.literal('true'), true: a => a.literal('true'),
@ -231,37 +225,31 @@ export default {
null: a => a.literal('null'), null: a => a.literal('null'),
number: a => new NumberParser(), number: a => new NumberParser(),
string: a => new StringParser(), string: a => new StringParser(),
whitespace: a => a.optional( whitespace: a => a.stringOf(c => ' \r\n\t'.includes(c)),
a.stringOf(c => ' \r\n\t'.includes(c)),
),
}, { }, {
element: it => it[0].value, element: it => it.filter(it => it.$ === 'value')[0].value,
value: it => it, value: it => it,
array: it => { array: it => {
// A parsed array contains 3 values: `[`, the entries array, and `]`, so we only care about index 1. // A parsed array contains 3 values: `[`, the entries array, and `]`, so we only care about index 1.
// If it's less than 3, there were no entries. // If it's less than 3, there were no entries.
if (it.length < 3) return []; if (it.length < 3) return [];
return (it[1].value || []) return (it[1].value || [])
.filter(it => it.$ !== 'literal') .filter(it => it.$ === 'element')
.map(it => it.value); .map(it => it.value);
}, },
member: it => { member: it => {
// A parsed member contains 3 values: a name, `:`, and a value. const [ name_part, value_part ] = it.filter(it => it.$ === 'string' || it.$ === 'element');
const [ name_part, colon, value_part ] = it;
return { name: name_part.value, value: value_part.value }; return { name: name_part.value, value: value_part.value };
}, },
object: it => { object: it => {
console.log('OBJECT!!!!');
console.log(it[1]);
// A parsed object contains 3 values: `{`, the members array, and `}`, so we only care about index 1. // A parsed object contains 3 values: `{`, the members array, and `}`, so we only care about index 1.
// If it's less than 3, there were no members. // If it's less than 3, there were no members.
if (it.length < 3) return {}; if (it.length < 3) return {};
const result = {}; const result = {};
// FIXME: This is all wrong!!!
(it[1].value || []) (it[1].value || [])
.filter(it => it.$ === 'member') .filter(it => it.$ === 'member')
.forEach(it => { .forEach(it => {
result[it.name] = it.value; result[it.value.name] = it.value.value;
}); });
return result; return result;
}, },