From df07164f81d9636b32caf331250fe2285a8ce57e Mon Sep 17 00:00:00 2001 From: Benny van Reeven Date: Sat, 9 Dec 2017 17:41:37 +0100 Subject: [PATCH] Add support for typed languages By defining a type such as the following: type MyLanguageSpec = { FooRule: Foo; BarRule: Bar; StringRule: string; } and passing that as the type parameter to createLanguage, both the resulting language and the language passed into every parser rule will be typed. --- types/parsimmon/index.d.ts | 9 ++++++ types/parsimmon/parsimmon-tests.ts | 47 +++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/types/parsimmon/index.d.ts b/types/parsimmon/index.d.ts index a65be6de03..3ec225f38d 100644 --- a/types/parsimmon/index.d.ts +++ b/types/parsimmon/index.d.ts @@ -82,6 +82,14 @@ declare namespace Parsimmon { [key: string]: Parser; } + type TypedRule = { + [P in keyof TLanguageSpec]: (r: TypedLanguage) => Parser; + }; + + type TypedLanguage = { + [P in keyof TLanguageSpec]: Parser; + }; + interface Parser { /** * parse the string @@ -192,6 +200,7 @@ declare namespace Parsimmon { * Starting point for building a language parser in Parsimmon */ function createLanguage(rules: Rule): Language; + function createLanguage(rules: TypedRule): TypedLanguage; /** * To be used inside of Parsimmon(fn). Generates an object describing how diff --git a/types/parsimmon/parsimmon-tests.ts b/types/parsimmon/parsimmon-tests.ts index a923364aad..c6dbaec22c 100644 --- a/types/parsimmon/parsimmon-tests.ts +++ b/types/parsimmon/parsimmon-tests.ts @@ -1,5 +1,5 @@ import P = require('parsimmon'); -import { Parser, Mark, Result, Index, Reply, Language } from "parsimmon"; +import { Parser, Mark, Result, Index, Reply, Language, TypedLanguage } from "parsimmon"; // -- -- -- -- -- -- -- -- -- -- -- -- -- @@ -201,6 +201,45 @@ language = P.createLanguage({ AnotherRule: () => P.string(""), }); -anyPar = language.SomeRule; -anyPar = language.AnotherRule; -anyPar = language.UndefinedRule; +// $ExpectType Parser +language.SomeRule; +// $ExpectType Parser +language.AnotherRule; +// $ExpectType Parser +language.UndefinedRule; + +interface MyLanguageSpec { + FooRule: Foo; + BarRule: Bar; + StringRule: string; +} + +let myLanguage: TypedLanguage; + +myLanguage = P.createLanguage({ + FooRule: r => { + fooPar = r.FooRule; + barPar = r.BarRule; + strPar = r.StringRule; + return fooPar; + }, + BarRule: r => barPar, + StringRule: () => strPar, +}); + +// $ExpectType Parser +myLanguage.FooRule; +// $ExpectType Parser +myLanguage.BarRule; +// $ExpectType Parser +myLanguage.StringRule; + +const noRules = P.createLanguage<{}>({}); + +// $ExpectError +P.createLanguage<{MissingRule: string}>({}); + +P.createLanguage<{SomeRule: string}>({ + SomeRule: r => strPar, + AnotherRule: (r: any) => strPar // $ExpectError +});