Browse Source

Finish concept JSON parser

This now can parse JSON correctly in various configurations.
Sam Atkins 1 year ago
parent
commit
03123faa8a
1 changed files with 16 additions and 28 deletions
  1. 16 28
      packages/phoenix/src/puter-shell/coreutils/concept-parser.js

+ 16 - 28
packages/phoenix/src/puter-shell/coreutils/concept-parser.js

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