Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: IntrinsicLabsAI/gbnfgen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.10.0
Choose a base ref
...
head repository: IntrinsicLabsAI/gbnfgen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.11.0
Choose a head ref
  • 3 commits
  • 6 files changed
  • 2 contributors

Commits on Oct 30, 2023

  1. Fix badge

    a10y authored Oct 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8962374 View commit details

Commits on Dec 20, 2023

  1. Bump vitest from 0.34.6 to 1.1.0 (#20)

    Bumps
    [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest)
    from 0.34.6 to 1.1.0.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/vitest-dev/vitest/releases">vitest's
    releases</a>.</em></p>
    <blockquote>
    <h2>v1.1.0</h2>
    <h3>   🚀 Features</h3>
    <ul>
    <li>Add es-main compatibility to vite-node  -  by <a
    href="https://github.com/zookatron"><code>@​zookatron</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4751">vitest-dev/vitest#4751</a>
    <a href="https://github.com/vitest-dev/vitest/commit/486a3e61"><!-- raw
    HTML omitted -->(486a3)<!-- raw HTML omitted --></a></li>
    <li>Add --workspace option, fix root resolution in workspaces  -  by <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
    <a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
    <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4773">vitest-dev/vitest#4773</a>
    <a href="https://github.com/vitest-dev/vitest/commit/67d93eda"><!-- raw
    HTML omitted -->(67d93)<!-- raw HTML omitted --></a></li>
    <li>Add --no-file-parallelism, --maxWorkers, --minWorkers flags  -  by
    <a href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a>
    and <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4705">vitest-dev/vitest#4705</a>
    <a href="https://github.com/vitest-dev/vitest/commit/fd5d7e66"><!-- raw
    HTML omitted -->(fd5d7)<!-- raw HTML omitted --></a></li>
    <li>Add --no-isolate flag to improve performance, add documentation
    about performance  -  by <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a>, <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> and
    <strong>Pascal Jufer</strong> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4777">vitest-dev/vitest#4777</a>
    <a href="https://github.com/vitest-dev/vitest/commit/4d55a026"><!-- raw
    HTML omitted -->(4d55a)<!-- raw HTML omitted --></a></li>
    <li>Add <code>--exclude</code> CLI flag  -  by <a
    href="https://github.com/Namchee"><code>@​Namchee</code></a> and <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
    <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4279">vitest-dev/vitest#4279</a>
    <a href="https://github.com/vitest-dev/vitest/commit/f859efc0"><!-- raw
    HTML omitted -->(f859e)<!-- raw HTML omitted --></a></li>
    </ul>
    <h3>   🐞 Bug Fixes</h3>
    <ul>
    <li>Correctly reset provided values  -  by <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
    <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4775">vitest-dev/vitest#4775</a>
    <a href="https://github.com/vitest-dev/vitest/commit/5a71eb30"><!-- raw
    HTML omitted -->(5a71e)<!-- raw HTML omitted --></a></li>
    <li><strong>expect</strong>:
    <ul>
    <li>Fix <code>toHaveProperty</code> assertion error diff  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4734">vitest-dev/vitest#4734</a>
    <a href="https://github.com/vitest-dev/vitest/commit/f8f70f7c"><!-- raw
    HTML omitted -->(f8f70)<!-- raw HTML omitted --></a></li>
    </ul>
    </li>
    <li><strong>runner</strong>:
    <ul>
    <li>Handle fixture teardown error  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4683">vitest-dev/vitest#4683</a>
    <a href="https://github.com/vitest-dev/vitest/commit/c6f5f7f9"><!-- raw
    HTML omitted -->(c6f5f)<!-- raw HTML omitted --></a></li>
    </ul>
    </li>
    <li><strong>types</strong>:
    <ul>
    <li><code>defineWorkspace</code> fix intellisense and report type errors
     -  by <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4743">vitest-dev/vitest#4743</a>
    <a href="https://github.com/vitest-dev/vitest/commit/9cc36689"><!-- raw
    HTML omitted -->(9cc36)<!-- raw HTML omitted --></a></li>
    </ul>
    </li>
    <li><strong>ui</strong>:
    <ul>
    <li>Escape html for console log view  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4724">vitest-dev/vitest#4724</a>
    <a href="https://github.com/vitest-dev/vitest/commit/e0dde6ab"><!-- raw
    HTML omitted -->(e0dde)<!-- raw HTML omitted --></a></li>
    <li>Fix coverage iframe url for html report preview  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4717">vitest-dev/vitest#4717</a>
    <a href="https://github.com/vitest-dev/vitest/commit/71911039"><!-- raw
    HTML omitted -->(71911)<!-- raw HTML omitted --></a></li>
    <li>Show file item when search filter matches only test cases  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4736">vitest-dev/vitest#4736</a>
    <a href="https://github.com/vitest-dev/vitest/commit/f43fdd87"><!-- raw
    HTML omitted -->(f43fd)<!-- raw HTML omitted --></a></li>
    </ul>
    </li>
    <li><strong>vitest</strong>:
    <ul>
    <li>Pass down CLI options to override workspace configs  -  by <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
    <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4774">vitest-dev/vitest#4774</a>
    <a href="https://github.com/vitest-dev/vitest/commit/8dabef86"><!-- raw
    HTML omitted -->(8dabe)<!-- raw HTML omitted --></a></li>
    </ul>
    </li>
    </ul>
    <h5>    <a
    href="https://github.com/vitest-dev/vitest/compare/v1.0.4...v1.1.0">View
    changes on GitHub</a></h5>
    <h2>v1.0.4</h2>
    <p>The previous release was built incorrectly and didn't include the
    performance fix. This release fixes that.</p>
    <h3>   🐞 Bug Fixes</h3>
    <ul>
    <li><strong>cli</strong>: <code>--coverage.all=false</code> resolved
    incorrectly  -  by <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4697">vitest-dev/vitest#4697</a>
    <a href="https://github.com/vitest-dev/vitest/commit/a7931bbf"><!-- raw
    HTML omitted -->(a7931)<!-- raw HTML omitted --></a></li>
    </ul>
    <h3>   🏎 Performance</h3>
    <ul>
    <li><strong>reporters</strong>: Downgrade <code>log-update</code> to v5
     -  by <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4711">vitest-dev/vitest#4711</a>
    <a href="https://github.com/vitest-dev/vitest/commit/13ff97a3"><!-- raw
    HTML omitted -->(13ff9)<!-- raw HTML omitted --></a></li>
    </ul>
    <h5>    <a
    href="https://github.com/vitest-dev/vitest/compare/v1.0.3...v1.0.4">View
    changes on GitHub</a></h5>
    <h2>v1.0.3</h2>
    <h3>   🐞 Bug Fixes</h3>
    <ul>
    <li>Correct package exports  -  by <a
    href="https://github.com/userquin"><code>@​userquin</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4707">vitest-dev/vitest#4707</a>
    <a href="https://github.com/vitest-dev/vitest/commit/37388d69"><!-- raw
    HTML omitted -->(37388)<!-- raw HTML omitted --></a></li>
    <li><strong>runner</strong>: Fix async fixture teardown  -  by <a
    href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4700">vitest-dev/vitest#4700</a>
    <a href="https://github.com/vitest-dev/vitest/commit/92afd54c"><!-- raw
    HTML omitted -->(92afd)<!-- raw HTML omitted --></a></li>
    <li><strong>vitest</strong>: Correctly filter changed files when Vitest
    workspace is used  -  by <a
    href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
    <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4693">vitest-dev/vitest#4693</a>
    <a href="https://github.com/vitest-dev/vitest/commit/3413518b"><!-- raw
    HTML omitted -->(34135)<!-- raw HTML omitted --></a></li>
    </ul>
    <h3>   🏎 Performance</h3>
    <ul>
    <li><strong>reporters</strong>: Downgrade <code>log-update</code> to v5
     -  by <a
    href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
    href="https://redirect.github.com/vitest-dev/vitest/issues/4711">vitest-dev/vitest#4711</a>
    <a href="https://github.com/vitest-dev/vitest/commit/13ff97a3"><!-- raw
    HTML omitted -->(13ff9)<!-- raw HTML omitted --></a></li>
    </ul>
    <!-- raw HTML omitted -->
    </blockquote>
    <p>... (truncated)</p>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/9497f484cf55392cac224fe0d049d8d5242f9564"><code>9497f48</code></a>
    chore: release v1.1.0</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/e975b5729fbd519fe1dec2c8f9e40f75bdba2251"><code>e975b57</code></a>
    types: use satisfies for defaults (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4738">#4738</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/f859efc0940f6e72766b56f528975f62578f8762"><code>f859efc</code></a>
    feat: add <code>--exclude</code> CLI flag (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4279">#4279</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/4d55a026d2d5d1920018c9b79a6d969b875fa11e"><code>4d55a02</code></a>
    feat: add --no-isolate flag to improve performance, add documentation
    about p...</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/fd5d7e66e4a90f3048f50b1ef86330522d6c9b2c"><code>fd5d7e6</code></a>
    feat: add --no-file-parallelism, --maxWorkers, --minWorkers flags (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4705">#4705</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/67d93eda66c73b49af210ad8a117ecfceaa81a3d"><code>67d93ed</code></a>
    feat: add --workspace option, fix root resolution in workspaces (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4773">#4773</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/8dabef860a3f51f5a4c4debc10faa1837fdcdd71"><code>8dabef8</code></a>
    fix(vitest): pass down CLI options to override workspace configs (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4774">#4774</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/5a71eb303815101e253a0cca9c256d9691dcc508"><code>5a71eb3</code></a>
    fix: correctly reset provided values (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4775">#4775</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/9cc3668960ad8cb44dcb0745047673e0196d038b"><code>9cc3668</code></a>
    fix(types): <code>defineWorkspace</code> fix intellisense and report
    type errors (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4743">#4743</a>)</li>
    <li><a
    href="https://github.com/vitest-dev/vitest/commit/9c552b6f8decb78677b20e870eb430184e0b78ea"><code>9c552b6</code></a>
    chore(deps): update dependency <code>@​types/prompts</code> to ^2.4.9
    (<a
    href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/4720">#4720</a>)</li>
    <li>Additional commits viewable in <a
    href="https://github.com/vitest-dev/vitest/commits/v1.1.0/packages/vitest">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vitest&package-manager=npm_and_yarn&previous-version=0.34.6&new-version=1.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    
    
    </details>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Dec 20, 2023
    Copy the full SHA
    7c8c429 View commit details

Commits on Feb 14, 2024

  1. Add support for union type literals in general (#28)

    a10y authored Feb 14, 2024
    Copy the full SHA
    aa9c033 View commit details
Showing with 720 additions and 265 deletions.
  1. +1 −1 README.md
  2. +604 −222 package-lock.json
  3. +1 −1 package.json
  4. +21 −0 src/compiler.test.ts
  5. +69 −41 src/compiler.ts
  6. +24 −0 src/grammar.ts
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![logo](./logo.png)

[![npm version](https://badge.fury.io/js/@intrinsicai%2Fgbnfgen.svg)](https://badge.fury.io/js/@intrinsicai%2Fgbnfgen)
[![npm](https://img.shields.io/npm/v/@intrinsicai%2Fgbnfgen.svg)](https://www.npmjs.com/package/@intrinsicai/gbnfgen)
[![NPM Publish](https://github.com/IntrinsicLabsAI/gbnfgen/actions/workflows/npm.yml/badge.svg)](https://github.com/IntrinsicLabsAI/gbnfgen/actions/workflows/npm.yml)


826 changes: 604 additions & 222 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
"vitest": "^0.34.0"
"vitest": "^1.1.0"
},
"dependencies": {
"ts-morph": "^20.0.0"
21 changes: 21 additions & 0 deletions src/compiler.test.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,27 @@ import { expect, test } from "vitest";
import { compile, compileSync } from "./compiler.js";
import { serializeGrammar } from "./grammar.js";

test("union types", () => {
const grammar = compileSync(`
interface Person {
age: number[] | string[];
}
`, "Person"
);

expect(serializeGrammar(grammar).trimEnd()).toEqual(
String.raw`
root ::= Person
Person ::= "{" ws "\"age\":" ws ( stringlist | numberlist ) "}"
Personlist ::= "[]" | "[" ws Person ("," ws Person)* "]"
string ::= "\"" ([^"]*) "\""
boolean ::= "true" | "false"
ws ::= [ \t\n]*
number ::= [0-9]+ "."? [0-9]*
stringlist ::= "[" ws "]" | "[" ws string ("," ws string)* ws "]"
numberlist ::= "[" ws "]" | "[" ws string ("," ws number)* ws "]"`.trim())
});

test("Single interface generation", () => {
const postalAddressGrammar = compileSync(
`interface PostalAddress {
110 changes: 69 additions & 41 deletions src/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
import { Project, ts, InterfaceDeclaration, EnumDeclaration } from "ts-morph";
import {
Grammar,
GrammarElement,
GrammarRule,
RuleReference,
group,
literal,
reference,
sequence,
} from "./grammar.js";
import { EnumDeclaration, InterfaceDeclaration, Project, ts } from "ts-morph";
import { alternatives, Grammar, GrammarElement, GrammarRule, group, literal, reference, sequence, } from "./grammar.js";

import {
toElementId,
toListElementId,
WS_REF,
getDefaultGrammar,
GrammarRegister,
registerToGrammar,
toElementId,
toListElementId,
WS_REF,
} from "./util.js";

// Turn interface properties into Grammar References
export function toGrammar(iface: Interface): Grammar {

function inferReferenceRule(propType: PropertyType) {
if (propType.type === "simple") {
return reference(propType.name);
}

if (propType.type === "array") {
return reference(toListElementId(propType.reference));
}

throw new Error(`Expected a simple or array type, received ${propType}`);
}

function propertyRules(prop: InterfaceProperty): Array<GrammarRule> {
const { name, type } = prop;
let typeRef: RuleReference;
let typeRef: GrammarRule;

// TODO: Throw exception error if grammar type not found ?
if (typeof type === "string") {
typeRef = reference(type);
} else if (type.isArray) {
typeRef = reference(toListElementId(type.reference));
if (type.type === "union") {
typeRef = alternatives(
...type.refs.map(propType => inferReferenceRule(propType))
);
} else {
typeRef = reference(toElementId(type.reference));
typeRef = inferReferenceRule(type);
}

return [WS_REF, literal(`"${name}":`), WS_REF, typeRef];
@@ -75,7 +78,10 @@ export function toGrammar(iface: Interface): Grammar {
}

// Parameterized list of things
export type PropertyType = string | { reference: string; isArray: boolean };
export type PropertyType =
| { type: "simple", name: string }
| { type: "array", reference: string }
| { type: "union", refs: PropertyType[] };

export interface InterfaceProperty {
name: string;
@@ -109,6 +115,34 @@ function handleEnum(enumNode: EnumDeclaration): GrammarElement {
return { identifier: enumNode.getName(), alternatives: choices };
}

/**
* Infer {@link PropertyType} from a declared property name or set of property names.
*/
function inferPropType(
register: Map<string, Array<GrammarRule>>,
propType: string,
declaredTypes: Set<string>,
declaredArrayTypes: Map<string, string>,
propName: string
): PropertyType {
if (register.has(propType)) {
return { type: "simple", name: propType };
} else if (propType === "string[]" || propType === "Array<string>") {
return { type: "simple", name: "stringlist" };
} else if (propType === "number[]" || propType === "Array<number>") {
return { type: "simple", name: "numberlist" };
} else if (declaredTypes.has(propType)) {
return { type: "simple", name: propType };
} else if (declaredArrayTypes.has(propType)) {
const baseType = declaredArrayTypes.get(propType)!;
return { type: "array", reference: baseType };
}

throw new Error(
`Failed validating parameter ${propName}: unsupported type ${propType}`
);
}

function handleInterface(
iface: InterfaceDeclaration,
declaredTypes: Set<string>,
@@ -118,6 +152,7 @@ function handleInterface(
const declaredArrayTypes: Map<string, string> = new Map();
for (const declType of declaredTypes) {
declaredArrayTypes.set(`${declType}[]`, declType);
declaredArrayTypes.set(`Array<${declType}>`, declType);
}

if (iface.getTypeParameters().length > 0) {
@@ -137,24 +172,18 @@ function handleInterface(
const propName = child.getName();
const propType = child.getType().getText();

// Validate one of the accepted types
let propTypeValidated: PropertyType;
if (register.has(propType)) {
propTypeValidated = propType;
} else if (propType === "string[]" || propType === "Array<string>") {
propTypeValidated = "stringlist";
} else if (propType === "number[]" || propType === "Array<number>") {
propTypeValidated = "numberlist";
} else if (declaredTypes.has(propType)) {
propTypeValidated = { reference: propType, isArray: false };
} else if (declaredArrayTypes.has(propType)) {
const baseType = declaredArrayTypes.get(propType)!;
propTypeValidated = { reference: baseType, isArray: true };
} else {
throw new Error(
`Failed validating parameter ${propName}: unsupported type ${propType}`
);
}
const unionTypes = (child.getType().isUnion() && !child.getType().isEnum() && !child.getType().isBoolean())
? child.getType().getUnionTypes().map(typ => typ.getText(child))
: [];

// Properties can either be simple singular types, or union types
let propTypeValidated: PropertyType = unionTypes.length === 0
? inferPropType(register, propType, declaredTypes, declaredArrayTypes, propName)
: {
type: "union",
refs: unionTypes.map(typ => inferPropType(register, typ, declaredTypes, declaredArrayTypes, propName))
};

props.push({
name: propName,
type: propTypeValidated,
@@ -169,7 +198,6 @@ function handleInterface(

/**
* Async variant of main compilation function, targeting {@link Grammar} type from raw TypeScript interface source code.
* @param source
* @returns
*/
export async function compile(
24 changes: 24 additions & 0 deletions src/grammar.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ export interface GrammarElement {

export type GrammarRule =
| RuleSequence
| RuleAlternatives
| RuleGroup
| RuleLiteral
| RuleReference
@@ -19,6 +20,11 @@ export interface RuleSequence {
rules: Array<GrammarRule>;
}

export interface RuleAlternatives {
type: "alt";
rules: Array<GrammarRule>;
}

export interface RuleGroup {
type: "group";
rules: RuleSequence;
@@ -44,6 +50,10 @@ export function isSequence(rule: GrammarRule): rule is RuleSequence {
return rule.type === "sequence";
}

export function isAlternatives(rule: GrammarRule): rule is RuleAlternatives {
return rule.type === "alt";
}

export function isGroup(rule: GrammarRule): rule is RuleGroup {
return rule.type === "group";
}
@@ -65,6 +75,8 @@ function serializeRule(rule: GrammarRule): string {
return serializeSequence(rule);
} else if (isGroup(rule)) {
return serializeGroup(rule);
} else if (isAlternatives(rule)) {
return serializeAlternatives(rule)
} else if (isLiteral(rule)) {
return serializeLiteralRule(rule);
} else if (isReference(rule)) {
@@ -89,6 +101,11 @@ function serializeGroup(rule: RuleGroup): string {
return `(${serializeSequence(rule.rules)})${multiplicity}`;
}

function serializeAlternatives(alt: RuleAlternatives): string {
const alternatives = alt.rules.map(rule => serializeRule(rule));
return "( " + alternatives.join(" | ") + " )";
}

function serializeLiteralRule(rule: RuleLiteral): string {
return JSON.stringify(rule.literal);
}
@@ -163,6 +180,13 @@ export function reference(value: string): RuleReference {
};
}

export function alternatives(...values: Array<GrammarRule>): RuleAlternatives {
return {
type: "alt",
rules: values,
}
}

export function group(
rules: RuleSequence,
multiplicity: RuleGroup["multiplicity"]