Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Talk about common initiative with HOTScript #30

Closed
ecyrbe opened this issue Jun 24, 2023 · 3 comments
Closed

Talk about common initiative with HOTScript #30

ecyrbe opened this issue Jun 24, 2023 · 3 comments

Comments

@ecyrbe
Copy link

ecyrbe commented Jun 24, 2023

Hello Mike,

with gabriel vergnaud, we have have created HOTScript, and also created a parser combinator.
I successfully made it allow recursive definition:
gvergnaud/hotscript#78

example :

     // The grammar is defined as a recursive grammar:
      // -------------------------------------------------------------
      // | Value = Object | Array | String | Number | Boolean | Null |
      // | Object = { (Pair (, Pair)*)? }                            |
      // | Pair = String : Value                                     |
      // | Array = [ (Value (, Value)*)? ]                           |
      // | String = " Character* "                                   |
      // | Character = any character except "                        |
      // | Number = -? Digits ( . Digits )?                          |
      // | Boolean = true | false                                    |
      // | Null = null                                               |
      // -------------------------------------------------------------
      type Value = P.Choice<
        [JSonObject, JSonArray, JSonString, JSonNumber, JsonBoolean, JSonNull]
      >;
      type JSonObject = P.Map<
        P.Sequence<
          [
            P.Trim<P.Skip<P.Literal<"{">>>,
            P.Optional<P.SepBy<JSonPair, P.Trim<P.Literal<",">>>>,
            P.Trim<P.Skip<P.Literal<"}">>>
          ]
        >,
        Objects.FromArray
      >;
      type JSonPair = P.Sequence<
        [JSonString, P.Trim<P.Skip<P.Literal<":">>>, Value]
      >;
      type JSonArray = P.Map<
        P.Sequence<
          [
            P.Trim<P.Skip<P.Literal<"[">>>,
            P.Optional<P.SepBy<Value, P.Trim<P.Literal<",">>>>,
            P.Trim<P.Skip<P.Literal<"]">>>
          ]
        >,
        Objects.Create<[arg0]>
      >;

      type JSonString = P.Map<
        P.Between<
          P.TrimLeft<P.Skip<P.Literal<'"'>>>,
          P.Many<P.NotLiteral<'"'>>,
          P.TrimRight<P.Skip<P.Literal<'"'>>>
        >,
        Tuples.Join<"">
      >;

      type JSonNumber = P.Map<
        P.Sequence<
          [
            P.Optional<P.Literal<"-" | "+">>,
            P.Digits,
            P.Optional<P.Sequence<[P.Literal<".">, P.Digits]>>
          ]
        >,
        ComposeLeft<[Tuples.Join<"">, Strings.ToNumber]>
      >;
      type JsonBoolean = P.Map<
        P.Literal<"true" | "false">,
        Match<[Match.With<"true", true>, Match.With<"false", false>]>
      >;
      type JSonNull = P.Map<P.Literal<"null">, Constant<null>>;

      type Json<T extends string> = Eval<
        P.Parse<P.Map<P.Sequence<[Value, P.EndOfInput]>, Tuples.At<0>>, T>
      >;

      type res1 = Json<`{"hello": " world! with @", "foo": [1.4, 2, 3]}`>;
      //   ^?
      type test1 = Expect<
        Equal<res1, { hello: " world! with @"; foo: [1.4, 2, 3] }>
      >;
      type res2 = Json<`[]`>;
      //   ^?
      type test2 = Expect<Equal<res2, []>>;
      type res3 = Json<`{}`>;
      //   ^?
      type test3 = Expect<Equal<res3, {}>>;
      // 4 deep nested objects
      type res4 = Json<`{"a": {"b": {"c": {"d": 8}}}}`>;
      //   ^?
      type test4 = Expect<Equal<res4, { a: { b: { c: { d: 8 } } } }>>;

but it fails to parse too deep json structures.
did you succeed to make arbitrary big json parsing ?

if you would like we can discuss on HOTScript discord : https://discord.gg/VXESFdD2

@poteat
Copy link
Owner

poteat commented Jul 4, 2023

Nope, not at all unfortunately! JSON is still heavily limited in supported size when built out using parser combinators

@ecyrbe
Copy link
Author

ecyrbe commented Jul 6, 2023

Thanks for the feedback. I hoped you had found something we didn't. The search continues then.

One tip for you about implementing recursive grammars like EBNF, there is a neat trick that delays TS evaluation to allow recursive declarations to not trigger TS recursive and maybe infinitive errors.
Don't put any constraints on parameters. they trigger typescript eager evaluation.
example here in your code :
image
delay type checking with extends in the body of your utility type by doing a conditional type check.
This will allow your types to not trigger maybe infinite errors.

@poteat
Copy link
Owner

poteat commented Aug 5, 2023

Thanks for the tip! I created an issue to look into that trick 🤓

I was so delighted to find other folks explore the type-level parser combinator space - kudos :D

@poteat poteat closed this as completed Aug 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants