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.
This commit is contained in:
Benny van Reeven
2017-12-09 18:42:10 +01:00
parent 4e800c3dc5
commit df07164f81
2 changed files with 52 additions and 4 deletions
+9
View File
@@ -82,6 +82,14 @@ declare namespace Parsimmon {
[key: string]: Parser<any>;
}
type TypedRule<TLanguageSpec> = {
[P in keyof TLanguageSpec]: (r: TypedLanguage<TLanguageSpec>) => Parser<TLanguageSpec[P]>;
};
type TypedLanguage<TLanguageSpec> = {
[P in keyof TLanguageSpec]: Parser<TLanguageSpec[P]>;
};
interface Parser<T> {
/**
* 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<TLanguageSpec>(rules: TypedRule<TLanguageSpec>): TypedLanguage<TLanguageSpec>;
/**
* To be used inside of Parsimmon(fn). Generates an object describing how
+43 -4
View File
@@ -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<any>
language.SomeRule;
// $ExpectType Parser<any>
language.AnotherRule;
// $ExpectType Parser<any>
language.UndefinedRule;
interface MyLanguageSpec {
FooRule: Foo;
BarRule: Bar;
StringRule: string;
}
let myLanguage: TypedLanguage<MyLanguageSpec>;
myLanguage = P.createLanguage<MyLanguageSpec>({
FooRule: r => {
fooPar = r.FooRule;
barPar = r.BarRule;
strPar = r.StringRule;
return fooPar;
},
BarRule: r => barPar,
StringRule: () => strPar,
});
// $ExpectType Parser<Foo>
myLanguage.FooRule;
// $ExpectType Parser<Bar>
myLanguage.BarRule;
// $ExpectType Parser<string>
myLanguage.StringRule;
const noRules = P.createLanguage<{}>({});
// $ExpectError
P.createLanguage<{MissingRule: string}>({});
P.createLanguage<{SomeRule: string}>({
SomeRule: r => strPar,
AnotherRule: (r: any) => strPar // $ExpectError
});