diff --git a/.dockerignore b/.dockerignore index a10e43d6..120a342d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ Dockerfile **/node_modules/** docker-compose.yml docker-compose.dev.yml +docker/.buildx-cache doc/** .dockerignore **/build diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index e95328ea..8fc32ba3 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -1,11 +1,5 @@ name: Docker Release -# This workflow was largely generated from the following prompt: -# "only run this on merge to main; clone the repo; set the VERSION environment -# variable from packages/runtime/package.json; use `docker manifest inspect` -# to verify the release doesn't already exist; create a multi-platform builder; -# build and push the image" - on: push: branches: [main] @@ -20,7 +14,7 @@ jobs: - name: Get version id: version run: | - echo "VERSION=$(cat packages/runtime/package.json | jq -r '.version')" >> "$GITHUB_OUTPUT" + echo "VERSION=$(cat packages/compiler/package.json | jq -r '.version')" >> "$GITHUB_OUTPUT" - name: Check if image already exists id: check diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 00000000..24565f53 --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,26 @@ +name: Go Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.work + + - name: Compile grammar to wasm + run: ./golang/runtime/generate.sh + + - name: Run Go tests + working-directory: golang/runtime + run: go test ./... \ No newline at end of file diff --git a/.gitignore b/.gitignore index d282e231..4c931b81 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,8 @@ yarn-error.log # api-extractor temp files temp/ + +# Docker buildx local layer cache +docker/.buildx-cache + +.DS_Store diff --git a/README.md b/README.md index 559fe327..5d65b923 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,21 @@ You can use the Ohm CLI without a local Node.js installation via the Docker imag docker run --rm -v $(pwd):/local ohmjs/ohm:latest compile my-grammar.ohm ``` +The `compile` command also supports: + +- **A separate output directory** — mount it at `/dst` and output paths resolve there: + + ```sh + docker run --rm -v $(pwd)/src:/local -v $(pwd)/dst:/dst \ + ohmjs/ohm:latest compile my-grammar.ohm + ``` + +- **Stdin / stdout streaming** — pass `-` as the grammar file to read from stdin; output goes to stdout: + + ```sh + cat my-grammar.ohm | docker run --rm -i ohmjs/ohm:latest compile - > my-grammar.wasm + ``` + For full usage instructions, including how to build the image locally and set up a development container, see [doc/docker.md](doc/docker.md). ### Installation diff --git a/doc/docker.md b/doc/docker.md index d2d9850c..0003d3df 100644 --- a/doc/docker.md +++ b/doc/docker.md @@ -43,6 +43,34 @@ Options: docker run --rm -v $(pwd):/local ohmjs/ohm:latest compile -o arithmetic.wasm arithmetic.ohm ``` +### Separate input and output directories + +Mount a second volume at `/dst` to send the compiled `.wasm` to a different directory than the grammar source. When `/dst` is present, output paths are resolved relative to `/dst`: + +```sh +docker run --rm \ + -v /path/to/src:/local \ + -v /path/to/dst:/dst \ + ohmjs/ohm:latest compile grammar.ohm +# writes /path/to/dst/grammar.wasm +``` + +If `-o` is given as a relative path it is also resolved against `/dst`; absolute paths are used as-is. + +### Reading from stdin / writing to stdout + +Use `-` as the grammar file to read the grammar from stdin. Use `-o -` (or omit `-o` when reading from stdin) to write the wasm bytes to stdout: + +```sh +# pipe grammar in, capture wasm out +cat grammar.ohm | docker run --rm -i ohmjs/ohm:latest compile - > grammar.wasm + +# explicit stdout +docker run --rm -i -v $(pwd):/local ohmjs/ohm:latest compile -o - grammar.ohm > grammar.wasm +``` + +In stdout mode, the CLI's status messages are redirected to stderr so stdout contains only the wasm bytes. + ### Getting help ```sh @@ -80,6 +108,10 @@ Clone the repository and build the production image with Docker Compose: git clone https://github.com/ohmjs/ohm.git cd ohm docker compose -f docker/docker-compose.yml build + +# or +cd ohm/docker +docker compose build ``` This builds the `ohm:latest` image using the `dist` stage of the multi-stage `Dockerfile`, which produces a slim image containing only the compiled packages and their production dependencies. @@ -110,16 +142,16 @@ The `-v $(pwd):/local` mount makes your current directory available at `/local` The `ohm-dev:latest` images is 1.62 GB and is 97% efficient with only 64 MB potentially wasted space. -### Publishing to Docker Hub +### Publishing to Docker Hub (from development machine) + +**Note: it is perferable to have the gha docker-release.yml do this** +But there can be a chicken and egg situation where it is easier to do this from a development machine. Build and push a versioned image to Docker Hub using the git tag as the version: ```sh # if not set default to ohmjs (ie docker hub using the ohmjs org) export DOCKER_REPO= -# if not set defaults to 'development' -export VERSION=$(cat packages/runtime/package.json | jq -r '.version') -# or export VERSION=$(git describe --tag --dirty) # # it might be necessary (particularly on osx) to create a new builder # # the default builder might not support multi-platform builds @@ -129,14 +161,23 @@ export VERSION=$(cat packages/runtime/package.json | jq -r '.version') # # or if already created # docker buildx use ohmjs-builder -# generate a person access token at https://app.docker.com/accounts/millergarym/settings/personal-access-tokens +# generate a person access token at https://app.docker.com/accounts//settings/personal-access-tokens # assuming DHPAT contains your PAT echo $DHPAT | docker login -u --password-stdin cd docker -docker buildx bake --allow=fs.read=.. --push +# if not set defaults to 'development' +export VERSION=$(cat ../packages/compiler/package.json | jq -r '.version') +docker buildx use ohmjs-builder +docker buildx bake \ + --set="*.cache-from=type=local,src=.buildx-cache" \ + --set="*.cache-to=type=local,dest=.buildx-cache,mode=max" \ + --allow=fs.read=.. \ + --push ``` -`git describe --tag --dirty` produces a version string based on the nearest git tag, appending commit info and a `-dirty` suffix if there are uncommitted changes. +Builds use a local layer cache stored in `docker/.buildx-cache`. +On subsequent runs this avoids re-downloading base layers and reinstalling dependencies. +Note the `docker/.buildx-cache` directory is over 1GB, and needs to be cleaned up manually. The defaults in `docker-compose.yml` are `DOCKER_REPO=ohmjs` and `VERSION=development`. See [docker-compose.yml](../docker/docker-compose.yml) for details. diff --git a/doc/releases/ohm-golang-v18.0.md b/doc/releases/ohm-golang-v18.0.md new file mode 100644 index 00000000..3d433800 --- /dev/null +++ b/doc/releases/ohm-golang-v18.0.md @@ -0,0 +1,361 @@ +# Ohm Go v18.0 — API Specification + +This document specifies the Go runtime API for Ohm v18. The Go implementation consumes `.wasm` files produced by the Ohm compiler. This document is the authoritative specification for the implementation; portions marked **[not yet implemented]** describe the target behavior. + +## TL;DR + +Prerequists +- Golang +- Docker (for generating wasm files from ohm source) + +```bash +cd golang/examples +# Step 1 +go generate +# expected output 'Wrote Wasm to my-grammar.wasm' + +# Step 2 +go build +# note, if Step 1 failed, the build will fail with a message '... pattern my-grammar.wasm: no matching files found' + +# Step 3 +./ohmgo-examples +# or +./ohmgo-examples "" +# expected out, 'match failed' or 'match succeeded' +``` + +## Compiling grammars + +In v18 the grammar is compiled to a `.wasm` binary at build time, then loaded at runtime. The compiler is packaged as a Docker image. + +### Command line (Docker) + +The compiler is packaged as a Docker image. Mount your working directory to `/local` and use the `compile` subcommand: + +```bash +docker run --rm -v "$(pwd):/local" ohm:latest compile my-grammar.ohm +# writes my-grammar.wasm in the current directory +``` + +With an explicit output path or grammar name: + +```bash +docker run --rm -v "$(pwd):/local" ohm:latest compile -o out/my-grammar.wasm my-grammar.ohm +docker run --rm -v "$(pwd):/local" ohm:latest compile --grammarName MyGrammar my-grammar.ohm +``` + +### Build integration + +Add a `go:generate` directive so `go generate` keeps the `.wasm` up to date: + +**Note: this depends on the OS setting a PWD environment variable** + +```go +//go:generate docker run --rm -v "$PWD:/local" ohm:latest compile my-grammar.ohm +``` + +## Loading and using grammars + +```go +import ( + "context" + "os" + + goohm "github.com/ohmjs/goohm/runtime" +) + +wasmBytes, err := os.ReadFile("my-grammar.wasm") +if err != nil { + // handle +} + +ctx := context.Background() +g, err := goohm.NewGrammar(ctx, wasmBytes) +if err != nil { + // handle +} +defer g.Close() +``` + +`NewGrammar` compiles the Wasm module and initialises the runtime. Call `Close` when the grammar is no longer needed to release all WebAssembly resources. + +## MatchResult lifecycle + +Parse results live in Wasm linear memory and **must be explicitly disposed**. Results must be disposed in LIFO order (most recent first). + +### `defer` (recommended) + +```go +result, err := g.Match(input) +if err != nil { + // handle +} +defer result.Close() + +if result.Succeeded() { + // ... use result ... +} +``` + +### Explicit close + +When you need precise control over disposal order (e.g. nested matches): + +```go +result1, _ := g.Match(input1) +result2, _ := g.Match(input2) + +result2.Close() // must close most-recent first +result1.Close() +``` + +### Notes + +- Results must be disposed in LIFO order (most recent first). +- Failing to dispose a result will prevent subsequent `Match()` calls from succeeding. + +## Matching with a start rule + +By default, `Match` uses the grammar's default start rule. Pass an optional start rule name to override: + +```go +result, err := g.Match(input, "MyRule") +``` + +## MatchResult API + +```go +type MatchResult struct { /* ... */ } + +func (r *MatchResult) Succeeded() bool +func (r *MatchResult) Failed() bool +func (r *MatchResult) Input() string +func (r *MatchResult) Close() + +// CST access (only valid when Succeeded() is true) +func (r *MatchResult) GetCstRoot() (*CstNode, error) +``` + +## CST nodes + +`MatchResult` gives you the CST directly — there is no Semantics layer. + +```go +result, err := g.Match(input) +if err != nil { + // handle +} +defer result.Close() + +if result.Succeeded() { + root, err := result.GetCstRoot() + if err != nil { + // handle + } + fmt.Println(root.CtorName()) // rule name + fmt.Println(root.SourceString()) // matched text + start, end := root.Source() + children := root.Children() +} +``` + +### Node types + +All nodes share: `CtorName()`, `SourceString()`, `Source()` (returns `startIdx, endIdx`), `Children()`. + +| Type | `CtorName()` | Description | +|------|-------------|-------------| +| `NonterminalNode` | rule name | Has `IsSyntactic()`, `IsLexical()`, `LeadingSpaces()` | +| `TerminalNode` | `"_terminal"` | Has `Value()` | +| `ListNode` | `"_list"` | From `*` or `+`. Has `Collect(cb)` **[not yet implemented]** | +| `OptNode` | `"_opt"` | From `?`. Has `IfPresent(cb, orElse)`, `IsPresent()`, `IsEmpty()` **[not yet implemented]** | +| `SeqNode` | `"_seq"` | Grouped sequence. Has `Unpack(cb)` **[not yet implemented]** | + +Type guards: + +```go +node.IsNonterminal() bool +node.IsTerminal() bool +node.IsList() bool +node.IsOptional() bool +node.IsSeq() bool // [not yet implemented] +``` + +### Arity + +- Iter (`*`/`+`) and Opt (`?`) nodes are **not flattened**. A rule `a b c*` produces 3 children; the third is a `ListNode`. +- Positive lookahead (`&e`) **does not bind a node**. + +### Working with ListNode + +`Collect` maps over the items in a `ListNode`. When an item is a `SeqNode`, its children are unpacked as separate arguments to the callback. + +**[not yet implemented]** + +```go +// Signature (generic, exact form TBD with Go generics or interface{}) +func (n *CstNode) Collect(cb func(items ...*CstNode) any) []any + +// Example: rule like items = (name ":" value)* +items := listNode.Collect(func(parts ...*CstNode) any { + // parts[0] = name, parts[1] = ":", parts[2] = value + return map[string]string{ + "name": parts[0].SourceString(), + "value": parts[2].SourceString(), + } +}) +``` + +### Working with OptNode + +`IfPresent` calls the first callback if the option matched and the second (optional) callback otherwise. When the value is a `SeqNode`, its children are unpacked. + +**[not yet implemented]** + +```go +func (n *CstNode) IsPresent() bool +func (n *CstNode) IsEmpty() bool +func (n *CstNode) IfPresent(present func(parts ...*CstNode) any, orElse func() any) any + +// Example +val := optNode.IfPresent( + func(parts ...*CstNode) any { return parts[0].SourceString() }, + func() any { return "default" }, +) +``` + +### Working with SeqNode + +`Unpack` spreads the children of a `SeqNode` as arguments to the callback. + +**[not yet implemented]** + +```go +func (n *CstNode) Unpack(cb func(parts ...*CstNode)) + +seqNode.Unpack(func(parts ...*CstNode) { + left, op, right := parts[0], parts[1], parts[2] + _ = left; _ = op; _ = right +}) +``` + +### LeadingSpaces + +For syntactic rules, nonterminal nodes may carry implicit leading whitespace. `LeadingSpaces()` returns a `*CstNode` of type `ListNode` (possibly empty) representing those spaces. + +**[not yet implemented as a public method]** + +```go +func (n *CstNode) LeadingSpaces() *CstNode // ListNode; nil if not applicable +``` + +## Error handling + +**[not yet implemented — fields below are the target API]** + +When `result.Failed()` is true, the following fields are available: + +```go +type MatchResult struct { /* ... */ } + +func (r *MatchResult) Message() string // Full message with line/col and input excerpt +func (r *MatchResult) ShortMessage() string // "Line 1, col 5: expected ..." +func (r *MatchResult) GetExpectedText() string // "letter or digit" +func (r *MatchResult) RightmostFailurePosition() int +func (r *MatchResult) RightmostFailures() []Failure +``` + +```go +result, _ := g.Match(input) +defer result.Close() + +if result.Failed() { + fmt.Println(result.Message()) + fmt.Println(result.ShortMessage()) + fmt.Println(result.GetExpectedText()) + fmt.Println(result.RightmostFailurePosition()) +} +``` + +## Syntactic vs. lexical rule classification + +`IsSyntactic()` checks whether the **first letter** of the rule name is an upper-case letter. Rule names that start with a non-letter character (e.g. `_ident`, `0digit`) are classified as lexical, not syntactic. + +```go +node.IsSyntactic() bool // true iff first letter in CtorName() is upper-case +node.IsLexical() bool // !IsSyntactic() for nonterminals +``` + +## Grammar introspection + +```go +g.GetRuleNames() []string // all rule names defined in the grammar +g.GetRuleId(name string) (int, bool) // rule name → internal id; false if not found +``` + +## Removed / not-yet-available APIs + +The following are not present in v18 (mirroring the JS v18 status): + +- **Semantics** — no `CreateSemantics`, `AddOperation`, `AddAttribute`. Traverse the CST directly. +- **Matcher** — no incremental parsing. +- **Tracing** — no `Trace()`. +- **Grammar introspection via `.Rules`** — use `GetRuleNames()` instead. + +## Full example + +```go +package main + +import ( + "context" + "fmt" + "os" + + goohm "github.com/ohmjs/goohm/runtime" +) + +func main() { + wasmBytes, err := os.ReadFile("arithmetic.wasm") + if err != nil { + panic(err) + } + + ctx := context.Background() + g, err := goohm.NewGrammar(ctx, wasmBytes) + if err != nil { + panic(err) + } + defer g.Close() + + result, err := g.Match("1 + 2 * 3") + if err != nil { + panic(err) + } + defer result.Close() + + if result.Failed() { + fmt.Println("Parse failed:", result.Message()) + return + } + + root, err := result.GetCstRoot() + if err != nil { + panic(err) + } + + walk(root, 0) +} + +func walk(node *goohm.CstNode, depth int) { + indent := "" + for i := 0; i < depth; i++ { + indent += " " + } + fmt.Printf("%s%s %q\n", indent, node.CtorName(), node.SourceString()) + for _, child := range node.Children() { + walk(child, depth+1) + } +} +``` diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 22aeda81..61a8e650 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -19,6 +19,12 @@ services: platforms: - linux/amd64 - linux/arm64/v8 + # # Not specifying cache here as it would just slow down gha builds. + # # When doing local development, see docker.md for instructions on how to use it local cache. + # cache-from: + # - type=local,src=.buildx-cache + # cache-to: + # - type=local,dest=.buildx-cache,mode=max target: ${TARGET:-dist} volumes: - .:/local diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c7be0388..6b05b922 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,16 +1,35 @@ #!/bin/bash function usage() { - echo "Usage: docker run --rm -v \`pwd\`:/local ohm:lastest " - echo "" - echo " where cmd is compile, generateBundles or shell" - echo "" - echo " compile usage: [(--debug|-d)] [(--grammarName|-g) ] [(--output|-o) ] " - echo "" - echo " generateBundles - currently not working" - echo "" - echo " shell: drop into a bash shell in the container, useful for debug the docker build" - echo "" + cat <<'EOF' +Usage: docker run --rm -v `pwd`:/local ohmjs/ohm:latest + + where is one of: compile, generateBundles, shell, help + + compile [options] + Options: + -d, --debug Enable debug output + -g, --grammarName Override the grammar name + -o, --output Write output to (default: .wasm) + + Output directory (-v :/dst): + If /dst is mounted, output paths are resolved relative to /dst. + eg: docker run --rm -v /srcdir:/local -v /dstdir:/dst ohmjs/ohm:latest compile grammar.ohm + + Stdin / stdout: + If is '-', the grammar is read from stdin. + If -o is '-', or if reading from stdin without -o, + the wasm bytes are written to stdout. + eg: cat grammar.ohm | docker run --rm -i ohmjs/ohm:latest compile - > grammar.wasm + + generateBundles (currently not working) + + shell Drop into a bash shell in the container + (useful for debugging the docker build) + + help Print this message + +EOF } if [ "$1" = "help" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then @@ -23,9 +42,107 @@ case "$1" in shift mkdir -p /local cd /local - node \ - --disable-warning=ExperimentalWarning \ - /ohm/packages/compiler/dist/src/cli.js "$@" + + # Parse args once so we can detect stdin/stdout ('-') modes before /dst remapping. + has_output=0 + output_val="" + input_file="" + grammar_name="" + debug_flag=0 + while [ $# -gt 0 ]; do + case "$1" in + -o|--output) + has_output=1 + output_val="$2" + shift 2 + ;; + -g|--grammarName) + grammar_name="$2" + shift 2 + ;; + -d|--debug) + debug_flag=1 + shift + ;; + *) + input_file="$1" + shift + ;; + esac + done + + # If the input is '-' the grammar is assumed to be piped in on stdin. + stdin_mode=0 + if [ "$input_file" = "-" ]; then + stdin_mode=1 + fi + + # If, in this case, an output name is not provided, or the output name is '-', + # the wasm bytes are provided on stdout. + stdout_mode=0 + if [ "$has_output" -eq 1 ] && [ "$output_val" = "-" ]; then + stdout_mode=1 + elif [ "$stdin_mode" -eq 1 ] && [ "$has_output" -eq 0 ]; then + stdout_mode=1 + fi + + tmp_in="" + tmp_out="" + if [ "$stdin_mode" -eq 1 ]; then + tmp_in="$(mktemp /tmp/ohm-stdin.XXXXXX).ohm" + cat > "$tmp_in" + input_file="$tmp_in" + fi + if [ "$stdout_mode" -eq 1 ]; then + tmp_out="$(mktemp /tmp/ohm-stdout.XXXXXX).wasm" + output_val="$tmp_out" + has_output=1 + fi + + # /dst remapping applies only when output goes to a file (not stdout). + if [ "$stdout_mode" -eq 0 ] && [ -d /dst ]; then + if [ "$has_output" -eq 1 ]; then + case "$output_val" in + /*) ;; + *) output_val="/dst/$output_val" ;; + esac + elif [ -n "$input_file" ]; then + base="$(basename "$input_file")" + output_val="/dst/${base%.*}.wasm" + has_output=1 + fi + fi + + final_args=() + [ "$debug_flag" -eq 1 ] && final_args+=("-d") + [ -n "$grammar_name" ] && final_args+=("-g" "$grammar_name") + [ "$has_output" -eq 1 ] && final_args+=("-o" "$output_val") + [ -n "$input_file" ] && final_args+=("$input_file") + + rc=0 + if [ "$stdout_mode" -eq 1 ]; then + # Redirect the CLI's "Wrote Wasm to ..." message to stderr to keep stdout clean. + tmp_log="$(mktemp /tmp/ohm-log.XXXXXX)" + node \ + --disable-warning=ExperimentalWarning \ + /ohm/packages/compiler/dist/src/cli.js "${final_args[@]}" >"$tmp_log" 2>&1 + rc=$? + if [ "$rc" -eq 0 ]; then + cat "$tmp_out" + else + cat "$tmp_log" >&2 + fi + rm -f "$tmp_log" + else + node \ + --disable-warning=ExperimentalWarning \ + /ohm/packages/compiler/dist/src/cli.js "${final_args[@]}" >&2 + rc=$? + fi + + [ -n "$tmp_in" ] && rm -f "$tmp_in" + [ -n "$tmp_out" ] && rm -f "$tmp_out" + exit "$rc" ;; generateBundles) set -x diff --git a/go.work b/go.work new file mode 100644 index 00000000..34197b8e --- /dev/null +++ b/go.work @@ -0,0 +1,7 @@ +go 1.26 + +use ( + ./golang/cli + ./golang/examples + ./golang/runtime +) diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 00000000..f83f0ae2 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,6 @@ +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= diff --git a/golang/cli/.gitignore b/golang/cli/.gitignore new file mode 100644 index 00000000..0383f078 --- /dev/null +++ b/golang/cli/.gitignore @@ -0,0 +1,3 @@ +ohmgo +**/*.wasm +old \ No newline at end of file diff --git a/golang/cli/.prototools b/golang/cli/.prototools new file mode 100644 index 00000000..ada630d1 --- /dev/null +++ b/golang/cli/.prototools @@ -0,0 +1,4 @@ +adlc = "1.2.3" + +[plugins] +adlc = "https://raw.githubusercontent.com/adl-lang/proto-toml-plugins/main/adlc/plugin.toml" diff --git a/golang/cli/README.md b/golang/cli/README.md new file mode 100644 index 00000000..b4a7ab71 --- /dev/null +++ b/golang/cli/README.md @@ -0,0 +1,196 @@ +# OhmGo — CLI for Ohm, for Go + +`ohmgo` is a command-line tool that helps you compile `.ohm` grammar files into WebAssembly (`.wasm`) for use with the [`goohm`](https://github.com/ohmjs/goohm) Go runtime. + +It does not compile grammars directly. Instead, it generates the Docker command needed to compile them via the official `ohmjs/ohm` image — letting you review, adapt, or automate the compilation step however you like. + +## Overview + +The typical workflow for using Ohm in a Go project looks like this: + +``` +my-grammar.ohm → (docker compile) → my-grammar.wasm → embedded in Go binary +``` + +`ohmgo` handles the middle step by generating the correct `docker run` invocation, pinned to the version of the `goohm` runtime you're using. + +## Installation + +```bash +go install github.com/ohmjs/ohmgo@latest +``` + +Or build from source: + +```bash +git clone https://github.com/ohmjs/ohmgo +cd ohmgo +go build -o ohmgo . +``` + +## Commands + +### `generate command` + +Generates a Docker command to compile a `.ohm` grammar file into a `.wasm` file compatible with the current `goohm` runtime version. + + +``` bash + + Usage: ohmgo generate command [options] + + Generate a command, in the specified format (default is 'command') to compile a .ohm grammar file + using the ohmjs/ohm docker image. Does not actually compile the file. + + Path to .ohm grammar file to compile. + + Options: + --debug, -d + --docker-tag, -t The version tag of the ohmjs/ohm docker image to use in the generated command. + Defaults to the version of the goohm runtime included in this cli. (default + 18.0.0-beta.15) + --grammar-name, -g + --output, -o + --format, -f Output format. One of: command, go_generate, script. (default command) + --help, -h display help + +``` + + +The `--docker-tag` default is derived at runtime from the `goohm` package, so it always matches the runtime version bundled with this CLI — preventing version mismatches between the compiler and the runtime. + +## Output Formats + +The `--format` flag controls how the generated command is wrapped. + +### `command` (default) + +A ready-to-run shell snippet with a comment: + + +``` bash + +# To generate a .wasm file for use with this version of the runtime, run: +docker run --rm -v "$PWD":/local ohmjs/ohm:18.0.0-beta.15 compile my-grammar.ohm +``` + + +### `go_generate` + +A `//go:generate` directive for embedding in a Go source file: + + +``` bash + +//go:generate docker run --rm -v $PWD:/local ohmjs/ohm:18.0.0-beta.15 compile my-grammar.ohm +``` + + +Paste this into any `.go` file in your package. Running `go generate ./...` will compile the grammar and produce `my-grammar.wasm` in the same directory. + +### `script` + +A standalone shell script with a shebang: + + +``` bash +#!/bin/sh + +docker run --rm -v "$PWD":/local ohmjs/ohm:18.0.0-beta.15 compile my-grammar.ohm +``` + + +Useful when you want a reusable script checked into your repo: + +```bash +ohmgo generate command --format=script my-grammar.ohm > compile.sh +chmod +x compile.sh +./compile.sh +``` + +## Using the Compiled Grammar in Go + +Once you have a `.wasm` file, load it with `goohm`: + +```go +package main + +import ( + "context" + _ "embed" + "log" + + goohm "github.com/ohmjs/goohm" +) + +//go:embed my-grammar.wasm +var wasmBytes []byte + +func main() { + ctx := context.Background() + grmr, err := goohm.NewGrammar(ctx, wasmBytes) + if err != nil { + log.Fatalf("creating grammar: %v", err) + } + defer grmr.Close() + + result, err := grmr.Match("Hello, world!") + if err != nil { + log.Fatalf("matching: %v", err) + } + defer result.Close() + + if result.Succeeded() { + log.Println("match succeeded") + } +} +``` + +## Shell Completion + +Install or remove zsh, bash or fish completion: + +```bash +ohmgo --install # install zsh, bash or fish completions +ohmgo --uninstall # remove zsh, bash or fish completion +``` + +### Development Notes + + + +``` +# ohm_model.adl -> golang +cd genvisitor +./genadl.sh +cd .. + +# genvisitor.adl -> golang +./genadl.sh + +# manual AST -> AST which will be the output of collect +go install && ohmgo o2o | jq '.' > genvisitor/ohm.json + +# generate visitor from code in genvisitor/genvisitor_fn.go +go install && ohmgo generate visitor2 ../../packages/ohm-js/src/ohm-grammar.ohm > genvisitor/gen2/ohmgrammar/visitor.go + +# testing collector +go install && ohmgo collect_visitor_ast ../../packages/ohm-js/src/ohm-grammar.ohm | jq '.' + +# test visitor walk +go install && ohmgo exec ../../packages/ohm-js/src/ohm-grammar.ohm + +# generate sexpr +go install && ohmgo to_sexpr -S -t ../../packages/ohm-js/src/ohm-grammar.ohm > ohm-grammar.sexpr + +go install && ohmgo test_gmrs --re-match-test . tests/ruleast_01.txtar + +go install && ohmgo generate types2 -o - @../../packages/ohm-js/src/ohm-grammar.ohm > ohm_gen1/types.go +go install && ohmgo generate interfaces2 -o - @../../packages/ohm-js/src/ohm-grammar.ohm > ohm_gen1/interfaces.go +go install && ohmgo generate accepts2 -o - @../../packages/ohm-js/src/ohm-grammar.ohm > ohm_gen1/accepts.go + +go install && ohmgo generate types2 -o - @../../packages/ohm-js/test/arithmetic.ohm > arithmetic/types.go +go install && ohmgo generate interfaces2 -o - @../../packages/ohm-js/test/arithmetic.ohm > arithmetic/interfaces.go +go install && ohmgo generate accepts2 -o - @../../packages/ohm-js/test/arithmetic.ohm > arithmetic/accepts.go + +``` \ No newline at end of file diff --git a/golang/cli/adl.gencfg.json b/golang/cli/adl.gencfg.json new file mode 100644 index 00000000..67d33301 --- /dev/null +++ b/golang/cli/adl.gencfg.json @@ -0,0 +1,29 @@ +{ + "Loader": { + "Searchdir": [ + "." + ], + "MergeAdlext": "adl-go", + "BundleMaps": [ + { + "AdlModuleNamePrefix": "sys", + "GoModPath": "github.com/adl-lang/goadl_rt/v3", + "AdlSrc": "https://github.com/adl-lang/goadlc/archive/refs/tags/v1.0.0-alpha.13.zip", + "Path": "adl/stdlib_go" + } + ], + "Files": [ + "./ruleast.adl" + ] + }, + "Mod": { + "Outputdir": "." + }, + "GoTypes": { + "NoGoFmt": false, + "GoAdlPath": "github.com/adl-lang/goadl_rt/v3", + "ExcludeAst": false, + "Outputdir": "./" + }, + "GoApis": [] +} \ No newline at end of file diff --git a/golang/cli/candp/candp.go b/golang/cli/candp/candp.go new file mode 100644 index 00000000..da07e56b --- /dev/null +++ b/golang/cli/candp/candp.go @@ -0,0 +1,227 @@ +package candp + +import ( + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/ohmjs/goohm" + "github.com/samber/lo" +) + +type CompileAndParseCmd struct { + KeepWasm bool `opts:"short=K"` + ExcludeTerminals bool `opts:"short=t"` + SyntacticRulesOnly bool `opts:"short=S"` + ExcludeBuiltin bool `opts:"short=b"` + PruneLists bool `opts:"short=l"` + NoClosingNewline bool `opts:"short=n"` + Verbose bool `opts:"short=v" help:"Output source (start & end) and source string for every node"` + GrammarFile string `opts:"mode=arg"` + Source string `opts:"mode=arg"` +} + +var builtins = map[string]struct{}{ + "any": {}, + "letter": {}, + "lower": {}, + "upper": {}, + "digit": {}, + "hexDigit": {}, + "alnum": {}, + "space": {}, + "end": {}, +} + +func NewCompileAndParseCmd() *CompileAndParseCmd { + return &CompileAndParseCmd{} +} + +func (vc *CompileAndParseCmd) Run() error { + if len(vc.Source) > 2 && vc.Source[:1] == "@" { + barr, err := os.ReadFile(vc.Source[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %v", err) + } + vc.Source = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + fmt.Printf("%s\n", out) + return nil +} + +func (vc *CompileAndParseCmd) Process() (string, error) { + // create a tempdir, get the absolute path of the directory GrammarFile is in + // run `docker run --rm -v ":/local" -v ":/dst" ohmjs/ohm:18.0.0-beta.15 compile GrammarFile` + tempdir, err := os.MkdirTemp("", "ohm-compile-*") + if err != nil { + return "", fmt.Errorf("creating tempdir: %v", err) + } + if !vc.KeepWasm { + defer os.RemoveAll(tempdir) + } else { + fmt.Fprintf(os.Stderr, "working dir %s\n", tempdir) + } + absGrammarPath, err := filepath.Abs(vc.GrammarFile) + if err != nil { + return "", fmt.Errorf("resolving grammar file path: %v", err) + } + basedir := filepath.Dir(absGrammarPath) + grammarBasename := filepath.Base(absGrammarPath) + dockerTag := ((*goohm.Grammar)(nil)).MatchingDockerImageTags()[0] + cmd := exec.Command("docker", "run", "--rm", + "-v", fmt.Sprintf("%s:/local", basedir), + "-v", fmt.Sprintf("%s:/dst", tempdir), + fmt.Sprintf("ohmjs/ohm:%s", dockerTag), + "compile", grammarBasename, + ) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("docker compile: %v", err) + } + // get the basename of GrammarFile without the extension + // read /.wasm + baseNoExt := strings.TrimSuffix(grammarBasename, filepath.Ext(grammarBasename)) + wasmPath := filepath.Join(tempdir, baseNoExt+".wasm") + wasmBytes, err := os.ReadFile(wasmPath) + if err != nil { + return "", fmt.Errorf("reading compiled wasm at %s: %v", wasmPath, err) + } + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, wasmBytes); err != nil { + return "", fmt.Errorf("creating grammar: %v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.Source); err != nil { + return "", fmt.Errorf("matching: %v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed for grammar\n'%s'\nsource\n'%s'\n", vc.GrammarFile, vc.Source) + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %v", err) + } + var result strings.Builder + vc.toSexprNode(root, 0, &result) + return result.String()[1:], nil +} + +func (vc *CompileAndParseCmd) toSexprNode(node goohm.Node, depth int, result *strings.Builder) { + kids := node.Children() + if vc.ExcludeTerminals { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + _, is := node.(goohm.TerminalNode) + return !is + }) + } + if vc.SyntacticRulesOnly { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + ctor := node.CtorName() + return strings.ToUpper(ctor[:1]) == ctor[:1] + }) + } + if vc.ExcludeBuiltin { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + ctor := node.CtorName() + _, ex := builtins[ctor] + return !ex + }) + } + ctor := node.CtorName() + if vc.PruneLists && ctor == "_list" { + for _, n := range kids { + vc.toSexprNode(n, depth, result) + } + return + } + switch { + case len(kids) != 0: + result.WriteString("\n") + result.WriteString(strings.Repeat(" ", depth)) + result.WriteString("(") + result.WriteString(ctor) + if vc.Verbose { + s, f := node.Source() + result.WriteString(fmt.Sprintf(" %d-%d ", s, f)) + src := node.SourceString() + src = sexprStrEncode(src) + if len(src) > 40 { + src = src[:37] + "..." + } + result.WriteString("'") + result.WriteString(src) + result.WriteString("'") + } + case ctor == "_terminal": + result.WriteString(" (") + result.WriteString(ctor) + default: + result.WriteString(" ") + result.WriteString(ctor) + } + + if ctor == "_terminal" { + addTerm(node, result) + } + for _, n := range kids { + vc.toSexprNode(n, depth+1, result) + } + switch { + case len(kids) != 0: + if !vc.NoClosingNewline { + result.WriteString("\n") + result.WriteString(strings.Repeat(" ", depth)) + } + result.WriteString(")") + case ctor == "_terminal": + result.WriteString(")") + } +} + +func addTerm(node goohm.Node, result *strings.Builder) { + val := node.SourceString() + switch val { + case "\t": + result.WriteString(" TAB") + case "\n": + result.WriteString(" NL") + case "(": + result.WriteString(" OP") + case ")": + result.WriteString(" CP") + case "{": + result.WriteString(" OC") + case "}": + result.WriteString(" CC") + default: + result.WriteString(" '") + result.WriteString(val) + result.WriteString("'") + } + result.WriteString(" ") + s, f := node.Source() + result.WriteString(fmt.Sprintf("%d-%d", s, f)) +} + +func sexprStrEncode(val string) string { + val = strings.ReplaceAll(val, "\t", "\\t") + val = strings.ReplaceAll(val, "\n", "\\n") + val = strings.ReplaceAll(val, "(", "OP") + val = strings.ReplaceAll(val, ")", "CP") + val = strings.ReplaceAll(val, "{", "OC") + val = strings.ReplaceAll(val, "}", "CC") + return val +} diff --git a/golang/cli/flake.lock b/golang/cli/flake.lock new file mode 100644 index 00000000..54675baf --- /dev/null +++ b/golang/cli/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1780336545, + "narHash": "sha256-vhVhuXzFrIOfcssC/9hDHx7MHzDKjF3keHuREOQqQiQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "4df1b885d76a54e1aa1a318f8d16fd6005b6401f", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/golang/cli/flake.nix b/golang/cli/flake.nix new file mode 100644 index 00000000..c28e9cac --- /dev/null +++ b/golang/cli/flake.nix @@ -0,0 +1,76 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { nixpkgs, flake-utils, ... }: + flake-utils.lib.eachSystem [ "aarch64-darwin" "x86_64-linux" ] ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + adl = pkgs.callPackage ( + { + stdenv, + fetchurl, + unzip, + }: + let + version = "1.2.3"; + src = fetchurl ( + if stdenv.isDarwin && stdenv.hostPlatform.isAarch64 then + { + url = "https://github.com/adl-lang/adl/releases/download/v${version}/adl-bindist-${version}-macos-arm64.zip"; + sha256 = "sha256-IAdm+tWqRwkoCWfMn69KIdG6rAztRU+aZDQTGGWfZJY="; + } + else if stdenv.isLinux && stdenv.hostPlatform.isx86_64 then + { + url = "https://github.com/adl-lang/adl/releases/download/v${version}/adl-bindist-${version}-linux-x64.zip"; + sha256 = "sha256-5V/RU8LV78NkcE3pu9fkMvbjb184QYO33MjqRtlQPJE="; + } + else + throw "adl: unsupported platform ${stdenv.hostPlatform.system}, only macos-arm64 and linux-x64 are available" + ); + in + stdenv.mkDerivation { + pname = "adl"; + inherit version src; + + nativeBuildInputs = [ unzip ]; + sourceRoot = "."; + + installPhase = '' + mkdir -p $out/bin $out/lib + cp bin/adlc $out/bin/ + cp -r lib/* $out/lib/ + chmod +x $out/bin/* + ''; + + meta = { + description = "Helix ADL tool"; + platforms = [ + "aarch64-darwin" + "x86_64-linux" + ]; + }; + } + ) { }; + devPackages = with pkgs; [ + adl + go + ]; + in + { + devShells = { + default = pkgs.mkShell { + buildInputs = devPackages; + }; + ci = pkgs.mkShell { + buildInputs = devPackages; + SHELLOPTS = "errexit:pipefail"; + }; + }; + } + ); +} diff --git a/golang/cli/genadl.sh b/golang/cli/genadl.sh new file mode 100755 index 00000000..e1890da2 --- /dev/null +++ b/golang/cli/genadl.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +go tool github.com/adl-lang/goadlc/cmd/goadlc -cfg adl.gencfg.json diff --git a/golang/cli/gencmd/gencmd.go b/golang/cli/gencmd/gencmd.go new file mode 100644 index 00000000..49a26ad1 --- /dev/null +++ b/golang/cli/gencmd/gencmd.go @@ -0,0 +1,79 @@ +package gencmd + +import ( + "fmt" + "strings" + + "github.com/ohmjs/goohm" +) + +type genCmdCmd struct { + Debug bool + DockerTag string `opts:"short=t" help:"The version tag of the ohmjs/ohm docker image to use in the generated command. Defaults to the version of the goohm runtime included in this cli."` + GrammarName string + Output string + Format format `help:"Output format. One of: command, go_generate, script."` + SourceFile string `opts:"mode=arg" help:"Path to .ohm grammar file to compile."` +} + +type format string + +var validFormats = []string{"command", "go_generate", "script"} + +func (format) Complete(s string) []string { + return validFormats +} + +func (e *format) Set(s string) error { + for _, v := range validFormats { + if s == v { + *e = format(s) + return nil + } + } + return fmt.Errorf("must be one of: %v", strings.Join(validFormats, ", ")) +} + +func NewGenCmdCmd() *genCmdCmd { + return &genCmdCmd{ + Format: format("command"), + DockerTag: ((*goohm.Grammar)(nil)).MatchingDockerImageTags()[0], + } +} + +func (c *genCmdCmd) Run() error { + var ( + debug = "" + grammar = "" + output = "" + ) + if c.Debug { + debug = "--debug " + } + if c.GrammarName != "" { + grammar = fmt.Sprintf("--grammarName %s ", c.GrammarName) + } + if c.Output != "" { + output = fmt.Sprintf("--output %s ", c.Output) + } + + switch c.Format { + case "command": + fmt.Printf(` +# To generate a .wasm file for use with this version of the runtime, run: +docker run --rm -v "$PWD":/local ohmjs/ohm:%s compile %s%s%s%s +`, c.DockerTag, debug, grammar, output, c.SourceFile) + case "go_generate": + fmt.Printf(` +//go:generate docker run --rm -v $PWD:/local ohmjs/ohm:%s compile %s%s%s%s +`, c.DockerTag, debug, grammar, output, c.SourceFile) + case "script": + fmt.Printf(`#!/bin/sh + +docker run --rm -v "$PWD":/local ohmjs/ohm:%s compile %s%s%s%s +`, c.DockerTag, debug, grammar, output, c.SourceFile) + default: + return fmt.Errorf("invalid format: %s", c.Format) + } + return nil +} diff --git a/golang/cli/go.mod b/golang/cli/go.mod new file mode 100644 index 00000000..926abe4e --- /dev/null +++ b/golang/cli/go.mod @@ -0,0 +1,25 @@ +module github.com/ohmjs/ohmgo + +go 1.26 + +require ( + github.com/adl-lang/goadl_rt/v3 v3.0.0-alpha.9 + github.com/google/go-cmp v0.6.0 + github.com/jpillora/opts v1.2.3 + github.com/samber/lo v1.53.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d +) + +require ( + github.com/adl-lang/goadlc v1.0.0-alpha.13 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/jpillora/md-tmpl v1.3.0 // indirect + github.com/mattn/go-zglob v0.0.4 // indirect + github.com/posener/complete v1.2.2-0.20190308074557-af07aa5181b3 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/text v0.22.0 // indirect +) + +tool github.com/adl-lang/goadlc/cmd/goadlc diff --git a/golang/cli/go.sum b/golang/cli/go.sum new file mode 100644 index 00000000..5addfe61 --- /dev/null +++ b/golang/cli/go.sum @@ -0,0 +1,28 @@ +github.com/adl-lang/goadl_rt/v3 v3.0.0-alpha.9 h1:Bsmh92XL0FekdBKjuyvQnpOs3WR8J7vUORv4AOGon4s= +github.com/adl-lang/goadl_rt/v3 v3.0.0-alpha.9/go.mod h1:OTKpMzWp6Wcau9RBvjMmkvADMoI9azo/xocnh+4f38k= +github.com/adl-lang/goadlc v1.0.0-alpha.13 h1:FkK5mqZ/UOS7dJGlHWWUdDRibYDBLKWAKFS9DBJb1Uw= +github.com/adl-lang/goadlc v1.0.0-alpha.13/go.mod h1:R4uK/axwPg8ZKD8FBzhnRPIo8iVb/ahnIwMIdNu2Vlo= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/jpillora/md-tmpl v1.3.0 h1:M9XrHfGD0Jue5arhejVUj4HE74PXuaR1/KC0FJ9olWk= +github.com/jpillora/md-tmpl v1.3.0/go.mod h1:7kH6OzBwoCAbrXV0OiXKAYLdXwVCMAEirNxZ5uUl5pA= +github.com/jpillora/opts v1.2.3 h1:Q0YuOM7y0BlunHJ7laR1TUxkUA7xW8A2rciuZ70xs8g= +github.com/jpillora/opts v1.2.3/go.mod h1:7p7X/vlpKZmtaDFYKs956EujFqA6aCrOkcCaS6UBcR4= +github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= +github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= +github.com/posener/complete v1.2.2-0.20190308074557-af07aa5181b3 h1:GqpA1/5oN1NgsxoSA4RH0YWTaqvUlQNeOpHXD/JRbOQ= +github.com/posener/complete v1.2.2-0.20190308074557-af07aa5181b3/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= +github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM= +github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= diff --git a/golang/cli/main.go b/golang/cli/main.go new file mode 100644 index 00000000..a58e29c1 --- /dev/null +++ b/golang/cli/main.go @@ -0,0 +1,82 @@ +package main + +//go:generate go run github.com/jpillora/md-tmpl -w README.md +//go:generate go generate ./utils + +import ( + "fmt" + "os" + + "github.com/jpillora/opts" + "github.com/ohmjs/ohmgo/candp" + "github.com/ohmjs/ohmgo/gencmd" + "github.com/ohmjs/ohmgo/ohm" + "github.com/ohmjs/ohmgo/ruleast" + "github.com/ohmjs/ohmgo/sexpr" + "github.com/ohmjs/ohmgo/tests" +) + +var ( + rootCmd = &struct{}{} + builder = opts.New(rootCmd). + Name("ohmgo"). + EmbedGlobalFlagSet(). + Complete() +) + +func init() { + parts := opts.New(&struct{}{}).Name("parts") + types := opts.New(ruleast.NewGenTypesCmd()).Name("go_types") + interfaces := opts.New(ruleast.NewGenInterfaceCmd()).Name("go_interfaces") + accepts := opts.New(ruleast.NewGenAcceptsCmd()).Name("go_accepts") + parts. + AddCommand(types). + AddCommand(interfaces). + AddCommand(accepts) + + command := opts.New(gencmd.NewGenCmdCmd()).Name("command"). + Summary("Generate a command, in the specified format (default is 'command') to compile a .ohm grammar file using the ohmjs/ohm docker image. Does not actually compile the file.") + gogen := opts.New(ruleast.NewGenGoCmd()).Name("go"). + Summary("Generate golang visitor interfaces and helper methods for this provided grammar. The 'family visitor' flavour (ie with an extra swappable receive) is implementated, with easy storage of payloads & results in the call stack.") + + generate := opts.New(&struct{}{}).Name("generate") + generate. + AddCommand(command). + AddCommand(parts). + AddCommand(gogen) + + test := opts.New(&struct{}{}).Name("test") + exec_accept := opts.New(ohm.NewExerciseGenedCmd()).Name("exec_accept") + rule_ast := opts.New(ruleast.NewRuleAstCmd()).Name("rule_ast") + c_and_p := opts.New(candp.NewCompileAndParseCmd()).Name("c_and_p") + to_sexpr := opts.New(sexpr.NewToSexprCmd()).Name("to_sexpr") + txtar := opts.New(tests.NewTestGmrCmd()).Name("txtar") + test. + AddCommand(exec_accept). + AddCommand(rule_ast). + AddCommand(c_and_p). + AddCommand(to_sexpr). + AddCommand(txtar) + + builder.AddCommand(test) + builder.AddCommand(generate) + +} + +func main() { + var ( + cli opts.ParsedOpts + err error + ) + cli, err = builder.ParseArgsError(os.Args) + if err != nil { + fmt.Fprintf(os.Stderr, "%[1]v", err) + os.Exit(1) + } + // cli = builder.ParseArgs(os.Args) + err = cli.Run() + if err != nil { + fmt.Fprintf(os.Stderr, "%[2]s\nError: %[1]v\n\n", err, cli.Selected().Help()) + os.Exit(2) + } +} diff --git a/golang/cli/ohm/accepts.go b/golang/cli/ohm/accepts.go new file mode 100644 index 00000000..b97ef6b7 --- /dev/null +++ b/golang/cli/ohm/accepts.go @@ -0,0 +1,2497 @@ +// Code generated by ohmgo generate accepts - DO NOT EDIT. +package ohm + +import ( + "github.com/ohmjs/goohm" +) + +// accepts for grammar Ohm + +// TODO for grammar Ohm, implement Make func for starting rule Grammars + +// Accept implementation for Grammars +// +// Grammars +// = Grammar* +func (node *Grammars[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Grammars") + if v, ok := visitor.(VisitorGrammars[P, R]); ok { + return v.VisitGrammars(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Grammars[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptGrammar(visitor, payload) + return +} + +func (node *Grammars[P, R]) AcceptGrammar(visitor any, payload P) (result R) { + for _, n := range node.Grammar.Children() { + kids := n.Children() + result = (&Grammar[P, R]{ + Ident: kids[0].(goohm.RuleNode), + SuperGrammar: kids[1].(goohm.OptNode), + Term1: kids[2].(goohm.TerminalNode), + Rule: kids[3].(goohm.ListNode), + Term2: kids[4].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +// Accept implementation for Grammar +// +// Grammar +// = ident SuperGrammar? "{" Rule* "}" +func (node *Grammar[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Grammar") + if v, ok := visitor.(VisitorGrammar[P, R]); ok { + return v.VisitGrammar(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Grammar[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexIdent(visitor, payload) + result = node.AcceptSuperGrammar(visitor, payload) + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptRule(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *Grammar[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +func (node *Grammar[P, R]) AcceptSuperGrammar(visitor any, payload P) (result R) { + // Opt + if len(node.SuperGrammar.Children()) > 0 { + n := node.SuperGrammar.Children()[0] + kids := n.Children() + result = (&SuperGrammar[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Ident: kids[1].(goohm.RuleNode), + }).Accept(n, visitor, payload) + } + return +} + +func (node *Grammar[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *Grammar[P, R]) AcceptRule(visitor any, payload P) (result R) { + for _, n := range node.Rule.Children() { + result = (&Rule[P, R]{ + Node: n, + }).Accept(n, visitor, payload) + } + return +} + +func (node *Grammar[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for SuperGrammar +// +// SuperGrammar +// = "<:" ident +func (node *SuperGrammar[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "SuperGrammar") + if v, ok := visitor.(VisitorSuperGrammar[P, R]); ok { + return v.VisitSuperGrammar(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *SuperGrammar[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexIdent(visitor, payload) + return +} + +func (node *SuperGrammar[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *SuperGrammar[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +// Accept implementation for Rule +// +// Rule +// = ident Formals? ruleDescr? "=" RuleBody -- define +// | ident Formals? ":=" OverrideRuleBody -- override +// | ident Formals? "+=" RuleBody -- extend +func (node *Rule[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Rule") + if v, ok := visitor.(VisitorRule[P, R]); ok { + return v.VisitRule(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Rule[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "Rule": + return (&Rule[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "Rule_define": + kids := node.Node.Children() + return (&RuleDefine[P, R]{ + Ident: kids[0].(goohm.RuleNode), + Formals: kids[1].(goohm.OptNode), + RuleDescr: kids[2].(goohm.OptNode), + Term: kids[3].(goohm.TerminalNode), + RuleBody: kids[4].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Rule_override": + kids := node.Node.Children() + return (&RuleOverride[P, R]{ + Ident: kids[0].(goohm.RuleNode), + Formals: kids[1].(goohm.OptNode), + Term: kids[2].(goohm.TerminalNode), + OverrideRuleBody: kids[3].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Rule_extend": + kids := node.Node.Children() + return (&RuleExtend[P, R]{ + Ident: kids[0].(goohm.RuleNode), + Formals: kids[1].(goohm.OptNode), + Term: kids[2].(goohm.TerminalNode), + RuleBody: kids[3].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for Rule_define +// +// ident Formals? ruleDescr? "=" RuleBody +func (node *RuleDefine[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Rule_define") + if v, ok := visitor.(VisitorRuleDefine[P, R]); ok { + return v.VisitRuleDefine(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *RuleDefine[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexIdent(visitor, payload) + result = node.AcceptFormals(visitor, payload) + result = node.AcceptLexRuleDescr(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptRuleBody(visitor, payload) + return +} + +func (node *RuleDefine[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +func (node *RuleDefine[P, R]) AcceptFormals(visitor any, payload P) (result R) { + // Opt + if len(node.Formals.Children()) > 0 { + n := node.Formals.Children()[0] + kids := n.Children() + result = (&Formals[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + ListOf: kids[1].(goohm.BHorNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +func (node *RuleDefine[P, R]) AcceptLexRuleDescr(visitor any, payload P) (result R) { + // Opt + if len(node.RuleDescr.Children()) > 0 { + n := node.RuleDescr.Children()[0] + kids := n.Children() + result = (&LexRuleDescr[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + RuleDescrText: kids[1].(goohm.RuleNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +func (node *RuleDefine[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *RuleDefine[P, R]) AcceptRuleBody(visitor any, payload P) (result R) { + // Rule + kids := node.RuleBody.Children() + result = (&RuleBody[P, R]{ + Term: kids[0].(goohm.OptNode), + NonemptyListOf: kids[1].(goohm.BHorNode), + }).Accept(node.RuleBody, visitor, payload) + return +} + +// Accept implementation for Rule_override +// +// ident Formals? ":=" OverrideRuleBody +func (node *RuleOverride[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Rule_override") + if v, ok := visitor.(VisitorRuleOverride[P, R]); ok { + return v.VisitRuleOverride(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *RuleOverride[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexIdent(visitor, payload) + result = node.AcceptFormals(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptOverrideRuleBody(visitor, payload) + return +} + +func (node *RuleOverride[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +func (node *RuleOverride[P, R]) AcceptFormals(visitor any, payload P) (result R) { + // Opt + if len(node.Formals.Children()) > 0 { + n := node.Formals.Children()[0] + kids := n.Children() + result = (&Formals[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + ListOf: kids[1].(goohm.BHorNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +func (node *RuleOverride[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *RuleOverride[P, R]) AcceptOverrideRuleBody(visitor any, payload P) (result R) { + // Rule + kids := node.OverrideRuleBody.Children() + result = (&OverrideRuleBody[P, R]{ + Term: kids[0].(goohm.OptNode), + NonemptyListOf: kids[1].(goohm.BHorNode), + }).Accept(node.OverrideRuleBody, visitor, payload) + return +} + +// Accept implementation for Rule_extend +// +// ident Formals? "+=" RuleBody +func (node *RuleExtend[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Rule_extend") + if v, ok := visitor.(VisitorRuleExtend[P, R]); ok { + return v.VisitRuleExtend(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *RuleExtend[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexIdent(visitor, payload) + result = node.AcceptFormals(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptRuleBody(visitor, payload) + return +} + +func (node *RuleExtend[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +func (node *RuleExtend[P, R]) AcceptFormals(visitor any, payload P) (result R) { + // Opt + if len(node.Formals.Children()) > 0 { + n := node.Formals.Children()[0] + kids := n.Children() + result = (&Formals[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + ListOf: kids[1].(goohm.BHorNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +func (node *RuleExtend[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *RuleExtend[P, R]) AcceptRuleBody(visitor any, payload P) (result R) { + // Rule + kids := node.RuleBody.Children() + result = (&RuleBody[P, R]{ + Term: kids[0].(goohm.OptNode), + NonemptyListOf: kids[1].(goohm.BHorNode), + }).Accept(node.RuleBody, visitor, payload) + return +} + +// Accept implementation for RuleBody +// +// RuleBody +// = "|"? NonemptyListOf +func (node *RuleBody[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "RuleBody") + if v, ok := visitor.(VisitorRuleBody[P, R]); ok { + return v.VisitRuleBody(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *RuleBody[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptNonemptyListOf(visitor, payload) + return +} + +func (node *RuleBody[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Opt + if len(node.Term.Children()) > 0 { + n := node.Term.Children()[0] + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + } + return +} + +func (node *RuleBody[P, R]) AcceptNonemptyListOf(visitor any, payload P) (result R) { + // BuiltinHOR + // TopLevelTerm + fn_elem := func(n goohm.Node) (result R) { + kids := n.Children() + result = (&TopLevelTerm[P, R]{ + Node: kids[0], + }).Accept(n, visitor, payload) + return + } + fn_sep := func(n goohm.Node) (result R) { + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + return + } + goohm.AcceptBuiltinHOR(node.NonemptyListOf, fn_elem, fn_sep) + return +} + +// Accept implementation for TopLevelTerm +// +// TopLevelTerm +// = Seq caseName -- inline +// | Seq +func (node *TopLevelTerm[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "TopLevelTerm") + if v, ok := visitor.(VisitorTopLevelTerm[P, R]); ok { + return v.VisitTopLevelTerm(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *TopLevelTerm[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "TopLevelTerm": + return (&TopLevelTerm[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "TopLevelTerm_inline": + kids := node.Node.Children() + return (&TopLevelTermInline[P, R]{ + Seq: kids[0].(goohm.RuleNode), + CaseName: kids[1].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Seq": + kids := node.Node.Children() + return (&Seq[P, R]{ + Iter: kids[0].(goohm.ListNode), + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for TopLevelTerm_inline +// +// Seq caseName +func (node *TopLevelTermInline[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "TopLevelTerm_inline") + if v, ok := visitor.(VisitorTopLevelTermInline[P, R]); ok { + return v.VisitTopLevelTermInline(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *TopLevelTermInline[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptSeq(visitor, payload) + result = node.AcceptLexCaseName(visitor, payload) + return +} + +func (node *TopLevelTermInline[P, R]) AcceptSeq(visitor any, payload P) (result R) { + // Rule + kids := node.Seq.Children() + result = (&Seq[P, R]{ + Iter: kids[0].(goohm.ListNode), + }).Accept(node.Seq, visitor, payload) + return +} + +func (node *TopLevelTermInline[P, R]) AcceptLexCaseName(visitor any, payload P) (result R) { + // Rule + kids := node.CaseName.Children() + result = (&LexCaseName[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Alt1: kids[1].(goohm.ListNode), + Name: kids[2].(goohm.RuleNode), + Alt2: kids[3].(goohm.ListNode), + Alt3: kids[4], + }).Accept(node.CaseName, visitor, payload) + return +} + +// Accept implementation for OverrideRuleBody +// +// OverrideRuleBody +// = "|"? NonemptyListOf +func (node *OverrideRuleBody[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "OverrideRuleBody") + if v, ok := visitor.(VisitorOverrideRuleBody[P, R]); ok { + return v.VisitOverrideRuleBody(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *OverrideRuleBody[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptNonemptyListOf(visitor, payload) + return +} + +func (node *OverrideRuleBody[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Opt + if len(node.Term.Children()) > 0 { + n := node.Term.Children()[0] + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + } + return +} + +func (node *OverrideRuleBody[P, R]) AcceptNonemptyListOf(visitor any, payload P) (result R) { + // BuiltinHOR + // OverrideTopLevelTerm + fn_elem := func(n goohm.Node) (result R) { + kids := n.Children() + result = (&OverrideTopLevelTerm[P, R]{ + Node: kids[0], + }).Accept(n, visitor, payload) + return + } + fn_sep := func(n goohm.Node) (result R) { + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + return + } + goohm.AcceptBuiltinHOR(node.NonemptyListOf, fn_elem, fn_sep) + return +} + +// Accept implementation for OverrideTopLevelTerm +// +// OverrideTopLevelTerm +// = "..." -- superSplice +// | TopLevelTerm +func (node *OverrideTopLevelTerm[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "OverrideTopLevelTerm") + if v, ok := visitor.(VisitorOverrideTopLevelTerm[P, R]); ok { + return v.VisitOverrideTopLevelTerm(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *OverrideTopLevelTerm[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "OverrideTopLevelTerm": + return (&OverrideTopLevelTerm[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "OverrideTopLevelTerm_superSplice": + kids := node.Node.Children() + return (&OverrideTopLevelTermSuperSplice[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "TopLevelTerm": + kids := node.Node.Children() + return (&TopLevelTerm[P, R]{ + Node: kids[0], + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for OverrideTopLevelTerm_superSplice +// +// "..." +func (node *OverrideTopLevelTermSuperSplice[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "OverrideTopLevelTerm_superSplice") + if v, ok := visitor.(VisitorOverrideTopLevelTermSuperSplice[P, R]); ok { + return v.VisitOverrideTopLevelTermSuperSplice(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *OverrideTopLevelTermSuperSplice[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *OverrideTopLevelTermSuperSplice[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for Formals +// +// Formals +// = "<" ListOf ">" +func (node *Formals[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Formals") + if v, ok := visitor.(VisitorFormals[P, R]); ok { + return v.VisitFormals(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Formals[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptListOf(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *Formals[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *Formals[P, R]) AcceptListOf(visitor any, payload P) (result R) { + // BuiltinHOR + // ident + fn_elem := func(n goohm.Node) (result R) { + kids := n.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(n, visitor, payload) + return + } + fn_sep := func(n goohm.Node) (result R) { + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + return + } + goohm.AcceptBuiltinHOR(node.ListOf, fn_elem, fn_sep) + return +} + +func (node *Formals[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for Params +// +// Params +// = "<" ListOf ">" +func (node *Params[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Params") + if v, ok := visitor.(VisitorParams[P, R]); ok { + return v.VisitParams(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Params[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptListOf(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *Params[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *Params[P, R]) AcceptListOf(visitor any, payload P) (result R) { + // BuiltinHOR + // Seq + fn_elem := func(n goohm.Node) (result R) { + kids := n.Children() + result = (&Seq[P, R]{ + Iter: kids[0].(goohm.ListNode), + }).Accept(n, visitor, payload) + return + } + fn_sep := func(n goohm.Node) (result R) { + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + return + } + goohm.AcceptBuiltinHOR(node.ListOf, fn_elem, fn_sep) + return +} + +func (node *Params[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for Alt +// +// Alt +// = NonemptyListOf +func (node *Alt[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Alt") + if v, ok := visitor.(VisitorAlt[P, R]); ok { + return v.VisitAlt(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Alt[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptNonemptyListOf(visitor, payload) + return +} + +func (node *Alt[P, R]) AcceptNonemptyListOf(visitor any, payload P) (result R) { + // BuiltinHOR + // Seq + fn_elem := func(n goohm.Node) (result R) { + kids := n.Children() + result = (&Seq[P, R]{ + Iter: kids[0].(goohm.ListNode), + }).Accept(n, visitor, payload) + return + } + fn_sep := func(n goohm.Node) (result R) { + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(goohm.TerminalNode)) + } + return + } + goohm.AcceptBuiltinHOR(node.NonemptyListOf, fn_elem, fn_sep) + return +} + +// Accept implementation for Seq +// +// Seq +// = Iter* +func (node *Seq[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Seq") + if v, ok := visitor.(VisitorSeq[P, R]); ok { + return v.VisitSeq(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Seq[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptIter(visitor, payload) + return +} + +func (node *Seq[P, R]) AcceptIter(visitor any, payload P) (result R) { + for _, n := range node.Iter.Children() { + result = (&Iter[P, R]{ + Node: n, + }).Accept(n, visitor, payload) + } + return +} + +// Accept implementation for Iter +// +// Iter +// = Pred "*" -- star +// | Pred "+" -- plus +// | Pred "?" -- opt +// | Pred +func (node *Iter[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Iter") + if v, ok := visitor.(VisitorIter[P, R]); ok { + return v.VisitIter(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Iter[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "Iter": + return (&Iter[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "Iter_star": + kids := node.Node.Children() + return (&IterStar[P, R]{ + Pred: kids[0].(goohm.RuleNode), + Term: kids[1].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "Iter_plus": + kids := node.Node.Children() + return (&IterPlus[P, R]{ + Pred: kids[0].(goohm.RuleNode), + Term: kids[1].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "Iter_opt": + kids := node.Node.Children() + return (&IterOpt[P, R]{ + Pred: kids[0].(goohm.RuleNode), + Term: kids[1].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "Pred": + kids := node.Node.Children() + return (&Pred[P, R]{ + Node: kids[0], + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for Iter_star +// +// Pred "*" +func (node *IterStar[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Iter_star") + if v, ok := visitor.(VisitorIterStar[P, R]); ok { + return v.VisitIterStar(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *IterStar[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptPred(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *IterStar[P, R]) AcceptPred(visitor any, payload P) (result R) { + // Rule + kids := node.Pred.Children() + result = (&Pred[P, R]{ + Node: kids[0], + }).Accept(node.Pred, visitor, payload) + return +} + +func (node *IterStar[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for Iter_plus +// +// Pred "+" +func (node *IterPlus[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Iter_plus") + if v, ok := visitor.(VisitorIterPlus[P, R]); ok { + return v.VisitIterPlus(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *IterPlus[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptPred(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *IterPlus[P, R]) AcceptPred(visitor any, payload P) (result R) { + // Rule + kids := node.Pred.Children() + result = (&Pred[P, R]{ + Node: kids[0], + }).Accept(node.Pred, visitor, payload) + return +} + +func (node *IterPlus[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for Iter_opt +// +// Pred "?" +func (node *IterOpt[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Iter_opt") + if v, ok := visitor.(VisitorIterOpt[P, R]); ok { + return v.VisitIterOpt(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *IterOpt[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptPred(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *IterOpt[P, R]) AcceptPred(visitor any, payload P) (result R) { + // Rule + kids := node.Pred.Children() + result = (&Pred[P, R]{ + Node: kids[0], + }).Accept(node.Pred, visitor, payload) + return +} + +func (node *IterOpt[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for Pred +// +// Pred +// = "~" Lex -- not +// | "&" Lex -- lookahead +// | Lex +func (node *Pred[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Pred") + if v, ok := visitor.(VisitorPred[P, R]); ok { + return v.VisitPred(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Pred[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "Pred": + return (&Pred[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "Pred_not": + kids := node.Node.Children() + return (&PredNot[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Lex: kids[1].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Pred_lookahead": + kids := node.Node.Children() + return (&PredLookahead[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Lex: kids[1].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Lex": + kids := node.Node.Children() + return (&Lex[P, R]{ + Node: kids[0], + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for Pred_not +// +// "~" Lex +func (node *PredNot[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Pred_not") + if v, ok := visitor.(VisitorPredNot[P, R]); ok { + return v.VisitPredNot(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *PredNot[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLex(visitor, payload) + return +} + +func (node *PredNot[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *PredNot[P, R]) AcceptLex(visitor any, payload P) (result R) { + // Rule + kids := node.Lex.Children() + result = (&Lex[P, R]{ + Node: kids[0], + }).Accept(node.Lex, visitor, payload) + return +} + +// Accept implementation for Pred_lookahead +// +// "&" Lex +func (node *PredLookahead[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Pred_lookahead") + if v, ok := visitor.(VisitorPredLookahead[P, R]); ok { + return v.VisitPredLookahead(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *PredLookahead[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLex(visitor, payload) + return +} + +func (node *PredLookahead[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *PredLookahead[P, R]) AcceptLex(visitor any, payload P) (result R) { + // Rule + kids := node.Lex.Children() + result = (&Lex[P, R]{ + Node: kids[0], + }).Accept(node.Lex, visitor, payload) + return +} + +// Accept implementation for Lex +// +// Lex +// = "#" Base -- lex +// | Base +func (node *Lex[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Lex") + if v, ok := visitor.(VisitorLex[P, R]); ok { + return v.VisitLex(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Lex[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "Lex": + return (&Lex[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "Lex_lex": + kids := node.Node.Children() + return (&LexLex[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Base: kids[1].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Base": + kids := node.Node.Children() + return (&Base[P, R]{ + Node: kids[0], + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for Lex_lex +// +// "#" Base +func (node *LexLex[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Lex_lex") + if v, ok := visitor.(VisitorLexLex[P, R]); ok { + return v.VisitLexLex(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexLex[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptBase(visitor, payload) + return +} + +func (node *LexLex[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *LexLex[P, R]) AcceptBase(visitor any, payload P) (result R) { + // Rule + kids := node.Base.Children() + result = (&Base[P, R]{ + Node: kids[0], + }).Accept(node.Base, visitor, payload) + return +} + +// Accept implementation for Base +// +// Base +// = ident Params? ~(ruleDescr? "=" | ":=" | "+=") -- application +// | oneCharTerminal ".." oneCharTerminal -- range +// | terminal -- terminal +// | "(" Alt ")" -- paren +func (node *Base[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Base") + if v, ok := visitor.(VisitorBase[P, R]); ok { + return v.VisitBase(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *Base[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "Base": + return (&Base[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "Base_application": + kids := node.Node.Children() + return (&BaseApplication[P, R]{ + Ident: kids[0].(goohm.RuleNode), + Params: kids[1].(goohm.OptNode), + }).Accept(node.Node, visitor, payload) + case "Base_range": + kids := node.Node.Children() + return (&BaseRange[P, R]{ + OneCharTerminal1: kids[0].(goohm.RuleNode), + Term: kids[1].(goohm.TerminalNode), + OneCharTerminal2: kids[2].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Base_terminal": + kids := node.Node.Children() + return (&BaseTerminal[P, R]{ + Terminal: kids[0].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "Base_paren": + kids := node.Node.Children() + return (&BaseParen[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + Alt: kids[1].(goohm.RuleNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for Base_application +// +// ident Params? ~(ruleDescr? "=" | ":=" | "+=") +func (node *BaseApplication[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Base_application") + if v, ok := visitor.(VisitorBaseApplication[P, R]); ok { + return v.VisitBaseApplication(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *BaseApplication[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexIdent(visitor, payload) + result = node.AcceptParams(visitor, payload) + return +} + +func (node *BaseApplication[P, R]) AcceptLexIdent(visitor any, payload P) (result R) { + // Rule + kids := node.Ident.Children() + result = (&LexIdent[P, R]{ + Name: kids[0].(goohm.RuleNode), + }).Accept(node.Ident, visitor, payload) + return +} + +func (node *BaseApplication[P, R]) AcceptParams(visitor any, payload P) (result R) { + // Opt + if len(node.Params.Children()) > 0 { + n := node.Params.Children()[0] + kids := n.Children() + result = (&Params[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + ListOf: kids[1].(goohm.BHorNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(n, visitor, payload) + } + return +} + +// Accept implementation for Base_range +// +// oneCharTerminal ".." oneCharTerminal +func (node *BaseRange[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Base_range") + if v, ok := visitor.(VisitorBaseRange[P, R]); ok { + return v.VisitBaseRange(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *BaseRange[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexOneCharTerminal1(visitor, payload) + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexOneCharTerminal2(visitor, payload) + return +} + +func (node *BaseRange[P, R]) AcceptLexOneCharTerminal1(visitor any, payload P) (result R) { + // Rule + kids := node.OneCharTerminal1.Children() + result = (&LexOneCharTerminal[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + TerminalChar: kids[1].(goohm.RuleNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(node.OneCharTerminal1, visitor, payload) + return +} + +func (node *BaseRange[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *BaseRange[P, R]) AcceptLexOneCharTerminal2(visitor any, payload P) (result R) { + // Rule + kids := node.OneCharTerminal2.Children() + result = (&LexOneCharTerminal[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + TerminalChar: kids[1].(goohm.RuleNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(node.OneCharTerminal2, visitor, payload) + return +} + +// Accept implementation for Base_terminal +// +// terminal +func (node *BaseTerminal[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Base_terminal") + if v, ok := visitor.(VisitorBaseTerminal[P, R]); ok { + return v.VisitBaseTerminal(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *BaseTerminal[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerminal(visitor, payload) + return +} + +func (node *BaseTerminal[P, R]) AcceptLexTerminal(visitor any, payload P) (result R) { + // Rule + kids := node.Terminal.Children() + result = (&LexTerminal[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + TerminalChar: kids[1].(goohm.ListNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(node.Terminal, visitor, payload) + return +} + +// Accept implementation for Base_paren +// +// "(" Alt ")" +func (node *BaseParen[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "Base_paren") + if v, ok := visitor.(VisitorBaseParen[P, R]); ok { + return v.VisitBaseParen(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *BaseParen[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptAlt(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *BaseParen[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *BaseParen[P, R]) AcceptAlt(visitor any, payload P) (result R) { + // Rule + kids := node.Alt.Children() + result = (&Alt[P, R]{ + NonemptyListOf: kids[0].(goohm.BHorNode), + }).Accept(node.Alt, visitor, payload) + return +} + +func (node *BaseParen[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for ruleDescr - a rule description +// +// ruleDescr (a rule description) +// = "(" ruleDescrText ")" +func (node *LexRuleDescr[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "ruleDescr") + if v, ok := visitor.(VisitorLexRuleDescr[P, R]); ok { + return v.VisitLexRuleDescr(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexRuleDescr[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptLexRuleDescrText(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *LexRuleDescr[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *LexRuleDescr[P, R]) AcceptLexRuleDescrText(visitor any, payload P) (result R) { + // Rule + kids := node.RuleDescrText.Children() + result = (&LexRuleDescrText[P, R]{ + Alt: kids[0].(goohm.ListNode), + }).Accept(node.RuleDescrText, visitor, payload) + return +} + +func (node *LexRuleDescr[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for ruleDescrText +// +// ruleDescrText +// = (~")" any)* +func (node *LexRuleDescrText[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "ruleDescrText") + if v, ok := visitor.(VisitorLexRuleDescrText[P, R]); ok { + return v.VisitLexRuleDescrText(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexRuleDescrText[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexAlt(visitor, payload) + return +} + +func (node *LexRuleDescrText[P, R]) AcceptLexAlt(visitor any, payload P) (result R) { + for _, n := range node.Alt.Children() { + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + } + return +} + +// Accept implementation for caseName +// +// caseName +// = "--" (~"\n" space)* name (~"\n" space)* ("\n" | &"}") +func (node *LexCaseName[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "caseName") + if v, ok := visitor.(VisitorLexCaseName[P, R]); ok { + return v.VisitLexCaseName(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexCaseName[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexAlt1(visitor, payload) + result = node.AcceptLexName(visitor, payload) + result = node.AcceptLexAlt2(visitor, payload) + result = node.AcceptLexAlt3(visitor, payload) + return +} + +func (node *LexCaseName[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *LexCaseName[P, R]) AcceptLexAlt1(visitor any, payload P) (result R) { + for _, n := range node.Alt1.Children() { + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + } + return +} + +func (node *LexCaseName[P, R]) AcceptLexName(visitor any, payload P) (result R) { + // Rule + kids := node.Name.Children() + result = (&LexName[P, R]{ + NameFirst: kids[0].(goohm.RuleNode), + NameRest: kids[1].(goohm.ListNode), + }).Accept(node.Name, visitor, payload) + return +} + +func (node *LexCaseName[P, R]) AcceptLexAlt2(visitor any, payload P) (result R) { + for _, n := range node.Alt2.Children() { + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + } + return +} + +func (node *LexCaseName[P, R]) AcceptLexAlt3(visitor any, payload P) (result R) { + // Node + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.Alt3) + } + } + return +} + +// Accept implementation for name - a name +// +// name (a name) +// = nameFirst nameRest* +func (node *LexName[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "name") + if v, ok := visitor.(VisitorLexName[P, R]); ok { + return v.VisitLexName(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexName[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexNameFirst(visitor, payload) + result = node.AcceptLexNameRest(visitor, payload) + return +} + +func (node *LexName[P, R]) AcceptLexNameFirst(visitor any, payload P) (result R) { + // Rule + kids := node.NameFirst.Children() + result = (&LexNameFirst[P, R]{ + Arg: kids[0], + }).Accept(node.NameFirst, visitor, payload) + return +} + +func (node *LexName[P, R]) AcceptLexNameRest(visitor any, payload P) (result R) { + for _, n := range node.NameRest.Children() { + kids := n.Children() + result = (&LexNameRest[P, R]{ + Arg: kids[0], + }).Accept(n, visitor, payload) + } + return +} + +// Accept implementation for nameFirst +// +// nameFirst +// = "_" +// | letter +func (node *LexNameFirst[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "nameFirst") + if v, ok := visitor.(VisitorLexNameFirst[P, R]); ok { + return v.VisitLexNameFirst(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexNameFirst[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexArg(visitor, payload) + return +} + +func (node *LexNameFirst[P, R]) AcceptLexArg(visitor any, payload P) (result R) { + // Node + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.Arg) + } + } + return +} + +// Accept implementation for nameRest +// +// nameRest +// = "_" +// | alnum +func (node *LexNameRest[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "nameRest") + if v, ok := visitor.(VisitorLexNameRest[P, R]); ok { + return v.VisitLexNameRest(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexNameRest[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexArg(visitor, payload) + return +} + +func (node *LexNameRest[P, R]) AcceptLexArg(visitor any, payload P) (result R) { + // Node + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.Arg) + } + } + return +} + +// Accept implementation for ident - an identifier +// +// ident (an identifier) +// = name +func (node *LexIdent[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "ident") + if v, ok := visitor.(VisitorLexIdent[P, R]); ok { + return v.VisitLexIdent(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexIdent[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexName(visitor, payload) + return +} + +func (node *LexIdent[P, R]) AcceptLexName(visitor any, payload P) (result R) { + // Rule + kids := node.Name.Children() + result = (&LexName[P, R]{ + NameFirst: kids[0].(goohm.RuleNode), + NameRest: kids[1].(goohm.ListNode), + }).Accept(node.Name, visitor, payload) + return +} + +// Accept implementation for terminal +// +// terminal +// = "\"" terminalChar* "\"" +func (node *LexTerminal[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "terminal") + if v, ok := visitor.(VisitorLexTerminal[P, R]); ok { + return v.VisitLexTerminal(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexTerminal[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptLexTerminalChar(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *LexTerminal[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *LexTerminal[P, R]) AcceptLexTerminalChar(visitor any, payload P) (result R) { + for _, n := range node.TerminalChar.Children() { + kids := n.Children() + result = (&LexTerminalChar[P, R]{ + Arg: kids[0], + }).Accept(n, visitor, payload) + } + return +} + +func (node *LexTerminal[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for oneCharTerminal +// +// oneCharTerminal +// = "\"" terminalChar "\"" +func (node *LexOneCharTerminal[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "oneCharTerminal") + if v, ok := visitor.(VisitorLexOneCharTerminal[P, R]); ok { + return v.VisitLexOneCharTerminal(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexOneCharTerminal[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptLexTerminalChar(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *LexOneCharTerminal[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *LexOneCharTerminal[P, R]) AcceptLexTerminalChar(visitor any, payload P) (result R) { + // Rule + kids := node.TerminalChar.Children() + result = (&LexTerminalChar[P, R]{ + Arg: kids[0], + }).Accept(node.TerminalChar, visitor, payload) + return +} + +func (node *LexOneCharTerminal[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for terminalChar +// +// terminalChar +// = escapeChar +// | ~"\\" ~"\"" ~"\n" "\u{0}".."\u{10FFFF}" +func (node *LexTerminalChar[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "terminalChar") + if v, ok := visitor.(VisitorLexTerminalChar[P, R]); ok { + return v.VisitLexTerminalChar(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexTerminalChar[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexArg(visitor, payload) + return +} + +func (node *LexTerminalChar[P, R]) AcceptLexArg(visitor any, payload P) (result R) { + // Node + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.Arg) + } + } + return +} + +// Accept implementation for escapeChar - an escape sequence +// +// escapeChar (an escape sequence) +// = "\\\\" -- backslash +// | "\\\"" -- doubleQuote +// | "\\\'" -- singleQuote +// | "\\b" -- backspace +// | "\\n" -- lineFeed +// | "\\r" -- carriageReturn +// | "\\t" -- tab +// | "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" -- unicodeCodePoint +// | "\\u" hexDigit hexDigit hexDigit hexDigit -- unicodeEscape +// | "\\x" hexDigit hexDigit -- hexEscape +func (node *LexEscapeChar[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar") + if v, ok := visitor.(VisitorLexEscapeChar[P, R]); ok { + return v.VisitLexEscapeChar(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeChar[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "LexEscapeChar": + return (&LexEscapeChar[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "escapeChar_backslash": + kids := node.Node.Children() + return (&LexEscapeCharBackslash[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_doubleQuote": + kids := node.Node.Children() + return (&LexEscapeCharDoubleQuote[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_singleQuote": + kids := node.Node.Children() + return (&LexEscapeCharSingleQuote[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_backspace": + kids := node.Node.Children() + return (&LexEscapeCharBackspace[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_lineFeed": + kids := node.Node.Children() + return (&LexEscapeCharLineFeed[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_carriageReturn": + kids := node.Node.Children() + return (&LexEscapeCharCarriageReturn[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_tab": + kids := node.Node.Children() + return (&LexEscapeCharTab[P, R]{ + Term: kids[0].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_unicodeCodePoint": + kids := node.Node.Children() + return (&LexEscapeCharUnicodeCodePoint[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + HexDigit1: kids[1].(goohm.RuleNode), + HexDigit2: kids[2].(goohm.OptNode), + HexDigit3: kids[3].(goohm.OptNode), + HexDigit4: kids[4].(goohm.OptNode), + HexDigit5: kids[5].(goohm.OptNode), + HexDigit6: kids[6].(goohm.OptNode), + Term2: kids[7].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_unicodeEscape": + kids := node.Node.Children() + return (&LexEscapeCharUnicodeEscape[P, R]{ + Term: kids[0].(goohm.TerminalNode), + HexDigit1: kids[1].(goohm.RuleNode), + HexDigit2: kids[2].(goohm.RuleNode), + HexDigit3: kids[3].(goohm.RuleNode), + HexDigit4: kids[4].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + case "escapeChar_hexEscape": + kids := node.Node.Children() + return (&LexEscapeCharHexEscape[P, R]{ + Term: kids[0].(goohm.TerminalNode), + HexDigit1: kids[1].(goohm.RuleNode), + HexDigit2: kids[2].(goohm.RuleNode), + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for escapeChar_backslash +// +// "\\\\" +func (node *LexEscapeCharBackslash[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_backslash") + if v, ok := visitor.(VisitorLexEscapeCharBackslash[P, R]); ok { + return v.VisitLexEscapeCharBackslash(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharBackslash[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharBackslash[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_doubleQuote +// +// "\\\"" +func (node *LexEscapeCharDoubleQuote[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_doubleQuote") + if v, ok := visitor.(VisitorLexEscapeCharDoubleQuote[P, R]); ok { + return v.VisitLexEscapeCharDoubleQuote(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharDoubleQuote[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharDoubleQuote[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_singleQuote +// +// "\\\'" +func (node *LexEscapeCharSingleQuote[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_singleQuote") + if v, ok := visitor.(VisitorLexEscapeCharSingleQuote[P, R]); ok { + return v.VisitLexEscapeCharSingleQuote(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharSingleQuote[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharSingleQuote[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_backspace +// +// "\\b" +func (node *LexEscapeCharBackspace[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_backspace") + if v, ok := visitor.(VisitorLexEscapeCharBackspace[P, R]); ok { + return v.VisitLexEscapeCharBackspace(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharBackspace[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharBackspace[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_lineFeed +// +// "\\n" +func (node *LexEscapeCharLineFeed[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_lineFeed") + if v, ok := visitor.(VisitorLexEscapeCharLineFeed[P, R]); ok { + return v.VisitLexEscapeCharLineFeed(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharLineFeed[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharLineFeed[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_carriageReturn +// +// "\\r" +func (node *LexEscapeCharCarriageReturn[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_carriageReturn") + if v, ok := visitor.(VisitorLexEscapeCharCarriageReturn[P, R]); ok { + return v.VisitLexEscapeCharCarriageReturn(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharCarriageReturn[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharCarriageReturn[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_tab +// +// "\\t" +func (node *LexEscapeCharTab[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_tab") + if v, ok := visitor.(VisitorLexEscapeCharTab[P, R]); ok { + return v.VisitLexEscapeCharTab(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharTab[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexEscapeCharTab[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for escapeChar_unicodeCodePoint +// +// "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" +func (node *LexEscapeCharUnicodeCodePoint[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_unicodeCodePoint") + if v, ok := visitor.(VisitorLexEscapeCharUnicodeCodePoint[P, R]); ok { + return v.VisitLexEscapeCharUnicodeCodePoint(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptLexHexDigit1(visitor, payload) + result = node.AcceptLexHexDigit2(visitor, payload) + result = node.AcceptLexHexDigit3(visitor, payload) + result = node.AcceptLexHexDigit4(visitor, payload) + result = node.AcceptLexHexDigit5(visitor, payload) + result = node.AcceptLexHexDigit6(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit1(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit1) + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit2(visitor any, payload P) (result R) { + // Opt + if len(node.HexDigit2.Children()) > 0 { + n := node.HexDigit2.Children()[0] + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit3(visitor any, payload P) (result R) { + // Opt + if len(node.HexDigit3.Children()) > 0 { + n := node.HexDigit3.Children()[0] + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit4(visitor any, payload P) (result R) { + // Opt + if len(node.HexDigit4.Children()) > 0 { + n := node.HexDigit4.Children()[0] + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit5(visitor any, payload P) (result R) { + // Opt + if len(node.HexDigit5.Children()) > 0 { + n := node.HexDigit5.Children()[0] + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexHexDigit6(visitor any, payload P) (result R) { + // Opt + if len(node.HexDigit6.Children()) > 0 { + n := node.HexDigit6.Children()[0] + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + return +} + +func (node *LexEscapeCharUnicodeCodePoint[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for escapeChar_unicodeEscape +// +// "\\u" hexDigit hexDigit hexDigit hexDigit +func (node *LexEscapeCharUnicodeEscape[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_unicodeEscape") + if v, ok := visitor.(VisitorLexEscapeCharUnicodeEscape[P, R]); ok { + return v.VisitLexEscapeCharUnicodeEscape(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexHexDigit1(visitor, payload) + result = node.AcceptLexHexDigit2(visitor, payload) + result = node.AcceptLexHexDigit3(visitor, payload) + result = node.AcceptLexHexDigit4(visitor, payload) + return +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) AcceptLexHexDigit1(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit1) + } + return +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) AcceptLexHexDigit2(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit2) + } + return +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) AcceptLexHexDigit3(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit3) + } + return +} + +func (node *LexEscapeCharUnicodeEscape[P, R]) AcceptLexHexDigit4(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit4) + } + return +} + +// Accept implementation for escapeChar_hexEscape +// +// "\\x" hexDigit hexDigit +func (node *LexEscapeCharHexEscape[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "escapeChar_hexEscape") + if v, ok := visitor.(VisitorLexEscapeCharHexEscape[P, R]); ok { + return v.VisitLexEscapeCharHexEscape(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexEscapeCharHexEscape[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexHexDigit1(visitor, payload) + result = node.AcceptLexHexDigit2(visitor, payload) + return +} + +func (node *LexEscapeCharHexEscape[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *LexEscapeCharHexEscape[P, R]) AcceptLexHexDigit1(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit1) + } + return +} + +func (node *LexEscapeCharHexEscape[P, R]) AcceptLexHexDigit2(visitor any, payload P) (result R) { + // Rule + // "unknown rule hexDigit" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.HexDigit2) + } + return +} + +// Accept implementation for space +// +// space +// += comment +func (node *LexSpace[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "space") + if v, ok := visitor.(VisitorLexSpace[P, R]); ok { + return v.VisitLexSpace(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexSpace[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexComment(visitor, payload) + return +} + +func (node *LexSpace[P, R]) AcceptLexComment(visitor any, payload P) (result R) { + // Rule + kids := node.Comment.Children() + result = (&LexComment[P, R]{ + Node: kids[0], + }).Accept(node.Comment, visitor, payload) + return +} + +// Accept implementation for comment +// +// comment +// = "//" (~"\n" any)* &("\n" | end) -- singleLine +// | "/*" (~"*/" any)* "*/" -- multiLine +func (node *LexComment[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "comment") + if v, ok := visitor.(VisitorLexComment[P, R]); ok { + return v.VisitLexComment(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexComment[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "LexComment": + return (&LexComment[P, R]{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).DefaultAccept(visitor, payload) + case "comment_singleLine": + kids := node.Node.Children() + return (&LexCommentSingleLine[P, R]{ + Term: kids[0].(goohm.TerminalNode), + Alt: kids[1].(goohm.ListNode), + }).Accept(node.Node, visitor, payload) + case "comment_multiLine": + kids := node.Node.Children() + return (&LexCommentMultiLine[P, R]{ + Term1: kids[0].(goohm.TerminalNode), + Alt: kids[1].(goohm.ListNode), + Term2: kids[2].(goohm.TerminalNode), + }).Accept(node.Node, visitor, payload) + default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +} + +// Accept implementation for comment_singleLine +// +// "//" (~"\n" any)* &("\n" | end) +func (node *LexCommentSingleLine[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "comment_singleLine") + if v, ok := visitor.(VisitorLexCommentSingleLine[P, R]); ok { + return v.VisitLexCommentSingleLine(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexCommentSingleLine[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + result = node.AcceptLexAlt(visitor, payload) + return +} + +func (node *LexCommentSingleLine[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +func (node *LexCommentSingleLine[P, R]) AcceptLexAlt(visitor any, payload P) (result R) { + for _, n := range node.Alt.Children() { + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + } + return +} + +// Accept implementation for comment_multiLine +// +// "/*" (~"*/" any)* "*/" +func (node *LexCommentMultiLine[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "comment_multiLine") + if v, ok := visitor.(VisitorLexCommentMultiLine[P, R]); ok { + return v.VisitLexCommentMultiLine(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexCommentMultiLine[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm1(visitor, payload) + result = node.AcceptLexAlt(visitor, payload) + result = node.AcceptLexTerm2(visitor, payload) + return +} + +func (node *LexCommentMultiLine[P, R]) AcceptLexTerm1(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term1) + } + return +} + +func (node *LexCommentMultiLine[P, R]) AcceptLexAlt(visitor any, payload P) (result R) { + for _, n := range node.Alt.Children() { + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } + } + return +} + +func (node *LexCommentMultiLine[P, R]) AcceptLexTerm2(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term2) + } + return +} + +// Accept implementation for tokens +// +// tokens = token* +func (node *LexTokens[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "tokens") + if v, ok := visitor.(VisitorLexTokens[P, R]); ok { + return v.VisitLexTokens(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexTokens[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexToken(visitor, payload) + return +} + +func (node *LexTokens[P, R]) AcceptLexToken(visitor any, payload P) (result R) { + for _, n := range node.Token.Children() { + kids := n.Children() + result = (&LexToken[P, R]{ + Arg1: kids[0], + }).Accept(n, visitor, payload) + } + return +} + +// Accept implementation for token +// +// token = caseName | comment | ident | operator | punctuation | terminal | any +func (node *LexToken[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "token") + if v, ok := visitor.(VisitorLexToken[P, R]); ok { + return v.VisitLexToken(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexToken[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexArg1(visitor, payload) + return +} + +func (node *LexToken[P, R]) AcceptLexArg1(visitor any, payload P) (result R) { + // Node + { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.Arg1) + } + } + return +} + +// Accept implementation for operator +// +// operator = "<:" | "=" | ":=" | "+=" | "*" | "+" | "?" | "~" | "&" +func (node *LexOperator[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "operator") + if v, ok := visitor.(VisitorLexOperator[P, R]); ok { + return v.VisitLexOperator(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexOperator[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexOperator[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + +// Accept implementation for punctuation +// +// punctuation = "<" | ">" | "," | "--" +func (node *LexPunctuation[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + goohm.AssertName(this, "punctuation") + if v, ok := visitor.(VisitorLexPunctuation[P, R]); ok { + return v.VisitLexPunctuation(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +func (node *LexPunctuation[P, R]) DefaultAccept(visitor any, payload P) (result R) { + result = node.AcceptLexTerm(visitor, payload) + return +} + +func (node *LexPunctuation[P, R]) AcceptLexTerm(visitor any, payload P) (result R) { + // Term + if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.Term) + } + return +} + diff --git a/golang/cli/ohm/exec_accept.go b/golang/cli/ohm/exec_accept.go new file mode 100644 index 00000000..e86fa485 --- /dev/null +++ b/golang/cli/ohm/exec_accept.go @@ -0,0 +1,73 @@ +package ohm + +import ( + "context" + "fmt" + "os" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" +) + +type execeriseGenedCmd struct { + Grammar string `opts:"mode=arg" help:"Path to .ohm grammar file to generate a visitor for."` +} + +func NewExerciseGenedCmd() *execeriseGenedCmd { + return &execeriseGenedCmd{} +} + +func (cm *execeriseGenedCmd) Run() error { + if cm.Grammar[:1] == "@" { + barr, err := os.ReadFile(cm.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %[1]v", err) + } + cm.Grammar = string(barr) + } + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return fmt.Errorf("creating grammar: %[1]v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(cm.Grammar); err != nil { + return fmt.Errorf("matching: %[1]v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return fmt.Errorf("Error getting cst root. %[1]v", err) + } + gmrs := &Grammars[any, any]{ + Grammar: root.Children()[0].(goohm.ListNode), + } + v := &v{} + gmrs.Accept(root, v, nil) + return nil +} + +type v struct { +} + +// BuiltInRule implements [goohm.BuiltinVisitor]. +func (v *v) BuiltInRule(node goohm.Node) { + fmt.Printf("%s", node.SourceString()) +} + +// Terminal implements [goohm.TerminalVisitor]. +func (v *v) Terminal(node goohm.TerminalNode) { + fmt.Printf("%s", node.SourceString()) +} + +var ( + _ goohm.TerminalVisitor = (*v)(nil) + _ goohm.BuiltinVisitor = (*v)(nil) +) diff --git a/golang/cli/ohm/interfaces.go b/golang/cli/ohm/interfaces.go new file mode 100644 index 00000000..3180bb6d --- /dev/null +++ b/golang/cli/ohm/interfaces.go @@ -0,0 +1,546 @@ +// Code generated by ohmgo generate interfaces - DO NOT EDIT. +package ohm + +// interfaces for grammar Ohm + +// Grammars +// -- rule -- +// Grammars +// = Grammar* +// ---- +type VisitorGrammars[P, R any] interface { + VisitGrammars(node *Grammars[P, R], payload P) (result R) +} + +// Grammar +// -- rule -- +// Grammar +// = ident SuperGrammar? "{" Rule* "}" +// ---- +type VisitorGrammar[P, R any] interface { + VisitGrammar(node *Grammar[P, R], payload P) (result R) +} + +// SuperGrammar +// -- rule -- +// SuperGrammar +// = "<:" ident +// ---- +type VisitorSuperGrammar[P, R any] interface { + VisitSuperGrammar(node *SuperGrammar[P, R], payload P) (result R) +} + +// Rule +// -- rule -- +// Rule +// = ident Formals? ruleDescr? "=" RuleBody -- define +// | ident Formals? ":=" OverrideRuleBody -- override +// | ident Formals? "+=" RuleBody -- extend +// +// ---- +type VisitorRule[P, R any] interface { + VisitRule(node *Rule[P, R], payload P) (result R) +} + +// Rule_define +// -- rule -- +// ident Formals? ruleDescr? "=" RuleBody +// ---- +type VisitorRuleDefine[P, R any] interface { + VisitRuleDefine(node *RuleDefine[P, R], payload P) (result R) +} + +// Rule_override +// -- rule -- +// ident Formals? ":=" OverrideRuleBody +// ---- +type VisitorRuleOverride[P, R any] interface { + VisitRuleOverride(node *RuleOverride[P, R], payload P) (result R) +} + +// Rule_extend +// -- rule -- +// ident Formals? "+=" RuleBody +// ---- +type VisitorRuleExtend[P, R any] interface { + VisitRuleExtend(node *RuleExtend[P, R], payload P) (result R) +} + +// RuleBody +// -- rule -- +// RuleBody +// = "|"? NonemptyListOf +// ---- +type VisitorRuleBody[P, R any] interface { + VisitRuleBody(node *RuleBody[P, R], payload P) (result R) +} + +// TopLevelTerm +// -- rule -- +// TopLevelTerm +// = Seq caseName -- inline +// | Seq +// ---- +type VisitorTopLevelTerm[P, R any] interface { + VisitTopLevelTerm(node *TopLevelTerm[P, R], payload P) (result R) +} + +// TopLevelTerm_inline +// -- rule -- +// Seq caseName +// ---- +type VisitorTopLevelTermInline[P, R any] interface { + VisitTopLevelTermInline(node *TopLevelTermInline[P, R], payload P) (result R) +} + +// OverrideRuleBody +// -- rule -- +// OverrideRuleBody +// = "|"? NonemptyListOf +// ---- +type VisitorOverrideRuleBody[P, R any] interface { + VisitOverrideRuleBody(node *OverrideRuleBody[P, R], payload P) (result R) +} + +// OverrideTopLevelTerm +// -- rule -- +// OverrideTopLevelTerm +// = "..." -- superSplice +// | TopLevelTerm +// ---- +type VisitorOverrideTopLevelTerm[P, R any] interface { + VisitOverrideTopLevelTerm(node *OverrideTopLevelTerm[P, R], payload P) (result R) +} + +// OverrideTopLevelTerm_superSplice +// -- rule -- +// "..." +// ---- +type VisitorOverrideTopLevelTermSuperSplice[P, R any] interface { + VisitOverrideTopLevelTermSuperSplice(node *OverrideTopLevelTermSuperSplice[P, R], payload P) (result R) +} + +// Formals +// -- rule -- +// Formals +// = "<" ListOf ">" +// ---- +type VisitorFormals[P, R any] interface { + VisitFormals(node *Formals[P, R], payload P) (result R) +} + +// Params +// -- rule -- +// Params +// = "<" ListOf ">" +// ---- +type VisitorParams[P, R any] interface { + VisitParams(node *Params[P, R], payload P) (result R) +} + +// Alt +// -- rule -- +// Alt +// = NonemptyListOf +// ---- +type VisitorAlt[P, R any] interface { + VisitAlt(node *Alt[P, R], payload P) (result R) +} + +// Seq +// -- rule -- +// Seq +// = Iter* +// ---- +type VisitorSeq[P, R any] interface { + VisitSeq(node *Seq[P, R], payload P) (result R) +} + +// Iter +// -- rule -- +// Iter +// = Pred "*" -- star +// | Pred "+" -- plus +// | Pred "?" -- opt +// | Pred +// ---- +type VisitorIter[P, R any] interface { + VisitIter(node *Iter[P, R], payload P) (result R) +} + +// Iter_star +// -- rule -- +// Pred "*" +// ---- +type VisitorIterStar[P, R any] interface { + VisitIterStar(node *IterStar[P, R], payload P) (result R) +} + +// Iter_plus +// -- rule -- +// Pred "+" +// ---- +type VisitorIterPlus[P, R any] interface { + VisitIterPlus(node *IterPlus[P, R], payload P) (result R) +} + +// Iter_opt +// -- rule -- +// Pred "?" +// ---- +type VisitorIterOpt[P, R any] interface { + VisitIterOpt(node *IterOpt[P, R], payload P) (result R) +} + +// Pred +// -- rule -- +// Pred +// = "~" Lex -- not +// | "&" Lex -- lookahead +// | Lex +// ---- +type VisitorPred[P, R any] interface { + VisitPred(node *Pred[P, R], payload P) (result R) +} + +// Pred_not +// -- rule -- +// "~" Lex +// ---- +type VisitorPredNot[P, R any] interface { + VisitPredNot(node *PredNot[P, R], payload P) (result R) +} + +// Pred_lookahead +// -- rule -- +// "&" Lex +// ---- +type VisitorPredLookahead[P, R any] interface { + VisitPredLookahead(node *PredLookahead[P, R], payload P) (result R) +} + +// Lex +// -- rule -- +// Lex +// = "#" Base -- lex +// | Base +// ---- +type VisitorLex[P, R any] interface { + VisitLex(node *Lex[P, R], payload P) (result R) +} + +// Lex_lex +// -- rule -- +// "#" Base +// ---- +type VisitorLexLex[P, R any] interface { + VisitLexLex(node *LexLex[P, R], payload P) (result R) +} + +// Base +// -- rule -- +// Base +// = ident Params? ~(ruleDescr? "=" | ":=" | "+=") -- application +// | oneCharTerminal ".." oneCharTerminal -- range +// | terminal -- terminal +// | "(" Alt ")" -- paren +// +// ---- +type VisitorBase[P, R any] interface { + VisitBase(node *Base[P, R], payload P) (result R) +} + +// Base_application +// -- rule -- +// ident Params? ~(ruleDescr? "=" | ":=" | "+=") +// ---- +type VisitorBaseApplication[P, R any] interface { + VisitBaseApplication(node *BaseApplication[P, R], payload P) (result R) +} + +// Base_range +// -- rule -- +// oneCharTerminal ".." oneCharTerminal +// ---- +type VisitorBaseRange[P, R any] interface { + VisitBaseRange(node *BaseRange[P, R], payload P) (result R) +} + +// Base_terminal +// -- rule -- +// terminal +// ---- +type VisitorBaseTerminal[P, R any] interface { + VisitBaseTerminal(node *BaseTerminal[P, R], payload P) (result R) +} + +// Base_paren +// -- rule -- +// "(" Alt ")" +// ---- +type VisitorBaseParen[P, R any] interface { + VisitBaseParen(node *BaseParen[P, R], payload P) (result R) +} + +// ruleDescr - a rule description +// -- rule -- +// ruleDescr (a rule description) +// = "(" ruleDescrText ")" +// ---- +type VisitorLexRuleDescr[P, R any] interface { + VisitLexRuleDescr(node *LexRuleDescr[P, R], payload P) (result R) +} + +// ruleDescrText +// -- rule -- +// ruleDescrText +// = (~")" any)* +// ---- +type VisitorLexRuleDescrText[P, R any] interface { + VisitLexRuleDescrText(node *LexRuleDescrText[P, R], payload P) (result R) +} + +// caseName +// -- rule -- +// caseName +// = "--" (~"\n" space)* name (~"\n" space)* ("\n" | &"}") +// ---- +type VisitorLexCaseName[P, R any] interface { + VisitLexCaseName(node *LexCaseName[P, R], payload P) (result R) +} + +// name - a name +// -- rule -- +// name (a name) +// = nameFirst nameRest* +// ---- +type VisitorLexName[P, R any] interface { + VisitLexName(node *LexName[P, R], payload P) (result R) +} + +// nameFirst +// -- rule -- +// nameFirst +// = "_" +// | letter +// ---- +type VisitorLexNameFirst[P, R any] interface { + VisitLexNameFirst(node *LexNameFirst[P, R], payload P) (result R) +} + +// nameRest +// -- rule -- +// nameRest +// = "_" +// | alnum +// ---- +type VisitorLexNameRest[P, R any] interface { + VisitLexNameRest(node *LexNameRest[P, R], payload P) (result R) +} + +// ident - an identifier +// -- rule -- +// ident (an identifier) +// = name +// ---- +type VisitorLexIdent[P, R any] interface { + VisitLexIdent(node *LexIdent[P, R], payload P) (result R) +} + +// terminal +// -- rule -- +// terminal +// = "\"" terminalChar* "\"" +// ---- +type VisitorLexTerminal[P, R any] interface { + VisitLexTerminal(node *LexTerminal[P, R], payload P) (result R) +} + +// oneCharTerminal +// -- rule -- +// oneCharTerminal +// = "\"" terminalChar "\"" +// ---- +type VisitorLexOneCharTerminal[P, R any] interface { + VisitLexOneCharTerminal(node *LexOneCharTerminal[P, R], payload P) (result R) +} + +// terminalChar +// -- rule -- +// terminalChar +// = escapeChar +// | ~"\\" ~"\"" ~"\n" "\u{0}".."\u{10FFFF}" +// ---- +type VisitorLexTerminalChar[P, R any] interface { + VisitLexTerminalChar(node *LexTerminalChar[P, R], payload P) (result R) +} + +// escapeChar - an escape sequence +// -- rule -- +// escapeChar (an escape sequence) +// = "\\\\" -- backslash +// | "\\\"" -- doubleQuote +// | "\\\'" -- singleQuote +// | "\\b" -- backspace +// | "\\n" -- lineFeed +// | "\\r" -- carriageReturn +// | "\\t" -- tab +// | "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" -- unicodeCodePoint +// | "\\u" hexDigit hexDigit hexDigit hexDigit -- unicodeEscape +// | "\\x" hexDigit hexDigit -- hexEscape +// +// ---- +type VisitorLexEscapeChar[P, R any] interface { + VisitLexEscapeChar(node *LexEscapeChar[P, R], payload P) (result R) +} + +// escapeChar_backslash +// -- rule -- +// "\\\\" +// ---- +type VisitorLexEscapeCharBackslash[P, R any] interface { + VisitLexEscapeCharBackslash(node *LexEscapeCharBackslash[P, R], payload P) (result R) +} + +// escapeChar_doubleQuote +// -- rule -- +// "\\\"" +// ---- +type VisitorLexEscapeCharDoubleQuote[P, R any] interface { + VisitLexEscapeCharDoubleQuote(node *LexEscapeCharDoubleQuote[P, R], payload P) (result R) +} + +// escapeChar_singleQuote +// -- rule -- +// "\\\'" +// ---- +type VisitorLexEscapeCharSingleQuote[P, R any] interface { + VisitLexEscapeCharSingleQuote(node *LexEscapeCharSingleQuote[P, R], payload P) (result R) +} + +// escapeChar_backspace +// -- rule -- +// "\\b" +// ---- +type VisitorLexEscapeCharBackspace[P, R any] interface { + VisitLexEscapeCharBackspace(node *LexEscapeCharBackspace[P, R], payload P) (result R) +} + +// escapeChar_lineFeed +// -- rule -- +// "\\n" +// ---- +type VisitorLexEscapeCharLineFeed[P, R any] interface { + VisitLexEscapeCharLineFeed(node *LexEscapeCharLineFeed[P, R], payload P) (result R) +} + +// escapeChar_carriageReturn +// -- rule -- +// "\\r" +// ---- +type VisitorLexEscapeCharCarriageReturn[P, R any] interface { + VisitLexEscapeCharCarriageReturn(node *LexEscapeCharCarriageReturn[P, R], payload P) (result R) +} + +// escapeChar_tab +// -- rule -- +// "\\t" +// ---- +type VisitorLexEscapeCharTab[P, R any] interface { + VisitLexEscapeCharTab(node *LexEscapeCharTab[P, R], payload P) (result R) +} + +// escapeChar_unicodeCodePoint +// -- rule -- +// "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" +// ---- +type VisitorLexEscapeCharUnicodeCodePoint[P, R any] interface { + VisitLexEscapeCharUnicodeCodePoint(node *LexEscapeCharUnicodeCodePoint[P, R], payload P) (result R) +} + +// escapeChar_unicodeEscape +// -- rule -- +// "\\u" hexDigit hexDigit hexDigit hexDigit +// ---- +type VisitorLexEscapeCharUnicodeEscape[P, R any] interface { + VisitLexEscapeCharUnicodeEscape(node *LexEscapeCharUnicodeEscape[P, R], payload P) (result R) +} + +// escapeChar_hexEscape +// -- rule -- +// "\\x" hexDigit hexDigit +// ---- +type VisitorLexEscapeCharHexEscape[P, R any] interface { + VisitLexEscapeCharHexEscape(node *LexEscapeCharHexEscape[P, R], payload P) (result R) +} + +// space +// -- rule -- +// space +// += comment +// ---- +type VisitorLexSpace[P, R any] interface { + VisitLexSpace(node *LexSpace[P, R], payload P) (result R) +} + +// comment +// -- rule -- +// comment +// = "//" (~"\n" any)* &("\n" | end) -- singleLine +// | "/*" (~"*/" any)* "*/" -- multiLine +// +// ---- +type VisitorLexComment[P, R any] interface { + VisitLexComment(node *LexComment[P, R], payload P) (result R) +} + +// comment_singleLine +// -- rule -- +// "//" (~"\n" any)* &("\n" | end) +// ---- +type VisitorLexCommentSingleLine[P, R any] interface { + VisitLexCommentSingleLine(node *LexCommentSingleLine[P, R], payload P) (result R) +} + +// comment_multiLine +// -- rule -- +// "/*" (~"*/" any)* "*/" +// ---- +type VisitorLexCommentMultiLine[P, R any] interface { + VisitLexCommentMultiLine(node *LexCommentMultiLine[P, R], payload P) (result R) +} + +// tokens +// -- rule -- +// tokens = token* +// ---- +type VisitorLexTokens[P, R any] interface { + VisitLexTokens(node *LexTokens[P, R], payload P) (result R) +} + +// token +// -- rule -- +// token = caseName | comment | ident | operator | punctuation | terminal | any +// ---- +type VisitorLexToken[P, R any] interface { + VisitLexToken(node *LexToken[P, R], payload P) (result R) +} + +// operator +// -- rule -- +// operator = "<:" | "=" | ":=" | "+=" | "*" | "+" | "?" | "~" | "&" +// ---- +type VisitorLexOperator[P, R any] interface { + VisitLexOperator(node *LexOperator[P, R], payload P) (result R) +} + +// punctuation +// -- rule -- +// punctuation = "<" | ">" | "," | "--" +// ---- +type VisitorLexPunctuation[P, R any] interface { + VisitLexPunctuation(node *LexPunctuation[P, R], payload P) (result R) +} + diff --git a/golang/cli/ohm/types.go b/golang/cli/ohm/types.go new file mode 100644 index 00000000..f56fe313 --- /dev/null +++ b/golang/cli/ohm/types.go @@ -0,0 +1,609 @@ +// Code generated by ohmgo generate types - DO NOT EDIT. +package ohm + +import ( + "github.com/ohmjs/goohm" +) + +// types for grammar Ohm + +// Grammars +// -- rule -- +// Grammars +// = Grammar* +// ---- +type Grammars[P, R any] struct { + Grammar goohm.ListNode +} + +// Grammar +// -- rule -- +// Grammar +// = ident SuperGrammar? "{" Rule* "}" +// ---- +type Grammar[P, R any] struct { + Ident goohm.RuleNode + SuperGrammar goohm.OptNode + Term1 goohm.TerminalNode + Rule goohm.ListNode + Term2 goohm.TerminalNode +} + +// SuperGrammar +// -- rule -- +// SuperGrammar +// = "<:" ident +// ---- +type SuperGrammar[P, R any] struct { + Term goohm.TerminalNode + Ident goohm.RuleNode +} + +// Rule +// -- rule -- +// Rule +// = ident Formals? ruleDescr? "=" RuleBody -- define +// | ident Formals? ":=" OverrideRuleBody -- override +// | ident Formals? "+=" RuleBody -- extend +// +// ---- +type Rule[P, R any] struct { + Node goohm.Node +} + +// Rule_define +// -- rule -- +// ident Formals? ruleDescr? "=" RuleBody +// ---- +type RuleDefine[P, R any] struct { + Ident goohm.RuleNode + Formals goohm.OptNode + RuleDescr goohm.OptNode + Term goohm.TerminalNode + RuleBody goohm.RuleNode +} + +// Rule_override +// -- rule -- +// ident Formals? ":=" OverrideRuleBody +// ---- +type RuleOverride[P, R any] struct { + Ident goohm.RuleNode + Formals goohm.OptNode + Term goohm.TerminalNode + OverrideRuleBody goohm.RuleNode +} + +// Rule_extend +// -- rule -- +// ident Formals? "+=" RuleBody +// ---- +type RuleExtend[P, R any] struct { + Ident goohm.RuleNode + Formals goohm.OptNode + Term goohm.TerminalNode + RuleBody goohm.RuleNode +} + +// RuleBody +// -- rule -- +// RuleBody +// = "|"? NonemptyListOf +// ---- +type RuleBody[P, R any] struct { + Term goohm.OptNode + NonemptyListOf goohm.BHorNode +} + +// TopLevelTerm +// -- rule -- +// TopLevelTerm +// = Seq caseName -- inline +// | Seq +// ---- +type TopLevelTerm[P, R any] struct { + Node goohm.Node +} + +// TopLevelTerm_inline +// -- rule -- +// Seq caseName +// ---- +type TopLevelTermInline[P, R any] struct { + Seq goohm.RuleNode + CaseName goohm.RuleNode +} + +// OverrideRuleBody +// -- rule -- +// OverrideRuleBody +// = "|"? NonemptyListOf +// ---- +type OverrideRuleBody[P, R any] struct { + Term goohm.OptNode + NonemptyListOf goohm.BHorNode +} + +// OverrideTopLevelTerm +// -- rule -- +// OverrideTopLevelTerm +// = "..." -- superSplice +// | TopLevelTerm +// ---- +type OverrideTopLevelTerm[P, R any] struct { + Node goohm.Node +} + +// OverrideTopLevelTerm_superSplice +// -- rule -- +// "..." +// ---- +type OverrideTopLevelTermSuperSplice[P, R any] struct { + Term goohm.TerminalNode +} + +// Formals +// -- rule -- +// Formals +// = "<" ListOf ">" +// ---- +type Formals[P, R any] struct { + Term1 goohm.TerminalNode + ListOf goohm.BHorNode + Term2 goohm.TerminalNode +} + +// Params +// -- rule -- +// Params +// = "<" ListOf ">" +// ---- +type Params[P, R any] struct { + Term1 goohm.TerminalNode + ListOf goohm.BHorNode + Term2 goohm.TerminalNode +} + +// Alt +// -- rule -- +// Alt +// = NonemptyListOf +// ---- +type Alt[P, R any] struct { + NonemptyListOf goohm.BHorNode +} + +// Seq +// -- rule -- +// Seq +// = Iter* +// ---- +type Seq[P, R any] struct { + Iter goohm.ListNode +} + +// Iter +// -- rule -- +// Iter +// = Pred "*" -- star +// | Pred "+" -- plus +// | Pred "?" -- opt +// | Pred +// ---- +type Iter[P, R any] struct { + Node goohm.Node +} + +// Iter_star +// -- rule -- +// Pred "*" +// ---- +type IterStar[P, R any] struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Iter_plus +// -- rule -- +// Pred "+" +// ---- +type IterPlus[P, R any] struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Iter_opt +// -- rule -- +// Pred "?" +// ---- +type IterOpt[P, R any] struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Pred +// -- rule -- +// Pred +// = "~" Lex -- not +// | "&" Lex -- lookahead +// | Lex +// ---- +type Pred[P, R any] struct { + Node goohm.Node +} + +// Pred_not +// -- rule -- +// "~" Lex +// ---- +type PredNot[P, R any] struct { + Term goohm.TerminalNode + Lex goohm.RuleNode +} + +// Pred_lookahead +// -- rule -- +// "&" Lex +// ---- +type PredLookahead[P, R any] struct { + Term goohm.TerminalNode + Lex goohm.RuleNode +} + +// Lex +// -- rule -- +// Lex +// = "#" Base -- lex +// | Base +// ---- +type Lex[P, R any] struct { + Node goohm.Node +} + +// Lex_lex +// -- rule -- +// "#" Base +// ---- +type LexLex[P, R any] struct { + Term goohm.TerminalNode + Base goohm.RuleNode +} + +// Base +// -- rule -- +// Base +// = ident Params? ~(ruleDescr? "=" | ":=" | "+=") -- application +// | oneCharTerminal ".." oneCharTerminal -- range +// | terminal -- terminal +// | "(" Alt ")" -- paren +// +// ---- +type Base[P, R any] struct { + Node goohm.Node +} + +// Base_application +// -- rule -- +// ident Params? ~(ruleDescr? "=" | ":=" | "+=") +// ---- +type BaseApplication[P, R any] struct { + Ident goohm.RuleNode + Params goohm.OptNode +} + +// Base_range +// -- rule -- +// oneCharTerminal ".." oneCharTerminal +// ---- +type BaseRange[P, R any] struct { + OneCharTerminal1 goohm.RuleNode + Term goohm.TerminalNode + OneCharTerminal2 goohm.RuleNode +} + +// Base_terminal +// -- rule -- +// terminal +// ---- +type BaseTerminal[P, R any] struct { + Terminal goohm.RuleNode +} + +// Base_paren +// -- rule -- +// "(" Alt ")" +// ---- +type BaseParen[P, R any] struct { + Term1 goohm.TerminalNode + Alt goohm.RuleNode + Term2 goohm.TerminalNode +} + +// ruleDescr - a rule description +// -- rule -- +// ruleDescr (a rule description) +// = "(" ruleDescrText ")" +// ---- +type LexRuleDescr[P, R any] struct { + Term1 goohm.TerminalNode + RuleDescrText goohm.RuleNode + Term2 goohm.TerminalNode +} + +// ruleDescrText +// -- rule -- +// ruleDescrText +// = (~")" any)* +// ---- +type LexRuleDescrText[P, R any] struct { + Alt goohm.ListNode +} + +// caseName +// -- rule -- +// caseName +// = "--" (~"\n" space)* name (~"\n" space)* ("\n" | &"}") +// ---- +type LexCaseName[P, R any] struct { + Term goohm.TerminalNode + Alt1 goohm.ListNode + Name goohm.RuleNode + Alt2 goohm.ListNode + Alt3 goohm.Node +} + +// name - a name +// -- rule -- +// name (a name) +// = nameFirst nameRest* +// ---- +type LexName[P, R any] struct { + NameFirst goohm.RuleNode + NameRest goohm.ListNode +} + +// nameFirst +// -- rule -- +// nameFirst +// = "_" +// | letter +// ---- +type LexNameFirst[P, R any] struct { + Arg goohm.Node +} + +// nameRest +// -- rule -- +// nameRest +// = "_" +// | alnum +// ---- +type LexNameRest[P, R any] struct { + Arg goohm.Node +} + +// ident - an identifier +// -- rule -- +// ident (an identifier) +// = name +// ---- +type LexIdent[P, R any] struct { + Name goohm.RuleNode +} + +// terminal +// -- rule -- +// terminal +// = "\"" terminalChar* "\"" +// ---- +type LexTerminal[P, R any] struct { + Term1 goohm.TerminalNode + TerminalChar goohm.ListNode + Term2 goohm.TerminalNode +} + +// oneCharTerminal +// -- rule -- +// oneCharTerminal +// = "\"" terminalChar "\"" +// ---- +type LexOneCharTerminal[P, R any] struct { + Term1 goohm.TerminalNode + TerminalChar goohm.RuleNode + Term2 goohm.TerminalNode +} + +// terminalChar +// -- rule -- +// terminalChar +// = escapeChar +// | ~"\\" ~"\"" ~"\n" "\u{0}".."\u{10FFFF}" +// ---- +type LexTerminalChar[P, R any] struct { + Arg goohm.Node +} + +// escapeChar - an escape sequence +// -- rule -- +// escapeChar (an escape sequence) +// = "\\\\" -- backslash +// | "\\\"" -- doubleQuote +// | "\\\'" -- singleQuote +// | "\\b" -- backspace +// | "\\n" -- lineFeed +// | "\\r" -- carriageReturn +// | "\\t" -- tab +// | "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" -- unicodeCodePoint +// | "\\u" hexDigit hexDigit hexDigit hexDigit -- unicodeEscape +// | "\\x" hexDigit hexDigit -- hexEscape +// +// ---- +type LexEscapeChar[P, R any] struct { + Node goohm.Node +} + +// escapeChar_backslash +// -- rule -- +// "\\\\" +// ---- +type LexEscapeCharBackslash[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_doubleQuote +// -- rule -- +// "\\\"" +// ---- +type LexEscapeCharDoubleQuote[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_singleQuote +// -- rule -- +// "\\\'" +// ---- +type LexEscapeCharSingleQuote[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_backspace +// -- rule -- +// "\\b" +// ---- +type LexEscapeCharBackspace[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_lineFeed +// -- rule -- +// "\\n" +// ---- +type LexEscapeCharLineFeed[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_carriageReturn +// -- rule -- +// "\\r" +// ---- +type LexEscapeCharCarriageReturn[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_tab +// -- rule -- +// "\\t" +// ---- +type LexEscapeCharTab[P, R any] struct { + Term goohm.TerminalNode +} + +// escapeChar_unicodeCodePoint +// -- rule -- +// "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" +// ---- +type LexEscapeCharUnicodeCodePoint[P, R any] struct { + Term1 goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.OptNode + HexDigit3 goohm.OptNode + HexDigit4 goohm.OptNode + HexDigit5 goohm.OptNode + HexDigit6 goohm.OptNode + Term2 goohm.TerminalNode +} + +// escapeChar_unicodeEscape +// -- rule -- +// "\\u" hexDigit hexDigit hexDigit hexDigit +// ---- +type LexEscapeCharUnicodeEscape[P, R any] struct { + Term goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.RuleNode + HexDigit3 goohm.RuleNode + HexDigit4 goohm.RuleNode +} + +// escapeChar_hexEscape +// -- rule -- +// "\\x" hexDigit hexDigit +// ---- +type LexEscapeCharHexEscape[P, R any] struct { + Term goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.RuleNode +} + +// space +// -- rule -- +// space +// += comment +// ---- +type LexSpace[P, R any] struct { + Comment goohm.RuleNode +} + +// comment +// -- rule -- +// comment +// = "//" (~"\n" any)* &("\n" | end) -- singleLine +// | "/*" (~"*/" any)* "*/" -- multiLine +// +// ---- +type LexComment[P, R any] struct { + Node goohm.Node +} + +// comment_singleLine +// -- rule -- +// "//" (~"\n" any)* &("\n" | end) +// ---- +type LexCommentSingleLine[P, R any] struct { + Term goohm.TerminalNode + Alt goohm.ListNode +} + +// comment_multiLine +// -- rule -- +// "/*" (~"*/" any)* "*/" +// ---- +type LexCommentMultiLine[P, R any] struct { + Term1 goohm.TerminalNode + Alt goohm.ListNode + Term2 goohm.TerminalNode +} + +// tokens +// -- rule -- +// tokens = token* +// ---- +type LexTokens[P, R any] struct { + Token goohm.ListNode +} + +// token +// -- rule -- +// token = caseName | comment | ident | operator | punctuation | terminal | any +// ---- +type LexToken[P, R any] struct { + Arg1 goohm.Node +} + +// operator +// -- rule -- +// operator = "<:" | "=" | ":=" | "+=" | "*" | "+" | "?" | "~" | "&" +// ---- +type LexOperator[P, R any] struct { + Term goohm.TerminalNode +} + +// punctuation +// -- rule -- +// punctuation = "<" | ">" | "," | "--" +// ---- +type LexPunctuation[P, R any] struct { + Term goohm.TerminalNode +} diff --git a/golang/cli/ruleast.adl b/golang/cli/ruleast.adl new file mode 100644 index 00000000..e90c5647 --- /dev/null +++ b/golang/cli/ruleast.adl @@ -0,0 +1,127 @@ +module ruleast { + +struct GrammarsNode { + Vector gmr_names; + StringMap grammars; +}; + +struct GrammarNode { + String name; + Vector rule_names; + StringMap rules; +}; + +union RuleNode { + BareRuleNode bare_rule; + VirtRuleNode virt_rule; + CasesRuleNode case_rule; +}; + +struct BareRuleNode { + String name; + RuleType rtype; + String descr; + String source; + Vector args; +}; + +newtype VirtRuleNode = Named; + +struct CasesRuleNode { + String name; + RuleType rtype; + String descr; + String source; + // unification of BareNode.args + Vector args; + Vector cases; +}; + +// struct UnionRuleDetailNode { +// Vector details; +// Vector cases; +// } + +union RuleType { + Void define; + Void override; + Void extend; +}; + +// used internally as intermediate value +// returned by TopLevelTerm Accept +union RuleDetailNode { + InlineNode inline; + BareNode bare; +}; + +struct Named { + String name; + N node; +}; + +struct InlineNode { + String case_name; + String source; + Vector args; +}; + +struct BareNode { + Vector args; +}; + +// union NodeType { +// Void nobj; +// Void nont; +// Void term; +// Void list; +// Void opt; +// }; + +newtype NamedArgNode = Named; + +union ArgNode { + NObjNode nobj; + NontNode rule; + TermNode term; + ListNode list; + OptNode opt; + BuiltinHOR bhor; +}; + +// Super type of all CST Node types +struct NObjNode { + // // todo not sure name make sense here + // String name; + // // todo not sure rule make sense here + // String rule; +}; + +struct NontNode { + // String name; + String rule; +}; + +struct ListNode { + // String name; + ArgNode elem; +}; + +struct OptNode { + // String name; + ArgNode elem; +}; + +struct BuiltinHOR { + // String name; + String list_type; + // even though 'Params = "<" ListOf ">"' (and 'Seq = Iter*') formal params 'expressions must have arity 1' + NamedArgNode elem; + NamedArgNode sep; +}; + +struct TermNode { + // String name; +}; + +}; \ No newline at end of file diff --git a/golang/cli/ruleast/build_rule_ast.go b/golang/cli/ruleast/build_rule_ast.go new file mode 100644 index 00000000..04fa4478 --- /dev/null +++ b/golang/cli/ruleast/build_rule_ast.go @@ -0,0 +1,572 @@ +package ruleast + +import ( + "fmt" + "slices" + "strings" + + "github.com/ohmjs/goohm" + "github.com/samber/lo" +) + +func AssertName(this goohm.Node, name string) { + if this.CtorName() != name { + panic(fmt.Errorf(`name didn't name. +expected '%s' +received '%s' +`, name, this.CtorName())) + } +} + +func NewBuildGrammars(root goohm.Node) *Grammars { + return &Grammars{ + Grammar: root.Children()[0].(goohm.ListNode), + } +} + +func (node *Grammars) BuildRuleAst(this goohm.Node) (*GrammarsNode, error) { + AssertName(this, "Grammars") + gmrs := map[string]GrammarNode{} + gmr_names := []string{} + for _, n := range node.Grammar.Children() { + kids := n.Children() + result, err := (&Grammar{ + Ident: kids[0].(goohm.RuleNode), + SuperGrammar: kids[1].(goohm.OptNode), + Term1: kids[2].(goohm.TerminalNode), + Rule: kids[3].(goohm.ListNode), + Term2: kids[4].(goohm.TerminalNode), + }).BuildRuleAst(n) + if err != nil { + return nil, err + } + gmr_names = append(gmr_names, result.Name) + gmrs[result.Name] = *result + } + return new(Make_GrammarsNode(gmr_names, gmrs)), nil +} + +func (node *Grammar) BuildRuleAst(this goohm.Node) (*GrammarNode, error) { + AssertName(this, "Grammar") + rules := []string{} + rmap := map[string]RuleNode{} + for _, n := range node.Rule.Children() { + rns, err := (&Rule{ + Node: n.(goohm.RuleNode), + }).BuildRuleAst(n) + if err != nil { + return nil, err + } + for _, rn := range rns { + name := rn.GetBranch().RuleName() + rules = append(rules, name) + rmap[name] = rn + } + } + return new(Make_GrammarNode( + node.Ident.SourceString(), + rules, + rmap, + )), nil +} + +func (node *Rule) BuildRuleAst(this goohm.Node) (result []RuleNode, err error) { + AssertName(this, "Rule") + switch node.Node.CtorName() { + case "Rule": + return (&Rule{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "Rule_define": + kids := node.Node.Children() + return (&RuleDefine{ + Ident: kids[0].(goohm.RuleNode), + Formals: kids[1].(goohm.OptNode), + RuleDescr: kids[2].(goohm.OptNode), + Term: kids[3].(goohm.TerminalNode), + RuleBody: kids[4].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + case "Rule_override": + panic("not implemented") + case "Rule_extend": + kids := node.Node.Children() + return (&RuleExtend{ + Ident: kids[0].(goohm.RuleNode), + Formals: kids[1].(goohm.OptNode), + Term: kids[2].(goohm.TerminalNode), + RuleBody: kids[3].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +func (node *RuleDefine) BuildRuleAst(this goohm.Node) ([]RuleNode, error) { + AssertName(this, "Rule_define") + descr := "" + if len(node.RuleDescr.Children()) > 0 { + descr = (&LexRuleDescr{ + RuleDescrText: node.RuleDescr.Children()[0].Children()[1].(goohm.RuleNode), + }).BuildRuleAst(node.RuleDescr.Children()[0]) + } + return BuildRuleAstRule( + node.RuleBody, + Make_RuleType_define(), + node.Ident.SourceString(), + this.SourceString(), + descr, + ) +} + +func (node *LexRuleDescr) BuildRuleAst(this goohm.Node) string { + AssertName(this, "ruleDescr") + return node.RuleDescrText.SourceString() +} + +func (node *RuleExtend) BuildRuleAst(this goohm.Node) ([]RuleNode, error) { + AssertName(this, "Rule_extend") + return BuildRuleAstRule( + node.RuleBody, + Make_RuleType_extend(), + node.Ident.SourceString(), + this.SourceString(), + "", + ) +} + +func BuildRuleAstRule( + ruleBody goohm.RuleNode, + rule_type RuleType, + name string, + sourceString string, + descr string, +) ([]RuleNode, error) { + rb := ruleBody.Children() + details, err := (&RuleBody{ + Term: rb[0].(goohm.OptNode), + NonemptyListOf: rb[1].(goohm.BHorNode), + }).BuildRuleAst(ruleBody) + if err != nil { + return nil, err + } + cases := lo.FlatMap[RuleDetailNode, InlineNode](details, func(item RuleDetailNode, index int) []InlineNode { + if b, ok := item.Cast_inline(); ok { + return []InlineNode{ + Make_InlineNode( + b.Case_name, + b.Source, + UnifyBranches2Args( + []BareNode{ + Make_BareNode(b.Args), + }, + len(b.Args), + ), + ), + } + } + return []InlineNode{} + }) + size := 0 + bare := lo.FlatMap[RuleDetailNode, BareNode](details, func(item RuleDetailNode, index int) []BareNode { + if b, ok := item.Cast_bare(); ok { + if size == 0 { + size = len(b.Args) + } else if size != len(b.Args) { + args := lo.Map[NamedArgNode, string](b.Args, func(item NamedArgNode, i int) string { + return fmt.Sprintf("%d %s %v", i, item.Name, item.Node) + }) + panic(fmt.Errorf("all branches must have the same number of args size %d curr %d. \n\t%s", + size, + len(b.Args), + strings.Join(args, "\n\t"), + )) + } + return []BareNode{b} + } + return []BareNode{} + }) + args := UnifyBranches2Args(bare, size) + // cases_args := lo.Map[InlineNode, InlineNode](cases, func(item InlineNode, index int) InlineNode { + // return Make_InlineNode( + // item.Case_name, + // unifyBranches2Args(bare, size), + // ) + // }) + if len(cases) > 0 { + result := []RuleNode{Make_RuleNode_case_rule( + Make_CasesRuleNode( + name, + Make_RuleType_define(), + descr, + sourceString, + args, + cases, + ), + )} + for _, c := range cases { + virt_rule := Make_RuleNode_virt_rule( + VirtRuleNode( + Make_Named( + name, + Make_BareRuleNode( + c.Case_name, + Make_RuleType_define(), + "", + c.Source, + c.Args, + ), + ), + ), + ) + result = append(result, virt_rule) + } + return result, nil + } + return []RuleNode{Make_RuleNode_bare_rule( + Make_BareRuleNode( + name, + rule_type, + descr, + sourceString, + args, + ), + )}, nil +} + +func (node *RuleBody) BuildRuleAst(this goohm.Node) (results []RuleDetailNode, err error) { + AssertName(this, "RuleBody") + for _, el := range node.NonemptyListOf.Elems() { + rdn, err := (&TopLevelTerm{ + Node: el.(goohm.RuleNode), + }).BuildRuleAst(el) + if err != nil { + return nil, err + } + results = append(results, *rdn) + } + return results, nil +} + +func (node *TopLevelTerm) BuildRuleAst(this goohm.Node) (*RuleDetailNode, error) { + AssertName(this, "TopLevelTerm") + switch node.Node.CtorName() { + case "TopLevelTerm": + return (&TopLevelTerm{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "TopLevelTerm_inline": + kids := node.Node.Children() + inlineNode, err := (&TopLevelTermInline{ + Seq: kids[0].(goohm.RuleNode), + CaseName: kids[1].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + if err != nil { + return nil, err + } + return new(Make_RuleDetailNode_inline(*inlineNode)), nil + // Make_RuleDetailNode() + case "Seq": + kids := node.Node.Children() + bnode, err := (&Seq{ + Iter: kids[0].(goohm.ListNode), + }).BuildRuleAst(node.Node) + if err != nil { + return nil, err + } + return new(Make_RuleDetailNode_bare(*bnode)), nil + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +func (node *TopLevelTermInline) BuildRuleAst(this goohm.Node) (*InlineNode, error) { + AssertName(this, "TopLevelTerm_inline") + name := node.CaseName.Children()[2].SourceString() + bnode, err := (&Seq{ + Iter: node.Seq.Children()[0].(goohm.ListNode), + }).BuildRuleAst(node.Seq) + if err != nil { + return nil, err + } + src := node.Seq.SourceString() + return new(Make_InlineNode(name, src, bnode.Args)), nil +} + +func (node *Seq) BuildRuleAst(this goohm.Node) (*BareNode, error) { + AssertName(this, "Seq") + args := []NamedArgNode{} + for _, n := range node.Iter.Children() { + arg, err := (&Iter{ + Node: n.(goohm.RuleNode), + }).BuildRuleAst(n) + if err != nil { + return nil, err + } + if arg == nil { + continue + } + args = append(args, *arg) + } + return new(Make_BareNode(args)), nil +} + +func (node *Iter) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Iter") + switch node.Node.CtorName() { + case "Iter": + return (&Iter{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "Iter_star": + return (&IterStar{ + Pred: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + case "Iter_plus": + return (&IterPlus{ + Pred: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + case "Iter_opt": + return (&IterOpt{ + Pred: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + case "Pred": + return (&Pred{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +func (node *IterStar) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Iter_star") + arg, err := (&Pred{ + Node: node.Pred.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Pred) + if arg == nil || err != nil { + return nil, err + } + return new( + NamedArgNode( + Make_Named( + arg.Name, + Make_ArgNode_list( + Make_ListNode( + arg.Node, + ), + ), + ), + ), + ), nil +} + +func (node *IterPlus) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Iter_plus") + arg, err := (&Pred{ + Node: node.Pred.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Pred) + if arg == nil || err != nil { + return nil, err + } + return new(NamedArgNode(Make_Named( + arg.Name, + Make_ArgNode_list( + Make_ListNode( + arg.Node, + ), + ), + ))), nil +} + +func (node *IterOpt) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Iter_opt") + arg, err := (&Pred{ + Node: node.Pred.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Pred) + if arg == nil || err != nil { + return nil, err + } + return new(NamedArgNode(Make_Named( + arg.Name, + Make_ArgNode_opt( + Make_OptNode( + arg.Node, + ), + ), + ))), nil +} + +func (node *Pred) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Pred") + switch node.Node.CtorName() { + case "Pred": + return (&Pred{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "Pred_not": + // none thing consumed + return nil, nil + case "Pred_lookahead": + // none thing consumed + return nil, nil + case "Lex": + return (&Lex{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +func (node *Lex) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Lex") + switch node.Node.CtorName() { + case "Lex": + return (&Lex{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "Lex_lex": + return (&LexLex{ + Term: node.Node.Children()[0].(goohm.TerminalNode), + Base: node.Node.Children()[1].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + case "Base": + return (&Base{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node) + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +func (node *LexLex) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + return (&Base{ + Node: node.Base, + }).BuildRuleAst(node.Base) +} + +func (node *Base) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Base") + switch node.Node.CtorName() { + case "Base": + return (&Base{ + Node: node.Node.Children()[0].(goohm.RuleNode), + }).BuildRuleAst(this) + case "Base_application": + kids := node.Node.Children() + return (&BaseApplication{ + Ident: kids[0].(goohm.RuleNode), + Params: kids[1].(goohm.OptNode), + }).BuildRuleAst(node.Node) + case "Base_range": + kids := node.Node.Children() + return new((&BaseRange{ + OneCharTerminal1: kids[0].(goohm.RuleNode), + Term: kids[1].(goohm.TerminalNode), + OneCharTerminal2: kids[2].(goohm.RuleNode), + }).BuildRuleAst(node.Node)), nil + case "Base_terminal": + kids := node.Node.Children() + return new((&BaseTerminal{ + Terminal: kids[0].(goohm.RuleNode), + }).BuildRuleAst(node.Node)), nil + case "Base_paren": + kids := node.Node.Children() + return new((&BaseParen{ + Term1: kids[0].(goohm.TerminalNode), + Alt: kids[1].(goohm.RuleNode), + Term2: kids[2].(goohm.TerminalNode), + }).BuildRuleAst(node.Node)), nil + default: + panic("unexpected " + node.Node.CtorName()) + } +} + +var builtInHOR = []string{ + "ListOf", "listOf", "NonemptyListOf", "nonemptyListOf", "EmptyListOf", "emptyListOf", +} + +func (node *BaseApplication) BuildRuleAst(this goohm.Node) (*NamedArgNode, error) { + AssertName(this, "Base_application") + if len(node.Params.Children()) > 0 { + hor_name := node.Ident.SourceString() + if slices.Contains(builtInHOR, hor_name) { + params := node.Params.Children()[0] + listof := params.Children()[1] + nel := listof.Children()[0] + seq := nel.Children()[0] + elem, err := (&Seq{ + Iter: seq.Children()[0].(goohm.ListNode), + }).BuildRuleAst(seq) + if err != nil { + return nil, err + } + // + list2 := nel.Children()[1] + seq2 := list2.Children()[1] + sep, err := (&Seq{ + Iter: seq2.Children()[0].(goohm.ListNode), + }).BuildRuleAst(seq2) + if err != nil { + return nil, err + } + if len(elem.Args) != 1 || len(sep.Args) != 1 { + return nil, fmt.Errorf("expected exactly one argument for elem and sep in builtin hor. got %d and %d", len(elem.Args), len(sep.Args)) + } + return new(NamedArgNode(Make_Named( + hor_name, + Make_ArgNode_bhor( + Make_BuiltinHOR( + hor_name, + elem.Args[0], + sep.Args[0], + ), + ), + ))), nil + } + return new(NamedArgNode(Make_Named( + node.Ident.SourceString(), + Make_ArgNode_nobj( + Make_NObjNode(), + ), + ))), nil + } + return new(NamedArgNode(Make_Named( + node.Ident.SourceString(), + Make_ArgNode_rule( + Make_NontNode( + node.Ident.SourceString(), + ), + ), + ))), nil +} + +func (node *BaseRange) BuildRuleAst(this goohm.Node) NamedArgNode { + AssertName(this, "Base_range") + return NamedArgNode(Make_Named( + "rng", + Make_ArgNode_term( + Make_TermNode(), + ), + )) +} + +func (node *BaseTerminal) BuildRuleAst(this goohm.Node) NamedArgNode { + AssertName(this, "Base_terminal") + return NamedArgNode(Make_Named( + "term", + Make_ArgNode_term( + Make_TermNode(), + ), + )) +} + +func (node *BaseParen) BuildRuleAst(this goohm.Node) NamedArgNode { + AssertName(this, "Base_paren") + return NamedArgNode(Make_Named( + "alt", + Make_ArgNode_nobj( + Make_NObjNode(), + ), + )) +} diff --git a/golang/cli/ruleast/build_rule_ast_exec.go b/golang/cli/ruleast/build_rule_ast_exec.go new file mode 100644 index 00000000..0cf27438 --- /dev/null +++ b/golang/cli/ruleast/build_rule_ast_exec.go @@ -0,0 +1,165 @@ +package ruleast + +import ( + "context" + _ "embed" + "fmt" + "os" + "runtime" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" +) + +type RuleAstCmd struct { + SkipSource bool `opts:"short=s"` + SuffixOutfLineNos bool `opts:"short=l"` + Grammar string `opts:"mode=arg" help:"Path to .ohm grammar file to generate a visitor for."` + + sbldr *strings.Builder +} + +func NewRuleAstCmd() *RuleAstCmd { + return &RuleAstCmd{ + sbldr: &strings.Builder{}, + } +} + +func (vc *RuleAstCmd) outf(format string, a ...any) { + _, file, line, _ := runtime.Caller(1) // for line numbers to be correct when SuffixOutfLineNos is true + parts := strings.Split(file, "/") + parts = parts[len(parts)-2:] + file = strings.Join(parts, "/") + callerLine := fmt.Sprintf("%s:%d", file, line) + f0 := format + if vc.SuffixOutfLineNos { + f0 = strings.ReplaceAll(format, "\n", fmt.Sprintf(" // %%[%d]s\n", len(a)+1)) + a = append(a, callerLine) + } + fmt.Fprintf(vc.sbldr, f0, a...) +} + +func (vc *RuleAstCmd) Run() error { + if vc.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %v", err) + } + vc.Grammar = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + fmt.Printf("%s\n", out) + return nil +} + +func (vc *RuleAstCmd) Process() (string, error) { + vc.sbldr = &strings.Builder{} + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return "", fmt.Errorf("creating grammar: %v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.Grammar); err != nil { + return "", fmt.Errorf("matching: %v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %v", err) + } + gAst, err := NewBuildGrammars(root).BuildRuleAst(root) + if err != nil { + return "", err + } + for _, k := range gAst.Gmr_names { + v := gAst.Grammars[k] + vc.outf("%[1]s\n", k) + for _, name := range v.Rule_names { + rule0 := v.Rules[name] + branch := rule0.GetBranch() + descr := branch.Descr("(", ") ") + Handle_RuleNode[any]( + rule0, + func(rule BareRuleNode) any { + if !vc.SkipSource { + vc.outf("```\n%[1]s\n```\n", rule._BareRuleNode.Source) + } + vc.outf("%[1]s @bare %[2]s{\n", rule.RuleName(), descr) + for _, a := range rule.Args { + vc.outf(" %[1]s %+[2]v\n", strings.ToLower(a.Name[:1])+a.Name[1:], argNodeStr(a.Node)) + } + vc.outf("}\n") + return nil + }, + func(rule VirtRuleNode) any { + if !vc.SkipSource { + vc.outf("```\n%s\n```\n", rule.Node._BareRuleNode.Source) + } + vc.outf("%[1]s @virt %[2]s %[3]s{\n", rule._Named.Name, rule.Node._BareRuleNode.Name, descr) + for _, a := range rule.Node.Args { + vc.outf(" %[1]s %+[2]v\n", strings.ToLower(a.Name[:1])+a.Name[1:], argNodeStr(a.Node)) + } + vc.outf("}\n") + return nil + }, + func(rule CasesRuleNode) any { + if !vc.SkipSource { + vc.outf("```\n%[1]s\n```\n", rule._CasesRuleNode.Source) + } + vc.outf("%[1]s @cases %[2]s{\n", rule.RuleName(), descr) + for _, c := range rule.Cases { + vc.outf(" %[1]s @inline\n", c.Case_name) + } + for _, a := range rule.Args { + vc.outf(" %[1]s %+[2]v\n", strings.ToLower(a.Name[:1])+a.Name[1:], argNodeStr(a.Node)) + } + vc.outf("}\n") + return nil + }, + nil, + ) + } + } + return vc.sbldr.String(), nil +} + +func argNodeStr(arg ArgNode) string { + return Handle_ArgNode[string]( + arg, + func(nobj NObjNode) string { + return "@node" + }, + func(rule NontNode) string { + return "@rule " + rule.Rule + }, + func(term TermNode) string { + return "@term" + }, + func(list ListNode) string { + return "@list " + argNodeStr(list.Elem) + }, + func(opt OptNode) string { + return "@opt " + argNodeStr(opt.Elem) + }, + func(bhor BuiltinHOR) string { + return fmt.Sprintf("@hor %s<%s, %s>", + bhor.List_type, + argNodeStr(bhor.Elem.Node), + argNodeStr(bhor.Sep.Node), + ) + }, + nil, + ) +} diff --git a/golang/cli/ruleast/build_rule_ast_types.go b/golang/cli/ruleast/build_rule_ast_types.go new file mode 100644 index 00000000..4fd7a04e --- /dev/null +++ b/golang/cli/ruleast/build_rule_ast_types.go @@ -0,0 +1,611 @@ +// Code generated by ohmgo generate types - DO NOT EDIT. +package ruleast + +import ( + "github.com/ohmjs/goohm" +) + +// types for grammar Ohm + +// Grammars +// -- rule -- +// Grammars +// = Grammar* +// ---- +type Grammars struct { + Grammar goohm.ListNode +} + +// Grammar +// -- rule -- +// Grammar +// = ident SuperGrammar? "{" Rule* "}" +// ---- +type Grammar struct { + Ident goohm.RuleNode + SuperGrammar goohm.OptNode + Term1 goohm.TerminalNode + Rule goohm.ListNode + Term2 goohm.TerminalNode +} + +// SuperGrammar +// -- rule -- +// SuperGrammar +// = "<:" ident +// ---- +type SuperGrammar struct { + Term goohm.TerminalNode + Ident goohm.RuleNode +} + +// Rule +// -- rule -- +// Rule +// = ident Formals? ruleDescr? "=" RuleBody -- define +// | ident Formals? ":=" OverrideRuleBody -- override +// | ident Formals? "+=" RuleBody -- extend +// +// ---- +type Rule struct { + Node goohm.Node +} + +// Rule_define +// -- rule -- +// ident Formals? ruleDescr? "=" RuleBody +// ---- +type RuleDefine struct { + Ident goohm.RuleNode + Formals goohm.OptNode + RuleDescr goohm.OptNode + Term goohm.TerminalNode + RuleBody goohm.RuleNode +} + +// Rule_override +// -- rule -- +// ident Formals? ":=" OverrideRuleBody +// ---- +type RuleOverride struct { + Ident goohm.RuleNode + Formals goohm.OptNode + Term goohm.TerminalNode + OverrideRuleBody goohm.RuleNode +} + +// Rule_extend +// -- rule -- +// ident Formals? "+=" RuleBody +// ---- +type RuleExtend struct { + Ident goohm.RuleNode + Formals goohm.OptNode + Term goohm.TerminalNode + RuleBody goohm.RuleNode +} + +// RuleBody +// -- rule -- +// RuleBody +// = "|"? NonemptyListOf +// ---- +type RuleBody struct { + Term goohm.OptNode + NonemptyListOf goohm.BHorNode +} + +// TopLevelTerm +// -- rule -- +// TopLevelTerm +// = Seq caseName -- inline +// | Seq +// ---- +type TopLevelTerm struct { + Node goohm.Node +} + +// TopLevelTerm_inline +// -- rule -- +// Seq caseName +// ---- +type TopLevelTermInline struct { + Seq goohm.RuleNode + CaseName goohm.RuleNode +} + +// OverrideRuleBody +// -- rule -- +// OverrideRuleBody +// = "|"? NonemptyListOf +// ---- +type OverrideRuleBody struct { + Term goohm.OptNode + NonemptyListOf goohm.BHorNode +} + +// OverrideTopLevelTerm +// -- rule -- +// OverrideTopLevelTerm +// = "..." -- superSplice +// | TopLevelTerm +// ---- +type OverrideTopLevelTerm struct { + Node goohm.Node +} + +// OverrideTopLevelTerm_superSplice +// -- rule -- +// "..." +// ---- +type OverrideTopLevelTermSuperSplice struct { + Term goohm.TerminalNode +} + +// Formals +// -- rule -- +// Formals +// = "<" ListOf ">" +// ---- +type Formals struct { + Term1 goohm.TerminalNode + ListOf goohm.BHorNode + Term2 goohm.TerminalNode +} + +// Params +// -- rule -- +// Params +// = "<" ListOf ">" +// ---- +type Params struct { + Term1 goohm.TerminalNode + ListOf goohm.BHorNode + Term2 goohm.TerminalNode +} + +// Alt +// -- rule -- +// Alt +// = NonemptyListOf +// ---- +type Alt struct { + NonemptyListOf goohm.BHorNode +} + +// Seq +// -- rule -- +// Seq +// = Iter* +// ---- +type Seq struct { + Iter goohm.ListNode +} + +// Iter +// -- rule -- +// Iter +// = Pred "*" -- star +// | Pred "+" -- plus +// | Pred "?" -- opt +// | Pred +// ---- +type Iter struct { + Node goohm.Node +} + +// Iter_star +// -- rule -- +// Pred "*" +// ---- +type IterStar struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Iter_plus +// -- rule -- +// Pred "+" +// ---- +type IterPlus struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Iter_opt +// -- rule -- +// Pred "?" +// ---- +type IterOpt struct { + Pred goohm.RuleNode + Term goohm.TerminalNode +} + +// Pred +// -- rule -- +// Pred +// = "~" Lex -- not +// | "&" Lex -- lookahead +// | Lex +// ---- +type Pred struct { + Node goohm.Node +} + +// Pred_not +// -- rule -- +// "~" Lex +// ---- +type PredNot struct { + Term goohm.TerminalNode + Lex goohm.RuleNode +} + +// Pred_lookahead +// -- rule -- +// "&" Lex +// ---- +type PredLookahead struct { + Term goohm.TerminalNode + Lex goohm.RuleNode +} + +// Lex +// -- rule -- +// Lex +// = "#" Base -- lex +// | Base +// ---- +type Lex struct { + Node goohm.Node +} + +// Lex_lex +// -- rule -- +// "#" Base +// ---- +type LexLex struct { + Term goohm.TerminalNode + Base goohm.RuleNode +} + +// Base +// -- rule -- +// Base +// = ident Params? ~(ruleDescr? "=" | ":=" | "+=") -- application +// | oneCharTerminal ".." oneCharTerminal -- range +// | terminal -- terminal +// | "(" Alt ")" -- paren +// +// ---- +type Base struct { + Node goohm.Node +} + +// Base_application +// -- rule -- +// ident Params? ~(ruleDescr? "=" | ":=" | "+=") +// ---- +type BaseApplication struct { + Ident goohm.RuleNode + Params goohm.OptNode +} + +// Base_range +// -- rule -- +// oneCharTerminal ".." oneCharTerminal +// ---- +type BaseRange struct { + OneCharTerminal1 goohm.RuleNode + Term goohm.TerminalNode + OneCharTerminal2 goohm.RuleNode +} + +// Base_terminal +// -- rule -- +// terminal +// ---- +type BaseTerminal struct { + Terminal goohm.RuleNode +} + +// Base_paren +// -- rule -- +// "(" Alt ")" +// ---- +type BaseParen struct { + Term1 goohm.TerminalNode + Alt goohm.RuleNode + Term2 goohm.TerminalNode +} + +// ruleDescr - a rule description +// -- rule -- +// ruleDescr (a rule description) +// = "(" ruleDescrText ")" +// ---- +type LexRuleDescr struct { + Term1 goohm.TerminalNode + RuleDescrText goohm.RuleNode + Term2 goohm.TerminalNode +} + +// ruleDescrText +// -- rule -- +// ruleDescrText +// = (~")" any)* +// ---- +type LexRuleDescrText struct { + Alt goohm.ListNode +} + +// caseName +// -- rule -- +// caseName +// = "--" (~"\n" space)* name (~"\n" space)* ("\n" | &"}") +// ---- +type LexCaseName struct { + Term goohm.TerminalNode + Alt1 goohm.ListNode + Name goohm.RuleNode + Alt2 goohm.ListNode + Alt3 goohm.Node +} + +// name - a name +// -- rule -- +// name (a name) +// = nameFirst nameRest* +// ---- +type LexName struct { + NameFirst goohm.RuleNode + NameRest goohm.ListNode +} + +// nameFirst +// -- rule -- +// nameFirst +// = "_" +// | letter +// ---- +type LexNameFirst struct { + Arg goohm.Node +} + +// nameRest +// -- rule -- +// nameRest +// = "_" +// | alnum +// ---- +type LexNameRest struct { + Arg goohm.Node +} + +// ident - an identifier +// -- rule -- +// ident (an identifier) +// = name +// ---- +type LexIdent struct { + Name goohm.RuleNode +} + +// terminal +// -- rule -- +// terminal +// = "\"" terminalChar* "\"" +// ---- +type LexTerminal struct { + Term1 goohm.TerminalNode + TerminalChar goohm.ListNode + Term2 goohm.TerminalNode +} + +// oneCharTerminal +// -- rule -- +// oneCharTerminal +// = "\"" terminalChar "\"" +// ---- +type LexOneCharTerminal struct { + Term1 goohm.TerminalNode + TerminalChar goohm.RuleNode + Term2 goohm.TerminalNode +} + +// terminalChar +// -- rule -- +// terminalChar +// = escapeChar +// | ~"\\" ~"\"" ~"\n" "\u{0}".."\u{10FFFF}" +// ---- +type LexTerminalChar struct { + Arg goohm.Node +} + +// escapeChar - an escape sequence +// -- rule -- +// escapeChar (an escape sequence) +// = "\\\\" -- backslash +// | "\\\"" -- doubleQuote +// | "\\\'" -- singleQuote +// | "\\b" -- backspace +// | "\\n" -- lineFeed +// | "\\r" -- carriageReturn +// | "\\t" -- tab +// | "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" -- unicodeCodePoint +// | "\\u" hexDigit hexDigit hexDigit hexDigit -- unicodeEscape +// | "\\x" hexDigit hexDigit -- hexEscape +// +// ---- +type LexEscapeChar struct { + Node goohm.Node +} + +// escapeChar_backslash +// -- rule -- +// "\\\\" +// ---- +type LexEscapeCharBackslash struct { + Term goohm.TerminalNode +} + +// escapeChar_doubleQuote +// -- rule -- +// "\\\"" +// ---- +type LexEscapeCharDoubleQuote struct { + Term goohm.TerminalNode +} + +// escapeChar_singleQuote +// -- rule -- +// "\\\'" +// ---- +type LexEscapeCharSingleQuote struct { + Term goohm.TerminalNode +} + +// escapeChar_backspace +// -- rule -- +// "\\b" +// ---- +type LexEscapeCharBackspace struct { + Term goohm.TerminalNode +} + +// escapeChar_lineFeed +// -- rule -- +// "\\n" +// ---- +type LexEscapeCharLineFeed struct { + Term goohm.TerminalNode +} + +// escapeChar_carriageReturn +// -- rule -- +// "\\r" +// ---- +type LexEscapeCharCarriageReturn struct { + Term goohm.TerminalNode +} + +// escapeChar_tab +// -- rule -- +// "\\t" +// ---- +type LexEscapeCharTab struct { + Term goohm.TerminalNode +} + +// escapeChar_unicodeCodePoint +// -- rule -- +// "\\u{" hexDigit hexDigit? hexDigit? +// hexDigit? hexDigit? hexDigit? "}" +// ---- +type LexEscapeCharUnicodeCodePoint struct { + Term1 goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.OptNode + HexDigit3 goohm.OptNode + HexDigit4 goohm.OptNode + HexDigit5 goohm.OptNode + HexDigit6 goohm.OptNode + Term2 goohm.TerminalNode +} + +// escapeChar_unicodeEscape +// -- rule -- +// "\\u" hexDigit hexDigit hexDigit hexDigit +// ---- +type LexEscapeCharUnicodeEscape struct { + Term goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.RuleNode + HexDigit3 goohm.RuleNode + HexDigit4 goohm.RuleNode +} + +// escapeChar_hexEscape +// -- rule -- +// "\\x" hexDigit hexDigit +// ---- +type LexEscapeCharHexEscape struct { + Term goohm.TerminalNode + HexDigit1 goohm.RuleNode + HexDigit2 goohm.RuleNode +} + +// space +// -- rule -- +// space +// += comment +// ---- +type LexSpace struct { + Comment goohm.RuleNode +} + +// comment +// -- rule -- +// comment +// = "//" (~"\n" any)* &("\n" | end) -- singleLine +// | "/*" (~"*/" any)* "*/" -- multiLine +// +// ---- +type LexComment struct { + Node goohm.Node +} + +// comment_singleLine +// -- rule -- +// "//" (~"\n" any)* &("\n" | end) +// ---- +type LexCommentSingleLine struct { + Term goohm.TerminalNode + Alt goohm.ListNode +} + +// comment_multiLine +// -- rule -- +// "/*" (~"*/" any)* "*/" +// ---- +type LexCommentMultiLine struct { + Term1 goohm.TerminalNode + Alt goohm.ListNode + Term2 goohm.TerminalNode +} + +// tokens +// -- rule -- +// tokens = token* +// ---- +type LexTokens struct { + Token goohm.ListNode +} + +// token +// -- rule -- +// token = caseName | comment | ident | operator | punctuation | terminal | any +// ---- +type LexToken struct { + Arg1 goohm.Node +} + +// operator +// -- rule -- +// operator = "<:" | "=" | ":=" | "+=" | "*" | "+" | "?" | "~" | "&" +// ---- +type LexOperator struct { + Term goohm.TerminalNode +} + +// punctuation +// -- rule -- +// punctuation = "<" | ">" | "," | "--" +// ---- +type LexPunctuation struct { + Term goohm.TerminalNode +} + + diff --git a/golang/cli/ruleast/gen_go.go b/golang/cli/ruleast/gen_go.go new file mode 100644 index 00000000..6f22403e --- /dev/null +++ b/golang/cli/ruleast/gen_go.go @@ -0,0 +1,123 @@ +package ruleast + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" +) + +type genGoCmd struct { + GenCmd genCmd `opts:"mode=embedded"` + OutputDir string `help:"Output directory for generated files.\nDefaults to the lowercase grammar name."` +} + +func NewGenGoCmd() *genGoCmd { + return &genGoCmd{ + GenCmd: genCmd{ + GoRuntimeImport: "github.com/ohmjs/goohm", + GoRuntimePackage: "goohm", + // sbldr: &strings.Builder{}, + // SuffixOutfLineNos: true, + }, + } +} + +func (vc *genGoCmd) Run() error { + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if vc.GenCmd.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.GenCmd.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %[1]v", err) + } + vc.GenCmd.Grammar = string(barr) + } + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return fmt.Errorf("creating grammar: %[1]v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.GenCmd.Grammar); err != nil { + return fmt.Errorf("matching: %[1]v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return fmt.Errorf("Error getting cst root. %[1]v", err) + } + gmrsAst, err := NewBuildGrammars(root).BuildRuleAst(root) + if err != nil { + return fmt.Errorf("Error building rule ast. %[1]v", err) + } + if vc.OutputDir == "" { + vc.OutputDir = strings.ToLower(gmrsAst.Gmr_names[0]) + } + if err = os.MkdirAll(vc.OutputDir, os.ModePerm); err != nil { + return fmt.Errorf("creating output directory: %[1]v", err) + } + // + types_sb := &strings.Builder{} + vc.GenCmd.sbldr = types_sb + types := &genTypesCmd{ + GenCmd: vc.GenCmd, + OutputFile: filepath.Join(vc.OutputDir, "types.go"), + } + gmrsAst.GenGoTypes(types) + // + inter_sb := &strings.Builder{} + vc.GenCmd.sbldr = inter_sb + inter := &genInterfaceCmd{ + GenCmd: vc.GenCmd, + OutputFile: filepath.Join(vc.OutputDir, "interfaces.go"), + } + gmrsAst.GenGoInterfaces(inter) + // + accepts_sb := &strings.Builder{} + vc.GenCmd.sbldr = accepts_sb + accepts := &genAcceptsCmd{ + GenCmd: vc.GenCmd, + OutputFile: filepath.Join(vc.OutputDir, "accepts.go"), + gmrsAst: *gmrsAst, + } + gmrsAst.GenGoAccepts(accepts) + // + if typesFile, err := os.Create(types.OutputFile); err != nil { + return fmt.Errorf("creating file: %[1]v", err) + } else { + defer typesFile.Close() + if _, err = typesFile.WriteString(types_sb.String()); err != nil { + return fmt.Errorf("writing file: %[1]v", err) + } + fmt.Fprintf(os.Stderr, "wrote %s\n", types.OutputFile) + } + if interFile, err := os.Create(inter.OutputFile); err != nil { + return fmt.Errorf("creating file: %[1]v", err) + } else { + defer interFile.Close() + if _, err = interFile.WriteString(inter_sb.String()); err != nil { + return fmt.Errorf("writing file: %[1]v", err) + } + fmt.Fprintf(os.Stderr, "wrote %s\n", inter.OutputFile) + } + if acceptsFile, err := os.Create(accepts.OutputFile); err != nil { + return fmt.Errorf("creating file: %[1]v", err) + } else { + defer acceptsFile.Close() + if _, err = acceptsFile.WriteString(accepts_sb.String()); err != nil { + return fmt.Errorf("writing file: %[1]v", err) + } + fmt.Fprintf(os.Stderr, "wrote %s\n", accepts.OutputFile) + } + return nil +} diff --git a/golang/cli/ruleast/gen_go_accepts.go b/golang/cli/ruleast/gen_go_accepts.go new file mode 100644 index 00000000..7e305199 --- /dev/null +++ b/golang/cli/ruleast/gen_go_accepts.go @@ -0,0 +1,667 @@ +package ruleast + +import ( + "context" + "fmt" + "os" + "runtime" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" + "github.com/samber/lo" +) + +type genAcceptsCmd struct { + GenCmd genCmd `opts:"mode=embedded"` + OutputFile string + gmrsAst GrammarsNode +} + +func (vc *genAcceptsCmd) outf(format string, a ...any) { + _, file, line, _ := runtime.Caller(1) // for line numbers to be correct when SuffixOutfLineNos is true + parts := strings.Split(file, "/") + parts = parts[len(parts)-2:] + file = strings.Join(parts, "/") + callerLine := fmt.Sprintf("%s:%d", file, line) + f0 := format + if vc.GenCmd.SuffixOutfLineNos { + f0 = strings.ReplaceAll(format, "\n", fmt.Sprintf(" // %%[%d]s\n", len(a)+1)) + a = append(a, callerLine) + } + fmt.Fprintf(vc.GenCmd.sbldr, f0, a...) +} + +func NewGenAcceptsCmd() *genAcceptsCmd { + return &genAcceptsCmd{ + GenCmd: genCmd{ + GoRuntimeImport: "github.com/ohmjs/goohm", + GoRuntimePackage: "goohm", + sbldr: &strings.Builder{}, + SuffixOutfLineNos: true, + }, + } +} + +func (vc *genAcceptsCmd) Run() error { + if vc.GenCmd.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.GenCmd.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %[1]v", err) + } + vc.GenCmd.Grammar = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + if vc.OutputFile == "-" { + fmt.Printf("%[1]s\n", out) + return nil + } + fi, err := os.Create(vc.OutputFile) + if err != nil { + return fmt.Errorf("error creating file %[1]w", err) + } + defer fi.Close() + _, err = fi.WriteString(out) + if err != nil { + return fmt.Errorf("error writing file %[1]w", err) + } + return nil +} + +func (vc *genAcceptsCmd) Process() (string, error) { + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return "", fmt.Errorf("creating grammar: %[1]v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.GenCmd.Grammar); err != nil { + return "", fmt.Errorf("matching: %[1]v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %[1]v", err) + } + gmrsAst, err := NewBuildGrammars(root).BuildRuleAst(root) + if err != nil { + return "", fmt.Errorf("Error building rule ast. %[1]v", err) + } + vc.gmrsAst = *gmrsAst + vc.gmrsAst.GenGoAccepts(vc) + return vc.GenCmd.sbldr.String(), nil +} + +func (gmrs GrammarsNode) GenGoAccepts(vc *genAcceptsCmd) { + if vc.GenCmd.GoTypePackage == "" { + vc.GenCmd.GoTypePackage = strings.ToLower(gmrs.Gmr_names[0]) + } + vc.outf(`// Code generated by ohmgo generate accepts - DO NOT EDIT. +package %[1]s + +import ( + "%[2]s" +) + +`, vc.GenCmd.GoTypePackage, vc.GenCmd.GoRuntimeImport) + for _, gname := range gmrs.Gmr_names { + vc.outf(`// accepts for grammar %[1]s + +`, gname) + gmr := gmrs.Grammars[gname] + gmr.GenGoAccepts(vc) + } +} + +func (gmr GrammarNode) GenGoAccepts(vc *genAcceptsCmd) { + vc.outf(`// TODO for grammar %[1]s, implement Make func for starting rule %[2]s + +`, + gmr.Name, + gmr.Rule_names[0], + ) + for _, rname := range gmr.Rule_names { + rule := gmr.Rules[rname] + branch := rule.GetBranch() + vc.outf(`// Accept implementation for %[1]s%[2]s +// +`, + branch.RuleName(), + branch.Descr(" - ", ""), + ) + for _, line := range branch.Source() { + line = strings.TrimSpace(line) + if line == "" { + continue + } + vc.outf(`// %[1]s +`, + line, + ) + } + vc.outf(`func (node *%[1]s[P, R]) Accept(this goohm.Node, visitor any, payload P) (result R) { + %[2]s.AssertName(this, "%[3]s") + if v, ok := visitor.(Visitor%[1]s[P, R]); ok { + return v.Visit%[1]s(node, payload) + } + goohm.CheckName[VisitorGrammars[P, R]](visitor) + return node.DefaultAccept(visitor, payload) +} + +`, + branch.TypeName(), + vc.GenCmd.GoRuntimePackage, + branch.RuleName(), + ) + branch.GenGoAccepts(vc, gmr.Name) + } +} + +func (node VirtRuleNode) GenGoAccepts(vc *genAcceptsCmd, gmr_name string) { + node0 := node.Node + node0._BareRuleNode.Name = node.TypeName() + node0.GenGoAccepts(vc, gmr_name) +} + +func (node BareRuleNode) GenGoAccepts(vc *genAcceptsCmd, gmr_name string) { + vc.outf(`func (node *%[1]s[P, R]) DefaultAccept(visitor any, payload P) (result R) { +`, + node.TypeName(), + ) + longest := lo.MaxBy(node.Args, func(a, b NamedArgNode) bool { + return len(a.Name) > len(b.Name) + }) + for _, arg := range node.Args { + padding := strings.Repeat(" ", len(longest.Name)-len(arg.Name)) + vc.outf(` result = node.Accept%[1]s(visitor, payload) +`, + r2name(arg.Name), + padding, + arg.Node.GetBranch().GoType(vc.GenCmd.GoRuntimePackage), + ) + } + vc.outf(` return +} + +`) + for _, arg := range node.Args { + vc.outf(`func (node *%[1]s[P, R]) Accept%[2]s(visitor any, payload P) (result R) { +`, + node.TypeName(), + r2name(arg.Name), + ) + arg.Node.GetBranch().GenGoLeafAccepts(vc, gmr_name, arg.Name) + vc.outf(` return +} + +`) + } +} + +func (node CasesRuleNode) GenGoAccepts(vc *genAcceptsCmd, gmr_name string) { + vc.outf(`func (node *%[1]s[P, R]) DefaultAccept(visitor any, payload P) (result R) { + switch node.Node.CtorName() { + case "%[1]s": + return (&%[1]s[P, R]{ + Node: node.Node.Children()[0].(%[2]s.RuleNode), + }).DefaultAccept(visitor, payload) +`, + node.TypeName(), + vc.GenCmd.GoRuntimePackage, + ) + gmr, ok := vc.gmrsAst.Grammars[gmr_name] + if !ok { + panic(fmt.Errorf("unknown grammar '%[1]s'", gmr_name)) + } + // inline cases + for _, case0 := range node.Cases { + virt_rule_name := node.RuleName() + "_" + case0.Case_name + virt_type_name := r2name(node.TypeName()) + upper1st(case0.Case_name) + rule, ok := gmr.Rules[virt_rule_name] + + // vc.outf( ` { + // if v, ok := visitor.(goohm.BuiltinVisitor); ok { + // v.BuiltInRule(node.%[1]s) + // } + // } + // `, + // upper1st(name), + // ) + + if !ok { + panic(fmt.Errorf("unknown rule '%[1]s'", virt_rule_name)) + } + vc.outf(` case "%[1]s": + kids := node.Node.Children() + return (&%[2]s[P, R]{ +`, + virt_rule_name, + virt_type_name, + ) + rule.GetBranch().GenGoLeafInstAccepts(vc, 3) + vc.outf(` }).Accept(node.Node, visitor, payload) +`) + } + // bare cases + if len(node.Args) > 1 { + // todo + } + for _, arg0 := range node.Args { + vc.outf(` case "%[1]s": +`, + arg0.Name, + ) + name := arg0.Name + // todo - this is not always true + n := arg0.Node.GetBranch().(NontNode) + rule, ok := gmr.Rules[n.Rule] + if !ok { + panic(fmt.Errorf("unknown rule %[1]s", name)) + } + vc.outf(` kids := node.Node.Children() + return (&%[1]s[P, R]{ +`, + r2name(name), + ) + rule.GetBranch().GenGoLeafInstAccepts(vc, 3) + vc.outf(` }).Accept(node.Node, visitor, payload) +`, + ) + } + // default + vc.outf(` default: + panic("unexpected " + node.Node.CtorName()) + } // end switch +`) + vc.outf(`} + +`) +} + +func (n NObjNode) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` // Node +`) + vc.outf(` { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.%[1]s) + } + } +`, + upper1st(name), + ) +} + +func (n NontNode) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` // Rule +`) + gmr, ok := vc.gmrsAst.Grammars[gmr_name] + if !ok { + panic(fmt.Errorf("unknown grammar %[1]s", gmr_name)) + } + rule, ok := gmr.Rules[n.Rule] + if !ok { + vc.outf(` // "unknown rule %[1]s" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(node.%[2]s) + } +`, + n.Rule, + upper1st(name), + ) + return + } + vc.outf(` kids := node.%[1]s.Children() + result = (&%[2]s[P, R]{ +`, + upper1st(name), + rule.GetBranch().TypeName(), + ) + rule.GetBranch().GenGoLeafInstAccepts(vc, 2) + // rule.GetBranch(). + vc.outf(` }).Accept(node.%[1]s, visitor, payload) +`, + upper1st(name), + ) +} + +func (n TermNode) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` // Term +`) + vc.outf(` if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(node.%[1]s) + } +`, + upper1st(name)) +} + +func (n ListNode) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` for _, n := range node.%[1]s.Children() { +`, + upper1st(name), + ) + Handle_ArgNode[any]( + n.Elem, + func(nobj NObjNode) any { + vc.outf(` { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } +`, + ) + return nil + }, + func(rulenode NontNode) any { + gmr, ok := vc.gmrsAst.Grammars[gmr_name] + if !ok { + panic(fmt.Errorf("unknown grammar %[1]s", gmr_name)) + } + rule, ok := gmr.Rules[rulenode.Rule] + if !ok { + vc.outf(` // "unknown rule %[1]s" +`, + rulenode.Rule, + ) + return nil + } + Handle_RuleNode[any]( + rule, + func(bare_rule BareRuleNode) any { + vc.outf(` kids := n.Children() + result = (&%[1]s[P, R]{ +`, + bare_rule.TypeName(), + ) + bare_rule.GenGoLeafInstAccepts(vc, 3) + vc.outf(` }).Accept(n, visitor, payload) +`, + // upper1st(name), + ) + return nil + }, + func(virt_rule VirtRuleNode) any { + panic("shouldn't get here") + }, + func(case_rule CasesRuleNode) any { + vc.outf(` result = (&%[1]s[P, R]{ + Node: n, + }).Accept(n, visitor, payload) +`, + upper1st(case_rule.Name), + ) + return nil + }, + nil, + ) + return nil + }, + func(term TermNode) any { + vc.outf(` if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n) + } +`, + ) + return nil + + }, + func(list ListNode) any { + panic("should not be possible") + }, + func(opt OptNode) any { + panic("should not be possible") + }, + func(bhor BuiltinHOR) any { + vc.outf(` panic("not implemented - why would you do this?") +`, + ) + return nil + }, + nil, + ) + vc.outf(` } +`, + ) +} + +func (n OptNode) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` // Opt +`) + vc.outf(` if len(node.%[1]s.Children()) > 0 { + n := node.%[1]s.Children()[0] +`, + upper1st(name), + ) + Handle_ArgNode[any]( + n.Elem, + func(nobj NObjNode) any { + vc.outf(` { + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + } +`, + ) + return nil + }, + func(rulenode NontNode) any { + gmr, ok := vc.gmrsAst.Grammars[gmr_name] + if !ok { + panic(fmt.Errorf("unknown grammar %[1]s", gmr_name)) + } + rule, ok := gmr.Rules[rulenode.Rule] + if !ok { + + vc.outf(` // "unknown rule %[1]s" + if v, ok := visitor.(goohm.BuiltinVisitor); ok { + v.BuiltInRule(n) + } +`, + rulenode.Rule, + ) + return nil + } + Handle_RuleNode[any]( + rule, + func(bare_rule BareRuleNode) any { + vc.outf(` kids := n.Children() + result = (&%[1]s[P, R]{ +`, + bare_rule.TypeName(), + ) + bare_rule.GenGoLeafInstAccepts(vc, 3) + vc.outf(` }).Accept(n, visitor, payload) +`, + // upper1st(name), + ) + return nil + }, + func(virt_rule VirtRuleNode) any { + panic("shouldn't get here") + }, + func(case_rule CasesRuleNode) any { + vc.outf(` result = (&%[1]s[P, R]{ + Node: n, + }).Accept(n, visitor, payload) +`, + upper1st(case_rule.Name), + ) + return nil + }, + nil, + ) + return nil + }, + func(term TermNode) any { + vc.outf(` if v, ok := visitor.(goohm.TerminalVisitor); ok { + v.Terminal(n.(%[1]s.TerminalNode)) + } +`, + vc.GenCmd.GoRuntimePackage, + ) + return nil + + }, + func(list ListNode) any { + panic("should not be possible") + }, + func(opt OptNode) any { + panic("should not be possible") + }, + func(bhor BuiltinHOR) any { + vc.outf(` panic("not implemented - why would you do this?") +`, + ) + return nil + }, + nil, + ) + vc.outf(` } +`, + ) +} + +func (n BuiltinHOR) GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) { + vc.outf(` // BuiltinHOR +`) + vc.outf(` // %[1]s +`, + n.Elem.Name, + ) + n.Elem.Node.GetBranch().GenGoBHORCallback(vc, gmr_name, "fn_elem") + n.Sep.Node.GetBranch().GenGoBHORCallback(vc, gmr_name, "fn_sep") + vc.outf(` goohm.AcceptBuiltinHOR(node.%[1]s, fn_elem, fn_sep) +`, + n.List_type, + ) +} + +func (NObjNode) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + if v, ok := visitor.(%[2]s.BuiltinVisitor); ok { + v.BuiltInRule(n) + }) + return +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) +} +func (rulenode NontNode) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + gmr, ok := vc.gmrsAst.Grammars[gmr_name] + if !ok { + panic(fmt.Errorf("unknown grammar %[1]s", gmr_name)) + } + rule, ok := gmr.Rules[rulenode.Rule] + if !ok { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + if v, ok := visitor.(%[2]s.BuiltinVisitor); ok { + v.BuiltInRule(n) + } + return + } +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) + return + } + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + kids := n.Children() + result = (&%[3]s[P, R]{ +`, + fname, + vc.GenCmd.GoRuntimePackage, + r2name(rulenode.Rule), + ) + rule.GetBranch().GenGoLeafInstAccepts(vc, 3) + vc.outf(` }).Accept(n, visitor, payload) + return + } +`, + ) +} +func (TermNode) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + if v, ok := visitor.(%[2]s.TerminalVisitor); ok { + v.Terminal(n.(%[2]s.TerminalNode)) + } + return + } +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) +} +func (n ListNode) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + panic("not implemented") + } +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) +} +func (OptNode) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + panic("not implemented") + } +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) +} +func (BuiltinHOR) GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) { + vc.outf(` %[1]s := func(n %[2]s.Node) (result R) { + panic("not implemented") + } +`, + fname, + vc.GenCmd.GoRuntimePackage, + ) +} + +func (node VirtRuleNode) GenGoLeafInstAccepts(vc *genAcceptsCmd, tabs int) { + node.Node.GenGoLeafInstAccepts(vc, tabs) +} + +func (node BareRuleNode) GenGoLeafInstAccepts(vc *genAcceptsCmd, tabs int) { + longest := lo.MaxBy(node.Args, func(a, b NamedArgNode) bool { + return len(a.Name) > len(b.Name) + }) + for i, arg := range node.Args { + padding := strings.Repeat(" ", len(longest.Name)-len(arg.Name)) + type_cast := arg.Node.GetBranch().GoType(vc.GenCmd.GoRuntimePackage) + if type_cast == vc.GenCmd.GoRuntimePackage+".Node" { + type_cast = "" + } else { + type_cast = ".(" + type_cast + ")" + } + vc.outf(`%[1]s%[2]s: %[3]skids[%[4]d]%[5]s, +`, + strings.Repeat("\t", tabs), + upper1st(arg.Name), + padding, + i, + type_cast, + ) + } +} + +func (node CasesRuleNode) GenGoLeafInstAccepts(vc *genAcceptsCmd, tabs int) { + vc.outf(`%[1]s%[2]s: kids[0], +`, + strings.Repeat("\t", tabs), + "Node", + // vc.GoRuntimePackage+".Node", + ) +} diff --git a/golang/cli/ruleast/gen_go_interfaces.go b/golang/cli/ruleast/gen_go_interfaces.go new file mode 100644 index 00000000..a57f931b --- /dev/null +++ b/golang/cli/ruleast/gen_go_interfaces.go @@ -0,0 +1,128 @@ +package ruleast + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" +) + +type genInterfaceCmd struct { + GenCmd genCmd `opts:"mode=embedded"` + OutputFile string +} + +func NewGenInterfaceCmd() *genInterfaceCmd { + return &genInterfaceCmd{ + GenCmd: genCmd{ + GoRuntimeImport: "github.com/ohmjs/goohm", + GoRuntimePackage: "goohm", + sbldr: &strings.Builder{}, + }, + } +} + +func (vc *genInterfaceCmd) Run() error { + if vc.GenCmd.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.GenCmd.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %v", err) + } + vc.GenCmd.Grammar = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + if vc.OutputFile == "-" { + fmt.Printf("%s\n", out) + return nil + } + fi, err := os.Create(vc.OutputFile) + if err != nil { + return fmt.Errorf("error creating file %w", err) + } + defer fi.Close() + _, err = fi.WriteString(out) + if err != nil { + return fmt.Errorf("error writing file %w", err) + } + return nil +} + +func (vc *genInterfaceCmd) Process() (string, error) { + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return "", fmt.Errorf("creating grammar: %v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.GenCmd.Grammar); err != nil { + return "", fmt.Errorf("matching: %v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %v", err) + } + gAst, err := NewBuildGrammars(root).BuildRuleAst(root) + if err != nil { + return "", fmt.Errorf("Error building rule ast. %v", err) + } + gAst.GenGoInterfaces(vc) + return vc.GenCmd.sbldr.String(), nil +} + +func (gmrs GrammarsNode) GenGoInterfaces(vc *genInterfaceCmd) { + if vc.GenCmd.GoTypePackage == "" { + vc.GenCmd.GoTypePackage = strings.ToLower(gmrs.Gmr_names[0]) + } + vc.GenCmd.outf(`// Code generated by ohmgo generate interfaces - DO NOT EDIT. +package %[1]s + +`, vc.GenCmd.GoTypePackage, vc.GenCmd.GoRuntimeImport) + for _, gname := range gmrs.Gmr_names { + vc.GenCmd.outf(`// interfaces for grammar %[1]s + +`, gname) + gmr := gmrs.Grammars[gname] + gmr.GenGoInterfaces(vc) + } +} + +func (gmr GrammarNode) GenGoInterfaces(vc *genInterfaceCmd) { + for _, rname := range gmr.Rule_names { + rule := gmr.Rules[rname] + branch := rule.GetBranch() + vc.GenCmd.outf(`// %[1]s%[2]s +// -- rule -- +`, + branch.RuleName(), + branch.Descr(" - ", ""), + ) + for _, line := range branch.Source() { + vc.GenCmd.outf(`// %s +`, + strings.TrimSpace(line), + ) + } + vc.GenCmd.outf(`// ---- +type Visitor%[1]s[P, R any] interface { + Visit%[1]s(node *%[1]s[P, R], payload P) (result R) +} + +`, + branch.TypeName(), + ) + } +} diff --git a/golang/cli/ruleast/gen_go_types.go b/golang/cli/ruleast/gen_go_types.go new file mode 100644 index 00000000..f6678044 --- /dev/null +++ b/golang/cli/ruleast/gen_go_types.go @@ -0,0 +1,169 @@ +package ruleast + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" + "github.com/samber/lo" +) + +type genTypesCmd struct { + GenCmd genCmd `opts:"mode=embedded"` + NoGenerics bool `opts:"short=g" help:"Do not generate generic types (ie with [P any, R any])"` + OutputFile string +} + +func NewGenTypesCmd() *genTypesCmd { + return &genTypesCmd{ + GenCmd: genCmd{ + GoRuntimeImport: "github.com/ohmjs/goohm", + GoRuntimePackage: "goohm", + sbldr: &strings.Builder{}, + // SuffixOutfLineNos: true, + }, + OutputFile: "-", + } +} + +func (vc *genTypesCmd) Run() error { + if vc.GenCmd.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.GenCmd.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %v", err) + } + vc.GenCmd.Grammar = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + if vc.OutputFile == "-" { + fmt.Printf("%[1]s\n", out) + return nil + } + fi, err := os.Create(vc.OutputFile) + if err != nil { + return fmt.Errorf("error creating file %w", err) + } + defer fi.Close() + _, err = fi.WriteString(out) + if err != nil { + return fmt.Errorf("error writing file %w", err) + } + return nil +} + +func (vc *genTypesCmd) Process() (string, error) { + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return "", fmt.Errorf("creating grammar: %v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.GenCmd.Grammar); err != nil { + return "", fmt.Errorf("matching: %v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %v", err) + } + gAst, err := NewBuildGrammars(root).BuildRuleAst(root) + if err != nil { + return "", fmt.Errorf("Error building rule ast. %v", err) + } + gAst.GenGoTypes(vc) + return vc.GenCmd.sbldr.String(), nil +} + +func (gmrs GrammarsNode) GenGoTypes(vc *genTypesCmd) { + if vc.GenCmd.GoTypePackage == "" { + vc.GenCmd.GoTypePackage = strings.ToLower(gmrs.Gmr_names[0]) + } + vc.GenCmd.outf(`// Code generated by ohmgo generate types - DO NOT EDIT. +package %[1]s + +import ( + "%[2]s" +) + +`, vc.GenCmd.GoTypePackage, vc.GenCmd.GoRuntimeImport) + for _, gname := range gmrs.Gmr_names { + vc.GenCmd.outf(`// types for grammar %[1]s + +`, gname) + gmr := gmrs.Grammars[gname] + gmr.GenGoTypes(vc) + } +} + +func (gmr GrammarNode) GenGoTypes(vc *genTypesCmd) { + for _, rname := range gmr.Rule_names { + rule := gmr.Rules[rname] + branch := rule.GetBranch() + vc.GenCmd.outf(`// %[1]s%[2]s +// -- rule -- +`, + branch.RuleName(), + branch.Descr(" - ", ""), + ) + for _, line := range branch.Source() { + vc.GenCmd.outf(`// %[1]s +`, + strings.TrimSpace(line), + ) + } + generics := "[P, R any]" + if vc.NoGenerics { + generics = "" + } + vc.GenCmd.outf(`// ---- +type %[1]s%[2]s struct { +`, + branch.TypeName(), + generics, + ) + branch.GenGoTypes(vc) + vc.GenCmd.outf(`} + +`) + } +} + +func (node VirtRuleNode) GenGoTypes(vc *genTypesCmd) { + node.Node.GenGoTypes(vc) +} + +func (node BareRuleNode) GenGoTypes(vc *genTypesCmd) { + longest := lo.MaxBy(node.Args, func(a, b NamedArgNode) bool { + return len(a.Name) > len(b.Name) + }) + for _, arg := range node.Args { + padding := strings.Repeat(" ", len(longest.Name)-len(arg.Name)) + vc.GenCmd.outf(` %[1]s %[2]s%[3]s +`, + upper1st(arg.Name), + padding, + arg.Node.GetBranch().GoType(vc.GenCmd.GoRuntimePackage), + ) + } +} + +func (node CasesRuleNode) GenGoTypes(vc *genTypesCmd) { + vc.GenCmd.outf(` %[1]s %[2]s +`, + "Node", + vc.GenCmd.GoRuntimePackage+".Node", + ) +} diff --git a/golang/cli/ruleast/gen_types.go b/golang/cli/ruleast/gen_types.go new file mode 100644 index 00000000..2292cddf --- /dev/null +++ b/golang/cli/ruleast/gen_types.go @@ -0,0 +1,31 @@ +package ruleast + +import ( + "fmt" + "runtime" + "strings" +) + +type genCmd struct { + Grammar string `opts:"mode=arg" help:"Path to .ohm grammar file to generate a visitor for."` + GoTypePackage string `opts:"short=P" help:"The package name for the generated code, default to lower case of the grammar"` + GoRuntimeImport string + GoRuntimePackage string + SuffixOutfLineNos bool `opts:"short=l"` + + sbldr *strings.Builder +} + +func (vc genCmd) outf(format string, a ...any) { + _, file, line, _ := runtime.Caller(1) // for line numbers to be correct when SuffixOutfLineNos is true + parts := strings.Split(file, "/") + parts = parts[len(parts)-2:] + file = strings.Join(parts, "/") + callerLine := fmt.Sprintf("%s:%d", file, line) + f0 := format + if vc.SuffixOutfLineNos { + f0 = strings.ReplaceAll(format, "\n", fmt.Sprintf("\t\t\t\t\t// %%[%d]s\n", len(a)+1)) + a = append(a, callerLine) + } + fmt.Fprintf(vc.sbldr, f0, a...) +} diff --git a/golang/cli/ruleast/ruleast.go b/golang/cli/ruleast/ruleast.go new file mode 100755 index 00000000..344bdc6f --- /dev/null +++ b/golang/cli/ruleast/ruleast.go @@ -0,0 +1,992 @@ +// Code generated by goadlc v3 - DO NOT EDIT. +package ruleast + +import ( + "fmt" +) + +type ArgNode struct { + Branch ArgNodeBranch +} + +type ArgNodeBranch interface { + isArgNodeBranch() +} + +func (*ArgNode) MakeNewBranch(key string) (any, error) { + switch key { + case "nobj": + return &_ArgNode_Nobj{}, nil + case "rule": + return &_ArgNode_Rule{}, nil + case "term": + return &_ArgNode_Term{}, nil + case "list": + return &_ArgNode_List{}, nil + case "opt": + return &_ArgNode_Opt{}, nil + case "bhor": + return &_ArgNode_Bhor{}, nil + } + return nil, fmt.Errorf("unknown branch is : %s", key) +} + +type _ArgNode_Nobj struct { + V NObjNode `branch:"nobj"` +} +type _ArgNode_Rule struct { + V NontNode `branch:"rule"` +} +type _ArgNode_Term struct { + V TermNode `branch:"term"` +} +type _ArgNode_List struct { + V ListNode `branch:"list"` +} +type _ArgNode_Opt struct { + V OptNode `branch:"opt"` +} +type _ArgNode_Bhor struct { + V BuiltinHOR `branch:"bhor"` +} + +func (_ArgNode_Nobj) isArgNodeBranch() {} +func (_ArgNode_Rule) isArgNodeBranch() {} +func (_ArgNode_Term) isArgNodeBranch() {} +func (_ArgNode_List) isArgNodeBranch() {} +func (_ArgNode_Opt) isArgNodeBranch() {} +func (_ArgNode_Bhor) isArgNodeBranch() {} + +func Make_ArgNode_nobj(v NObjNode) ArgNode { + return ArgNode{ + _ArgNode_Nobj{v}, + } +} + +func Make_ArgNode_rule(v NontNode) ArgNode { + return ArgNode{ + _ArgNode_Rule{v}, + } +} + +func Make_ArgNode_term(v TermNode) ArgNode { + return ArgNode{ + _ArgNode_Term{v}, + } +} + +func Make_ArgNode_list(v ListNode) ArgNode { + return ArgNode{ + _ArgNode_List{v}, + } +} + +func Make_ArgNode_opt(v OptNode) ArgNode { + return ArgNode{ + _ArgNode_Opt{v}, + } +} + +func Make_ArgNode_bhor(v BuiltinHOR) ArgNode { + return ArgNode{ + _ArgNode_Bhor{v}, + } +} + +func (un ArgNode) Cast_nobj() (NObjNode, bool) { + br, ok := un.Branch.(_ArgNode_Nobj) + return br.V, ok +} + +func (un ArgNode) Cast_rule() (NontNode, bool) { + br, ok := un.Branch.(_ArgNode_Rule) + return br.V, ok +} + +func (un ArgNode) Cast_term() (TermNode, bool) { + br, ok := un.Branch.(_ArgNode_Term) + return br.V, ok +} + +func (un ArgNode) Cast_list() (ListNode, bool) { + br, ok := un.Branch.(_ArgNode_List) + return br.V, ok +} + +func (un ArgNode) Cast_opt() (OptNode, bool) { + br, ok := un.Branch.(_ArgNode_Opt) + return br.V, ok +} + +func (un ArgNode) Cast_bhor() (BuiltinHOR, bool) { + br, ok := un.Branch.(_ArgNode_Bhor) + return br.V, ok +} + +func Handle_ArgNode[T any]( + _in ArgNode, + nobj func(nobj NObjNode) T, + rule func(rule NontNode) T, + term func(term TermNode) T, + list func(list ListNode) T, + opt func(opt OptNode) T, + bhor func(bhor BuiltinHOR) T, + _default func() T, +) T { + switch _b := _in.Branch.(type) { + case _ArgNode_Nobj: + if nobj != nil { + return nobj(_b.V) + } + case _ArgNode_Rule: + if rule != nil { + return rule(_b.V) + } + case _ArgNode_Term: + if term != nil { + return term(_b.V) + } + case _ArgNode_List: + if list != nil { + return list(_b.V) + } + case _ArgNode_Opt: + if opt != nil { + return opt(_b.V) + } + case _ArgNode_Bhor: + if bhor != nil { + return bhor(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : ArgNode") +} + +func HandleWithErr_ArgNode[T any]( + _in ArgNode, + nobj func(nobj NObjNode) (T, error), + rule func(rule NontNode) (T, error), + term func(term TermNode) (T, error), + list func(list ListNode) (T, error), + opt func(opt OptNode) (T, error), + bhor func(bhor BuiltinHOR) (T, error), + _default func() (T, error), +) (T, error) { + switch _b := _in.Branch.(type) { + case _ArgNode_Nobj: + if nobj != nil { + return nobj(_b.V) + } + case _ArgNode_Rule: + if rule != nil { + return rule(_b.V) + } + case _ArgNode_Term: + if term != nil { + return term(_b.V) + } + case _ArgNode_List: + if list != nil { + return list(_b.V) + } + case _ArgNode_Opt: + if opt != nil { + return opt(_b.V) + } + case _ArgNode_Bhor: + if bhor != nil { + return bhor(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : ArgNode") +} + +type BareNode struct { + _BareNode +} + +type _BareNode struct { + Args []NamedArgNode `json:"args"` +} + +func MakeAll_BareNode( + args []NamedArgNode, +) BareNode { + return BareNode{ + _BareNode{ + Args: args, + }, + } +} + +func Make_BareNode( + args []NamedArgNode, +) BareNode { + ret := BareNode{ + _BareNode{ + Args: args, + }, + } + return ret +} + +type BareRuleNode struct { + _BareRuleNode +} + +type _BareRuleNode struct { + Name string `json:"name"` + Rtype RuleType `json:"rtype"` + Descr string `json:"descr"` + Source string `json:"source"` + Args []NamedArgNode `json:"args"` +} + +func MakeAll_BareRuleNode( + name string, + rtype RuleType, + descr string, + source string, + args []NamedArgNode, +) BareRuleNode { + return BareRuleNode{ + _BareRuleNode{ + Name: name, + Rtype: rtype, + Descr: descr, + Source: source, + Args: args, + }, + } +} + +func Make_BareRuleNode( + name string, + rtype RuleType, + descr string, + source string, + args []NamedArgNode, +) BareRuleNode { + ret := BareRuleNode{ + _BareRuleNode{ + Name: name, + Rtype: rtype, + Descr: descr, + Source: source, + Args: args, + }, + } + return ret +} + +type BuiltinHOR struct { + _BuiltinHOR +} + +type _BuiltinHOR struct { + List_type string `json:"list_type"` + Elem NamedArgNode `json:"elem"` + Sep NamedArgNode `json:"sep"` +} + +func MakeAll_BuiltinHOR( + list_type string, + elem NamedArgNode, + sep NamedArgNode, +) BuiltinHOR { + return BuiltinHOR{ + _BuiltinHOR{ + List_type: list_type, + Elem: elem, + Sep: sep, + }, + } +} + +func Make_BuiltinHOR( + list_type string, + elem NamedArgNode, + sep NamedArgNode, +) BuiltinHOR { + ret := BuiltinHOR{ + _BuiltinHOR{ + List_type: list_type, + Elem: elem, + Sep: sep, + }, + } + return ret +} + +type CasesRuleNode struct { + _CasesRuleNode +} + +type _CasesRuleNode struct { + Name string `json:"name"` + Rtype RuleType `json:"rtype"` + Descr string `json:"descr"` + Source string `json:"source"` + Args []NamedArgNode `json:"args"` + Cases []InlineNode `json:"cases"` +} + +func MakeAll_CasesRuleNode( + name string, + rtype RuleType, + descr string, + source string, + args []NamedArgNode, + cases []InlineNode, +) CasesRuleNode { + return CasesRuleNode{ + _CasesRuleNode{ + Name: name, + Rtype: rtype, + Descr: descr, + Source: source, + Args: args, + Cases: cases, + }, + } +} + +func Make_CasesRuleNode( + name string, + rtype RuleType, + descr string, + source string, + args []NamedArgNode, + cases []InlineNode, +) CasesRuleNode { + ret := CasesRuleNode{ + _CasesRuleNode{ + Name: name, + Rtype: rtype, + Descr: descr, + Source: source, + Args: args, + Cases: cases, + }, + } + return ret +} + +type GrammarNode struct { + _GrammarNode +} + +type _GrammarNode struct { + Name string `json:"name"` + Rule_names []string `json:"rule_names"` + Rules map[string]RuleNode `json:"rules"` +} + +func MakeAll_GrammarNode( + name string, + rule_names []string, + rules map[string]RuleNode, +) GrammarNode { + return GrammarNode{ + _GrammarNode{ + Name: name, + Rule_names: rule_names, + Rules: rules, + }, + } +} + +func Make_GrammarNode( + name string, + rule_names []string, + rules map[string]RuleNode, +) GrammarNode { + ret := GrammarNode{ + _GrammarNode{ + Name: name, + Rule_names: rule_names, + Rules: rules, + }, + } + return ret +} + +type GrammarsNode struct { + _GrammarsNode +} + +type _GrammarsNode struct { + Gmr_names []string `json:"gmr_names"` + Grammars map[string]GrammarNode `json:"grammars"` +} + +func MakeAll_GrammarsNode( + gmr_names []string, + grammars map[string]GrammarNode, +) GrammarsNode { + return GrammarsNode{ + _GrammarsNode{ + Gmr_names: gmr_names, + Grammars: grammars, + }, + } +} + +func Make_GrammarsNode( + gmr_names []string, + grammars map[string]GrammarNode, +) GrammarsNode { + ret := GrammarsNode{ + _GrammarsNode{ + Gmr_names: gmr_names, + Grammars: grammars, + }, + } + return ret +} + +type InlineNode struct { + _InlineNode +} + +type _InlineNode struct { + Case_name string `json:"case_name"` + Source string `json:"source"` + Args []NamedArgNode `json:"args"` +} + +func MakeAll_InlineNode( + case_name string, + source string, + args []NamedArgNode, +) InlineNode { + return InlineNode{ + _InlineNode{ + Case_name: case_name, + Source: source, + Args: args, + }, + } +} + +func Make_InlineNode( + case_name string, + source string, + args []NamedArgNode, +) InlineNode { + ret := InlineNode{ + _InlineNode{ + Case_name: case_name, + Source: source, + Args: args, + }, + } + return ret +} + +type ListNode struct { + _ListNode +} + +type _ListNode struct { + Elem ArgNode `json:"elem"` +} + +func MakeAll_ListNode( + elem ArgNode, +) ListNode { + return ListNode{ + _ListNode{ + Elem: elem, + }, + } +} + +func Make_ListNode( + elem ArgNode, +) ListNode { + ret := ListNode{ + _ListNode{ + Elem: elem, + }, + } + return ret +} + +type NObjNode struct { + _NObjNode +} + +type _NObjNode struct { +} + +func MakeAll_NObjNode() NObjNode { + return NObjNode{ + _NObjNode{}, + } +} + +func Make_NObjNode() NObjNode { + ret := NObjNode{ + _NObjNode{}, + } + return ret +} + +type Named[N any] struct { + _Named[N] +} + +type _Named[N any] struct { + Name string `json:"name"` + Node N `json:"node"` +} + +func MakeAll_Named[N any]( + name string, + node N, +) Named[N] { + return Named[N]{ + _Named[N]{ + Name: name, + Node: node, + }, + } +} + +func Make_Named[N any]( + name string, + node N, +) Named[N] { + ret := Named[N]{ + _Named[N]{ + Name: name, + Node: node, + }, + } + return ret +} + +type NamedArgNode Named[ArgNode] + +type NontNode struct { + _NontNode +} + +type _NontNode struct { + Rule string `json:"rule"` +} + +func MakeAll_NontNode( + rule string, +) NontNode { + return NontNode{ + _NontNode{ + Rule: rule, + }, + } +} + +func Make_NontNode( + rule string, +) NontNode { + ret := NontNode{ + _NontNode{ + Rule: rule, + }, + } + return ret +} + +type OptNode struct { + _OptNode +} + +type _OptNode struct { + Elem ArgNode `json:"elem"` +} + +func MakeAll_OptNode( + elem ArgNode, +) OptNode { + return OptNode{ + _OptNode{ + Elem: elem, + }, + } +} + +func Make_OptNode( + elem ArgNode, +) OptNode { + ret := OptNode{ + _OptNode{ + Elem: elem, + }, + } + return ret +} + +type RuleDetailNode struct { + Branch RuleDetailNodeBranch +} + +type RuleDetailNodeBranch interface { + isRuleDetailNodeBranch() +} + +func (*RuleDetailNode) MakeNewBranch(key string) (any, error) { + switch key { + case "inline": + return &_RuleDetailNode_Inline{}, nil + case "bare": + return &_RuleDetailNode_Bare{}, nil + } + return nil, fmt.Errorf("unknown branch is : %s", key) +} + +type _RuleDetailNode_Inline struct { + V InlineNode `branch:"inline"` +} +type _RuleDetailNode_Bare struct { + V BareNode `branch:"bare"` +} + +func (_RuleDetailNode_Inline) isRuleDetailNodeBranch() {} +func (_RuleDetailNode_Bare) isRuleDetailNodeBranch() {} + +func Make_RuleDetailNode_inline(v InlineNode) RuleDetailNode { + return RuleDetailNode{ + _RuleDetailNode_Inline{v}, + } +} + +func Make_RuleDetailNode_bare(v BareNode) RuleDetailNode { + return RuleDetailNode{ + _RuleDetailNode_Bare{v}, + } +} + +func (un RuleDetailNode) Cast_inline() (InlineNode, bool) { + br, ok := un.Branch.(_RuleDetailNode_Inline) + return br.V, ok +} + +func (un RuleDetailNode) Cast_bare() (BareNode, bool) { + br, ok := un.Branch.(_RuleDetailNode_Bare) + return br.V, ok +} + +func Handle_RuleDetailNode[T any]( + _in RuleDetailNode, + inline func(inline InlineNode) T, + bare func(bare BareNode) T, + _default func() T, +) T { + switch _b := _in.Branch.(type) { + case _RuleDetailNode_Inline: + if inline != nil { + return inline(_b.V) + } + case _RuleDetailNode_Bare: + if bare != nil { + return bare(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleDetailNode") +} + +func HandleWithErr_RuleDetailNode[T any]( + _in RuleDetailNode, + inline func(inline InlineNode) (T, error), + bare func(bare BareNode) (T, error), + _default func() (T, error), +) (T, error) { + switch _b := _in.Branch.(type) { + case _RuleDetailNode_Inline: + if inline != nil { + return inline(_b.V) + } + case _RuleDetailNode_Bare: + if bare != nil { + return bare(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleDetailNode") +} + +type RuleNode struct { + Branch RuleNodeBranch +} + +type RuleNodeBranch interface { + isRuleNodeBranch() +} + +func (*RuleNode) MakeNewBranch(key string) (any, error) { + switch key { + case "bare_rule": + return &_RuleNode_Bare_rule{}, nil + case "virt_rule": + return &_RuleNode_Virt_rule{}, nil + case "case_rule": + return &_RuleNode_Case_rule{}, nil + } + return nil, fmt.Errorf("unknown branch is : %s", key) +} + +type _RuleNode_Bare_rule struct { + V BareRuleNode `branch:"bare_rule"` +} +type _RuleNode_Virt_rule struct { + V VirtRuleNode `branch:"virt_rule"` +} +type _RuleNode_Case_rule struct { + V CasesRuleNode `branch:"case_rule"` +} + +func (_RuleNode_Bare_rule) isRuleNodeBranch() {} +func (_RuleNode_Virt_rule) isRuleNodeBranch() {} +func (_RuleNode_Case_rule) isRuleNodeBranch() {} + +func Make_RuleNode_bare_rule(v BareRuleNode) RuleNode { + return RuleNode{ + _RuleNode_Bare_rule{v}, + } +} + +func Make_RuleNode_virt_rule(v VirtRuleNode) RuleNode { + return RuleNode{ + _RuleNode_Virt_rule{v}, + } +} + +func Make_RuleNode_case_rule(v CasesRuleNode) RuleNode { + return RuleNode{ + _RuleNode_Case_rule{v}, + } +} + +func (un RuleNode) Cast_bare_rule() (BareRuleNode, bool) { + br, ok := un.Branch.(_RuleNode_Bare_rule) + return br.V, ok +} + +func (un RuleNode) Cast_virt_rule() (VirtRuleNode, bool) { + br, ok := un.Branch.(_RuleNode_Virt_rule) + return br.V, ok +} + +func (un RuleNode) Cast_case_rule() (CasesRuleNode, bool) { + br, ok := un.Branch.(_RuleNode_Case_rule) + return br.V, ok +} + +func Handle_RuleNode[T any]( + _in RuleNode, + bare_rule func(bare_rule BareRuleNode) T, + virt_rule func(virt_rule VirtRuleNode) T, + case_rule func(case_rule CasesRuleNode) T, + _default func() T, +) T { + switch _b := _in.Branch.(type) { + case _RuleNode_Bare_rule: + if bare_rule != nil { + return bare_rule(_b.V) + } + case _RuleNode_Virt_rule: + if virt_rule != nil { + return virt_rule(_b.V) + } + case _RuleNode_Case_rule: + if case_rule != nil { + return case_rule(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleNode") +} + +func HandleWithErr_RuleNode[T any]( + _in RuleNode, + bare_rule func(bare_rule BareRuleNode) (T, error), + virt_rule func(virt_rule VirtRuleNode) (T, error), + case_rule func(case_rule CasesRuleNode) (T, error), + _default func() (T, error), +) (T, error) { + switch _b := _in.Branch.(type) { + case _RuleNode_Bare_rule: + if bare_rule != nil { + return bare_rule(_b.V) + } + case _RuleNode_Virt_rule: + if virt_rule != nil { + return virt_rule(_b.V) + } + case _RuleNode_Case_rule: + if case_rule != nil { + return case_rule(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleNode") +} + +type RuleType struct { + Branch RuleTypeBranch +} + +type RuleTypeBranch interface { + isRuleTypeBranch() +} + +func (*RuleType) MakeNewBranch(key string) (any, error) { + switch key { + case "define": + return &_RuleType_Define{}, nil + case "override": + return &_RuleType_Override{}, nil + case "extend": + return &_RuleType_Extend{}, nil + } + return nil, fmt.Errorf("unknown branch is : %s", key) +} + +type _RuleType_Define struct { + V struct{} `branch:"define"` +} +type _RuleType_Override struct { + V struct{} `branch:"override"` +} +type _RuleType_Extend struct { + V struct{} `branch:"extend"` +} + +func (_RuleType_Define) isRuleTypeBranch() {} +func (_RuleType_Override) isRuleTypeBranch() {} +func (_RuleType_Extend) isRuleTypeBranch() {} + +func Make_RuleType_define() RuleType { + return RuleType{ + _RuleType_Define{struct{}{}}, + } +} + +func Make_RuleType_override() RuleType { + return RuleType{ + _RuleType_Override{struct{}{}}, + } +} + +func Make_RuleType_extend() RuleType { + return RuleType{ + _RuleType_Extend{struct{}{}}, + } +} + +func (un RuleType) Cast_define() (struct{}, bool) { + br, ok := un.Branch.(_RuleType_Define) + return br.V, ok +} + +func (un RuleType) Cast_override() (struct{}, bool) { + br, ok := un.Branch.(_RuleType_Override) + return br.V, ok +} + +func (un RuleType) Cast_extend() (struct{}, bool) { + br, ok := un.Branch.(_RuleType_Extend) + return br.V, ok +} + +func Handle_RuleType[T any]( + _in RuleType, + define func(define struct{}) T, + override func(override struct{}) T, + extend func(extend struct{}) T, + _default func() T, +) T { + switch _b := _in.Branch.(type) { + case _RuleType_Define: + if define != nil { + return define(_b.V) + } + case _RuleType_Override: + if override != nil { + return override(_b.V) + } + case _RuleType_Extend: + if extend != nil { + return extend(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleType") +} + +func HandleWithErr_RuleType[T any]( + _in RuleType, + define func(define struct{}) (T, error), + override func(override struct{}) (T, error), + extend func(extend struct{}) (T, error), + _default func() (T, error), +) (T, error) { + switch _b := _in.Branch.(type) { + case _RuleType_Define: + if define != nil { + return define(_b.V) + } + case _RuleType_Override: + if override != nil { + return override(_b.V) + } + case _RuleType_Extend: + if extend != nil { + return extend(_b.V) + } + } + if _default != nil { + return _default() + } + panic("unhandled branch in : RuleType") +} + +type TermNode struct { + _TermNode +} + +type _TermNode struct { +} + +func MakeAll_TermNode() TermNode { + return TermNode{ + _TermNode{}, + } +} + +func Make_TermNode() TermNode { + ret := TermNode{ + _TermNode{}, + } + return ret +} + +type VirtRuleNode Named[BareRuleNode] diff --git a/golang/cli/ruleast/ruleast_ast.go b/golang/cli/ruleast/ruleast_ast.go new file mode 100755 index 00000000..8079a9b1 --- /dev/null +++ b/golang/cli/ruleast/ruleast_ast.go @@ -0,0 +1,1311 @@ +// Code generated by goadlc v3 - DO NOT EDIT. +package ruleast + +import ( + goadl "github.com/adl-lang/goadl_rt/v3" + "github.com/adl-lang/goadl_rt/v3/customtypes" + "github.com/adl-lang/goadl_rt/v3/sys/adlast" + "github.com/adl-lang/goadl_rt/v3/sys/types" +) + +func Texpr_ArgNode() adlast.ATypeExpr[ArgNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "ArgNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[ArgNode](te) +} + +func AST_ArgNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "ArgNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_union_( + adlast.MakeAll_Union( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "nobj", + "nobj", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NObjNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "rule", + "rule", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NontNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "term", + "term", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "TermNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "list", + "list", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "ListNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "opt", + "opt", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "OptNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "bhor", + "bhor", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "BuiltinHOR", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "ArgNode"), + AST_ArgNode(), + ) +} + +func Texpr_BareNode() adlast.ATypeExpr[BareNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "BareNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[BareNode](te) +} + +func AST_BareNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "BareNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "args", + "args", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "BareNode"), + AST_BareNode(), + ) +} + +func Texpr_BareRuleNode() adlast.ATypeExpr[BareRuleNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "BareRuleNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[BareRuleNode](te) +} + +func AST_BareRuleNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "BareRuleNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "name", + "name", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "rtype", + "rtype", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "RuleType", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "descr", + "descr", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "source", + "source", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "args", + "args", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "BareRuleNode"), + AST_BareRuleNode(), + ) +} + +func Texpr_BuiltinHOR() adlast.ATypeExpr[BuiltinHOR] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "BuiltinHOR"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[BuiltinHOR](te) +} + +func AST_BuiltinHOR() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "BuiltinHOR", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "list_type", + "list_type", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "elem", + "elem", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "sep", + "sep", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "BuiltinHOR"), + AST_BuiltinHOR(), + ) +} + +func Texpr_CasesRuleNode() adlast.ATypeExpr[CasesRuleNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "CasesRuleNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[CasesRuleNode](te) +} + +func AST_CasesRuleNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "CasesRuleNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "name", + "name", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "rtype", + "rtype", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "RuleType", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "descr", + "descr", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "source", + "source", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "args", + "args", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "cases", + "cases", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "InlineNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "CasesRuleNode"), + AST_CasesRuleNode(), + ) +} + +func Texpr_GrammarNode() adlast.ATypeExpr[GrammarNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "GrammarNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[GrammarNode](te) +} + +func AST_GrammarNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "GrammarNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "name", + "name", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "rule_names", + "rule_names", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "rules", + "rules", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "StringMap", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "RuleNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "GrammarNode"), + AST_GrammarNode(), + ) +} + +func Texpr_GrammarsNode() adlast.ATypeExpr[GrammarsNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "GrammarsNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[GrammarsNode](te) +} + +func AST_GrammarsNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "GrammarsNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "gmr_names", + "gmr_names", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "grammars", + "grammars", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "StringMap", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "GrammarNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "GrammarsNode"), + AST_GrammarsNode(), + ) +} + +func Texpr_InlineNode() adlast.ATypeExpr[InlineNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "InlineNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[InlineNode](te) +} + +func AST_InlineNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "InlineNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "case_name", + "case_name", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "source", + "source", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "args", + "args", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Vector", + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "NamedArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "InlineNode"), + AST_InlineNode(), + ) +} + +func Texpr_ListNode() adlast.ATypeExpr[ListNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "ListNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[ListNode](te) +} + +func AST_ListNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "ListNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "elem", + "elem", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "ArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "ListNode"), + AST_ListNode(), + ) +} + +func Texpr_NObjNode() adlast.ATypeExpr[NObjNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "NObjNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[NObjNode](te) +} + +func AST_NObjNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "NObjNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{}, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "NObjNode"), + AST_NObjNode(), + ) +} + +func Texpr_Named[N any](n adlast.ATypeExpr[N]) adlast.ATypeExpr[Named[N]] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "Named"), + ), + []adlast.TypeExpr{n.Value}, + ) + return adlast.Make_ATypeExpr[Named[N]](te) +} + +func AST_Named() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "Named", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{ + "N", + }, + []adlast.Field{ + adlast.MakeAll_Field( + "name", + "name", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "node", + "node", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_typeParam( + "N", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "Named"), + AST_Named(), + ) +} + +func Texpr_NamedArgNode() adlast.ATypeExpr[NamedArgNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "NamedArgNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[NamedArgNode](te) +} + +func AST_NamedArgNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "NamedArgNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_newtype_( + adlast.MakeAll_NewType( + []adlast.Ident{}, + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "Named", + ), + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "ArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "NamedArgNode"), + AST_NamedArgNode(), + ) +} + +func Texpr_NontNode() adlast.ATypeExpr[NontNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "NontNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[NontNode](te) +} + +func AST_NontNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "NontNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "rule", + "rule", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "String", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "NontNode"), + AST_NontNode(), + ) +} + +func Texpr_OptNode() adlast.ATypeExpr[OptNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "OptNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[OptNode](te) +} + +func AST_OptNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "OptNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "elem", + "elem", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "ArgNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "OptNode"), + AST_OptNode(), + ) +} + +func Texpr_RuleDetailNode() adlast.ATypeExpr[RuleDetailNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "RuleDetailNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[RuleDetailNode](te) +} + +func AST_RuleDetailNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "RuleDetailNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_union_( + adlast.MakeAll_Union( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "inline", + "inline", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "InlineNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "bare", + "bare", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "BareNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "RuleDetailNode"), + AST_RuleDetailNode(), + ) +} + +func Texpr_RuleNode() adlast.ATypeExpr[RuleNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "RuleNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[RuleNode](te) +} + +func AST_RuleNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "RuleNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_union_( + adlast.MakeAll_Union( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "bare_rule", + "bare_rule", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "BareRuleNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "virt_rule", + "virt_rule", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "VirtRuleNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "case_rule", + "case_rule", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "CasesRuleNode", + ), + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "RuleNode"), + AST_RuleNode(), + ) +} + +func Texpr_RuleType() adlast.ATypeExpr[RuleType] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "RuleType"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[RuleType](te) +} + +func AST_RuleType() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "RuleType", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_union_( + adlast.MakeAll_Union( + []adlast.Ident{}, + []adlast.Field{ + adlast.MakeAll_Field( + "define", + "define", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Void", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "override", + "override", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Void", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + adlast.MakeAll_Field( + "extend", + "extend", + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_primitive( + "Void", + ), + []adlast.TypeExpr{}, + ), + types.Make_Maybe_nothing[any](), + customtypes.MapMap[adlast.ScopedName, any]{}, + ), + }, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "RuleType"), + AST_RuleType(), + ) +} + +func Texpr_TermNode() adlast.ATypeExpr[TermNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "TermNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[TermNode](te) +} + +func AST_TermNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "TermNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_struct_( + adlast.MakeAll_Struct( + []adlast.Ident{}, + []adlast.Field{}, + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "TermNode"), + AST_TermNode(), + ) +} + +func Texpr_VirtRuleNode() adlast.ATypeExpr[VirtRuleNode] { + te := adlast.Make_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.Make_ScopedName("ruleast", "VirtRuleNode"), + ), + []adlast.TypeExpr{}, + ) + return adlast.Make_ATypeExpr[VirtRuleNode](te) +} + +func AST_VirtRuleNode() adlast.ScopedDecl { + decl := adlast.MakeAll_Decl( + "VirtRuleNode", + types.Make_Maybe_nothing[uint32](), + adlast.Make_DeclType_newtype_( + adlast.MakeAll_NewType( + []adlast.Ident{}, + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "Named", + ), + ), + []adlast.TypeExpr{ + adlast.MakeAll_TypeExpr( + adlast.Make_TypeRef_reference( + adlast.MakeAll_ScopedName( + "ruleast", + "BareRuleNode", + ), + ), + []adlast.TypeExpr{}, + ), + }, + ), + types.Make_Maybe_nothing[any](), + ), + ), + customtypes.MapMap[adlast.ScopedName, any]{}, + ) + return adlast.Make_ScopedDecl("ruleast", decl) +} + +func init() { + goadl.RESOLVER.Register( + adlast.Make_ScopedName("ruleast", "VirtRuleNode"), + AST_VirtRuleNode(), + ) +} diff --git a/golang/cli/ruleast/utils.go b/golang/cli/ruleast/utils.go new file mode 100644 index 00000000..7382e322 --- /dev/null +++ b/golang/cli/ruleast/utils.go @@ -0,0 +1,195 @@ +package ruleast + +import ( + "fmt" + "strings" +) + +func upper1st(s string) string { + return strings.ToUpper(s[:1]) + s[1:] +} + +func r2name(rname string) string { + if rname[0] >= 'A' && rname[0] <= 'Z' { + return rname + } + return "Lex" + upper1st(rname) +} + +type GoTyped interface { + GoType(rtpkg string) string + GenGoLeafAccepts(vc *genAcceptsCmd, gmr_name string, name string) + GenGoBHORCallback(vc *genAcceptsCmd, gmr_name string, fname string) + // GenGoBareCaseAccepts(vc *genAcceptsCmd, gmr_name string, name string) +} + +func (NObjNode) GoType(rtpkg string) string { return rtpkg + ".Node" } +func (NontNode) GoType(rtpkg string) string { return rtpkg + ".RuleNode" } +func (TermNode) GoType(rtpkg string) string { return rtpkg + ".TerminalNode" } +func (n ListNode) GoType(rtpkg string) string { + return rtpkg + ".ListNode" + // return n.Elem.GetBranch().GoType(rtpkg) +} +func (OptNode) GoType(rtpkg string) string { return rtpkg + ".OptNode" } +func (BuiltinHOR) GoType(rtpkg string) string { return rtpkg + ".BHorNode" } + +func (v ArgNode) GetBranch() GoTyped { + return Handle_ArgNode[GoTyped]( + v, + func(n NObjNode) GoTyped { return NObjNode{n._NObjNode} }, + func(n NontNode) GoTyped { return NontNode{n._NontNode} }, + func(n TermNode) GoTyped { return TermNode{n._TermNode} }, + func(n ListNode) GoTyped { return ListNode{n._ListNode} }, + func(n OptNode) GoTyped { return OptNode{n._OptNode} }, + func(n BuiltinHOR) GoTyped { return BuiltinHOR{n._BuiltinHOR} }, + nil, + ) +} + +type GoTypedRule interface { + Descr(pre, suf string) string + TypeName() string + RuleName() string + Source() []string + GetArgs() []NamedArgNode + GenGoTypes(vc *genTypesCmd) + GenGoAccepts(vc *genAcceptsCmd, gmr_name string) + GenGoLeafInstAccepts(vc *genAcceptsCmd, tabs int) +} + +func (rule RuleNode) GetBranch() GoTypedRule { + return Handle_RuleNode[GoTypedRule]( + rule, + func(r BareRuleNode) GoTypedRule { + return BareRuleNode{r._BareRuleNode} + }, + func(r VirtRuleNode) GoTypedRule { + return VirtRuleNode(Named[BareRuleNode]{r._Named}) + }, + func(r CasesRuleNode) GoTypedRule { + return CasesRuleNode{r._CasesRuleNode} + }, + nil, + ) +} + +func (r BareRuleNode) Descr(pre, suf string) string { + if r._BareRuleNode.Descr == "" { + return "" + } + return pre + r._BareRuleNode.Descr + suf +} +func (r CasesRuleNode) Descr(pre, suf string) string { + if r._CasesRuleNode.Descr == "" { + return "" + } + return pre + r._CasesRuleNode.Descr + suf +} +func (r VirtRuleNode) Descr(pre, suf string) string { + return r.Node.Descr(pre, suf) +} + +func (r BareRuleNode) TypeName() string { return r2name(r._BareRuleNode.Name) } +func (r CasesRuleNode) TypeName() string { return r2name(r._CasesRuleNode.Name) } +func (r VirtRuleNode) TypeName() string { + return r2name(r._Named.Name) + upper1st(r._Named.Node._BareRuleNode.Name) +} + +func (r BareRuleNode) RuleName() string { return r._BareRuleNode.Name } +func (r CasesRuleNode) RuleName() string { return r._CasesRuleNode.Name } +func (r VirtRuleNode) RuleName() string { + return r._Named.Name + "_" + r._Named.Node._BareRuleNode.Name +} + +func (r BareRuleNode) Source() []string { + return strings.Split(r._BareRuleNode.Source, "\n") +} +func (r CasesRuleNode) Source() []string { + return strings.Split(r._CasesRuleNode.Source, "\n") +} +func (r VirtRuleNode) Source() []string { + return r.Node.Source() +} + +func (r BareRuleNode) GetArgs() []NamedArgNode { return r.Args } +func (r CasesRuleNode) GetArgs() []NamedArgNode { return r.Args } +func (r VirtRuleNode) GetArgs() []NamedArgNode { return r._Named.Node.Args } + +func UnifyBranches2Args(bare []BareNode, size int) (args []NamedArgNode) { + nodetypes := make([]string, size) + nodenames := make([]string, size) + nameMap := map[string]int{} + for _, rulebody := range bare { + for i := range size { + key := Key4ArgNode(rulebody.Args[i].Node) + name := rulebody.Args[i].Name + if nodetypes[i] == "" { + nodetypes[i] = key + nodenames[i] = name + nameMap[rulebody.Args[i].Name]++ + continue + } + if nodetypes[i] != key || nodenames[i] != name { + nodetypes[i] = "node" + nodenames[i] = "arg" + nameMap["arg"]++ + } else { + nodenames[i] = name + } + } + } + for k, v := range nameMap { + if v == 1 { + continue + } + c := 1 + for i := range nodenames { + if nodenames[i] == k { + nodenames[i] = fmt.Sprintf("%s%d", k, c) + c++ + } + } + } + for i := range nodetypes { + var argNode ArgNode = bare[0].Args[i].Node + if nodetypes[i] == "node" { + argNode = Make_ArgNode_nobj( + Make_NObjNode(), + ) + } + args = append(args, + NamedArgNode( + Make_Named( + nodenames[i], + argNode, + ), + ), + ) + } + return +} + +func Key4ArgNode(arg ArgNode) string { + return Handle_ArgNode[string]( + arg, + func(nobj NObjNode) string { + return "node" + }, + func(rule NontNode) string { + return "rule" + }, + func(term TermNode) string { + return "term" + }, + func(list ListNode) string { + return "list" + }, + func(opt OptNode) string { + return "opt" + }, + func(bhor BuiltinHOR) string { + return "hor" + }, + nil, + ) +} diff --git a/golang/cli/sexpr/sexpr.go b/golang/cli/sexpr/sexpr.go new file mode 100644 index 00000000..e06b115a --- /dev/null +++ b/golang/cli/sexpr/sexpr.go @@ -0,0 +1,183 @@ +package sexpr + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/ohmjs/goohm" + "github.com/ohmjs/ohmgo/utils" + "github.com/samber/lo" +) + +type ToSexprCmd struct { + ExcludeTerminals bool `opts:"short=t"` + SyntacticRulesOnly bool `opts:"short=S"` + ExcludeBuiltin bool `opts:"short=b"` + PruneLists bool `opts:"short=l"` + NoClosingNewline bool `opts:"short=n"` + Verbose bool `opts:"short=v" help:"Output source (start & end) and source string for every node"` + Grammar string `opts:"mode=arg" help:"Grammar text, if starts with @ Path to .ohm grammar file to generate a visitor for."` +} + +var builtins = map[string]struct{}{ + "any": {}, + "letter": {}, + "lower": {}, + "upper": {}, + "digit": {}, + "hexDigit": {}, + "alnum": {}, + "space": {}, + "end": {}, +} + +func NewToSexprCmd() *ToSexprCmd { + return &ToSexprCmd{} +} + +func (vc *ToSexprCmd) Run() error { + if vc.Grammar[:1] == "@" { + barr, err := os.ReadFile(vc.Grammar[1:]) + if err != nil { + return fmt.Errorf("Error reading grammar file. %v", err) + } + vc.Grammar = string(barr) + } + out, err := vc.Process() + if err != nil { + return err + } + fmt.Printf("%s\n", out) + return nil +} + +func (vc *ToSexprCmd) Process() (string, error) { + ctx := context.Background() + var ( + gmr *goohm.Grammar + mr *goohm.MatchResult + err error + root goohm.Node + ) + if gmr, err = goohm.NewGrammar(ctx, utils.OhmGrammarWasmBytes()); err != nil { + return "", fmt.Errorf("creating grammar: %v", err) + } + defer gmr.Close() + if mr, err = gmr.Match(vc.Grammar); err != nil { + return "", fmt.Errorf("matching: %v", err) + } + defer mr.Close() + if !mr.Succeeded() { + return "", fmt.Errorf("match failed") + } + if root, err = mr.GetCstRoot(); err != nil { + return "", fmt.Errorf("Error getting cst root. %v", err) + } + var result strings.Builder + vc.toSexprNode(root, 0, &result) + return result.String()[1:], nil +} + +func (vc *ToSexprCmd) toSexprNode(node goohm.Node, depth int, result *strings.Builder) { + kids := node.Children() + if vc.ExcludeTerminals { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + _, is := node.(goohm.TerminalNode) + return !is + }) + } + if vc.SyntacticRulesOnly { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + ctor := node.CtorName() + return strings.ToUpper(ctor[:1]) == ctor[:1] + }) + } + if vc.ExcludeBuiltin { + kids = lo.Filter(kids, func(node goohm.Node, i int) bool { + ctor := node.CtorName() + _, ex := builtins[ctor] + return !ex + }) + } + ctor := node.CtorName() + if vc.PruneLists && ctor == "_list" { + for _, n := range kids { + vc.toSexprNode(n, depth, result) + } + return + } + switch { + case len(kids) != 0: + result.WriteString("\n") + result.WriteString(strings.Repeat(" ", depth)) + result.WriteString("(") + result.WriteString(ctor) + if vc.Verbose { + s, f := node.Source() + result.WriteString(fmt.Sprintf(" %d-%d ", s, f)) + src := node.SourceString() + src = sexprStrEncode(src) + if len(src) > 40 { + src = src[:37] + "..." + } + result.WriteString("'" + src + "'") + } + case ctor == "_terminal": + result.WriteString(" (") + result.WriteString(ctor) + default: + result.WriteString(" ") + result.WriteString(ctor) + } + + if ctor == "_terminal" { + addTerm(node, result) + } + for _, n := range kids { + vc.toSexprNode(n, depth+1, result) + } + switch { + case len(kids) != 0: + if !vc.NoClosingNewline { + result.WriteString("\n") + result.WriteString(strings.Repeat(" ", depth)) + } + result.WriteString(")") + case ctor == "_terminal": + result.WriteString(")") + } +} + +func addTerm(node goohm.Node, result *strings.Builder) { + val := node.SourceString() + switch val { + case "\n": + result.WriteString(" NL") + case "(": + result.WriteString(" OP") + case ")": + result.WriteString(" CP") + case "{": + result.WriteString(" OC") + case "}": + result.WriteString(" CC") + default: + result.WriteString(" '") + result.WriteString(val) + result.WriteString("'") + } + result.WriteString(" ") + s, f := node.Source() + result.WriteString(fmt.Sprintf("%d-%d", s, f)) +} + +func sexprStrEncode(val string) string { + val = strings.ReplaceAll(val, "\n", "\\n") + val = strings.ReplaceAll(val, "(", "OP") + val = strings.ReplaceAll(val, ")", "CP") + val = strings.ReplaceAll(val, "{", "OC") + val = strings.ReplaceAll(val, "}", "CC") + return val +} diff --git a/golang/cli/tests/grammar__readme.txtar b/golang/cli/tests/grammar__readme.txtar new file mode 100644 index 00000000..8540150a --- /dev/null +++ b/golang/cli/tests/grammar__readme.txtar @@ -0,0 +1,130 @@ +Grammars and tests results in the `a trivial text-based file archive format` +https://pkg.go.dev/golang.org/x/tools/txtar#hdr-Txtar_format + +Filenames are of the form [. ...]. + +Where valid are; + ohm + sexpr - see ohmgo test to_sexpr - sexpr tests in txtar files always refer to the 'ohm' file + txt + c_and_p - see ohmgo test c_and_p - compile and parse, reference the txt file of the same name + rule_ast - see ohmgo test rule_ast - rule AST, reference the txt file of the same name + +There needs to one and only one ohm + ohm for a grammar (no valid short flags) + +There can be multiple sexpr file, which test the grammar + sexpr for an sexpr representation of the grammar + for valid short flags see `ohmgo to_sexpr -h` + +When using [.flags].c_and_p, .txt is assumed to contain text which can be parsed with the ohm grammar. + +When using [.flags].rule_ast, .txt is assumed to contain a grammar. + +-- grammar.ohm -- +G { S = "a" | "b" } + +-- grammar.S.t.l.sexpr -- +(Grammars + (Grammar _opt + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) +) + +-- grammar.S.t.sexpr -- +(Grammars + (_list + (Grammar _opt + (_list + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (_list + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) +) + +-- file1.txt -- +a + +-- file1.c_and_p -- +(S (_terminal 'a' 0-1) +) + +-- gmr2.txt -- +G { S = "a" } + +-- gmr2.rule_ast -- +G +``` +S = "a" +``` +S @bare { + term @term +} diff --git a/golang/cli/tests/grammar_listof_01.txtar b/golang/cli/tests/grammar_listof_01.txtar new file mode 100644 index 00000000..a0a4bac2 --- /dev/null +++ b/golang/cli/tests/grammar_listof_01.txtar @@ -0,0 +1,223 @@ +-- grammar.ohm -- +G { + S = ListOf + a = "a".."z" +} +-- file1.txt -- +a,b,c +-- file1.n.c_and_p -- +(S + (ListOf + (NonemptyListOf + (a (_terminal 'a' 0-1)) + (_list (_terminal ',' 1-2) + (a (_terminal 'b' 2-3)) (_terminal ',' 3-4) + (a (_terminal 'c' 4-5)))))) +-- file1.l.n.c_and_p -- +(S + (ListOf + (NonemptyListOf + (a (_terminal 'a' 0-1)) (_terminal ',' 1-2) + (a (_terminal 'b' 2-3)) (_terminal ',' 3-4) + (a (_terminal 'c' 4-5))))) +-- grammar.sexpr -- +(Grammars + (_list + (Grammar + (ident + (name + (nameFirst + (letter + (upper (_terminal 'G' 0-1) + ) + ) + ) _list + ) + ) _opt (_terminal OC 2-3) + (_list + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'S' 7-8) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 9-10) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'L' 11-12) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'i' 12-13) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 13-14) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 14-15) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'O' 15-16) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'f' 16-17) + ) + ) + ) + ) + ) + ) + ) + (_opt + (Params (_terminal '<' 17-18) + (ListOf + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 18-19) + ) + ) + ) _list + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal ',' 19-20) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 21-22) + (_list + (terminalChar (_terminal ',' 22-23) + ) + ) (_terminal '"' 23-24) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '>' 24-25) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 28-29) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 30-31) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_range + (oneCharTerminal (_terminal '"' 32-33) + (terminalChar (_terminal 'a' 33-34) + ) (_terminal '"' 34-35) + ) (_terminal '..' 35-37) + (oneCharTerminal (_terminal '"' 37-38) + (terminalChar (_terminal 'z' 38-39) + ) (_terminal '"' 39-40) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) (_terminal CC 41-42) + ) + ) +) diff --git a/golang/cli/tests/grammar_mixed_01.txtar b/golang/cli/tests/grammar_mixed_01.txtar new file mode 100644 index 00000000..55c1ae44 --- /dev/null +++ b/golang/cli/tests/grammar_mixed_01.txtar @@ -0,0 +1,116 @@ +-- grammar.ohm -- +G { + S = "Z" -- A + | "B" +} +-- file1.txt -- +Z +-- file1.c_and_p -- +(S + (S_A (_terminal 'Z' 0-1) + ) +) +-- file2.txt -- +B +-- file2.c_and_p -- +(S (_terminal 'B' 0-1) +) +-- grammar.sexpr -- +(Grammars + (_list + (Grammar + (ident + (name + (nameFirst + (letter + (upper (_terminal 'G' 0-1) + ) + ) + ) _list + ) + ) _opt (_terminal OC 2-3) + (_list + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'S' 7-8) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 9-10) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 11-12) + (_list + (terminalChar (_terminal 'Z' 12-13) + ) + ) (_terminal '"' 13-14) + ) + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 15-17) + (_list + (space (_terminal ' ' 17-18) + ) + ) + (name + (nameFirst + (letter + (upper (_terminal 'A' 18-19) + ) + ) + ) _list + ) _list (_terminal NL 19-20) + ) + ) + ) + (_list (_terminal '|' 24-25) + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 26-27) + (_list + (terminalChar (_terminal 'B' 27-28) + ) + ) (_terminal '"' 28-29) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CC 30-31) + ) + ) +) diff --git a/golang/cli/tests/grammar_mixed_02.txtar b/golang/cli/tests/grammar_mixed_02.txtar new file mode 100644 index 00000000..cc6b2342 --- /dev/null +++ b/golang/cli/tests/grammar_mixed_02.txtar @@ -0,0 +1,42 @@ +-- grammar.ohm -- +G { + S = "A" -- A + | "B" + | "C" +} +-- file1.txt -- +B +-- file1.c_and_p -- +(S (_terminal 'B' 0-1) +) +-- file2.txt -- +C +-- file2.c_and_p -- +(S (_terminal 'C' 0-1) +) +-- grammar.n.l.S.v.t.sexpr -- +(Grammars 0-41 'G OC \n S = "A" -- A\n | "B"\n ...' + (Grammar 0-41 'G OC \n S = "A" -- A\n | "B"\n ...' _opt + (Rule 7-39 'S = "A" -- A\n | "B"\n | "C"' + (Rule_define 7-39 'S = "A" -- A\n | "B"\n | "C"' _opt _opt + (RuleBody 11-39 '"A" -- A\n | "B"\n | "C"' _opt + (NonemptyListOf 11-39 '"A" -- A\n | "B"\n | "C"' + (TopLevelTerm 11-20 '"A" -- A\n' + (TopLevelTerm_inline 11-20 '"A" -- A\n' + (Seq 11-14 '"A"' + (Iter 11-14 '"A"' + (Pred 11-14 '"A"' + (Lex 11-14 '"A"' + (Base 11-14 '"A"' Base_terminal))))))) + (TopLevelTerm 26-29 '"B"' + (Seq 26-29 '"B"' + (Iter 26-29 '"B"' + (Pred 26-29 '"B"' + (Lex 26-29 '"B"' + (Base 26-29 '"B"' Base_terminal)))))) + (TopLevelTerm 36-39 '"C"' + (Seq 36-39 '"C"' + (Iter 36-39 '"C"' + (Pred 36-39 '"C"' + (Lex 36-39 '"C"' + (Base 36-39 '"C"' Base_terminal)))))))))))) \ No newline at end of file diff --git a/golang/cli/tests/grammar_mixed_03.txtar b/golang/cli/tests/grammar_mixed_03.txtar new file mode 100644 index 00000000..2b1f3d38 --- /dev/null +++ b/golang/cli/tests/grammar_mixed_03.txtar @@ -0,0 +1,63 @@ +-- grammar.ohm -- +G { + S = "A" -- A + | "B" + | C + C = "C" +} +-- file0.txt -- +A +-- file0.c_and_p -- +(S + (S_A (_terminal 'A' 0-1) + ) +) +-- file1.txt -- +B +-- file1.c_and_p -- +(S (_terminal 'B' 0-1) +) +-- file2.txt -- +C +-- file2.c_and_p -- +(S + (C (_terminal 'C' 0-1) + ) +) +-- grammar.n.l.S.v.t.sexpr -- +(Grammars 0-49 'G OC \n S = "A" -- A\n | "B"\n ...' + (Grammar 0-49 'G OC \n S = "A" -- A\n | "B"\n ...' _opt + (Rule 7-37 'S = "A" -- A\n | "B"\n | C' + (Rule_define 7-37 'S = "A" -- A\n | "B"\n | C' _opt _opt + (RuleBody 11-37 '"A" -- A\n | "B"\n | C' _opt + (NonemptyListOf 11-37 '"A" -- A\n | "B"\n | C' + (TopLevelTerm 11-20 '"A" -- A\n' + (TopLevelTerm_inline 11-20 '"A" -- A\n' + (Seq 11-14 '"A"' + (Iter 11-14 '"A"' + (Pred 11-14 '"A"' + (Lex 11-14 '"A"' + (Base 11-14 '"A"' Base_terminal))))))) + (TopLevelTerm 26-29 '"B"' + (Seq 26-29 '"B"' + (Iter 26-29 '"B"' + (Pred 26-29 '"B"' + (Lex 26-29 '"B"' + (Base 26-29 '"B"' Base_terminal)))))) + (TopLevelTerm 36-37 'C' + (Seq 36-37 'C' + (Iter 36-37 'C' + (Pred 36-37 'C' + (Lex 36-37 'C' + (Base 36-37 'C' + (Base_application 36-37 'C' _opt))))))))))) + (Rule 40-47 'C = "C"' + (Rule_define 40-47 'C = "C"' _opt _opt + (RuleBody 44-47 '"C"' _opt + (NonemptyListOf 44-47 '"C"' + (TopLevelTerm 44-47 '"C"' + (Seq 44-47 '"C"' + (Iter 44-47 '"C"' + (Pred 44-47 '"C"' + (Lex 44-47 '"C"' + (Base 44-47 '"C"' Base_terminal)))))))))))) \ No newline at end of file diff --git a/golang/cli/tests/grammar_mixed_04.txtar b/golang/cli/tests/grammar_mixed_04.txtar new file mode 100644 index 00000000..650a0b2d --- /dev/null +++ b/golang/cli/tests/grammar_mixed_04.txtar @@ -0,0 +1,87 @@ +-- grammar.ohm -- +G { + Iter + = Pred "*" -- star + | Pred "+" -- plus + | Pred "?" -- opt + | Pred + Pred = "a" +} +-- file0.txt -- +a +-- file0.c_and_p -- +(Iter + (Pred (_terminal 'a' 0-1) + ) +) + +-- file1.txt -- +a* +-- file1.c_and_p -- +(Iter + (Iter_star + (Pred (_terminal 'a' 0-1) + ) (_terminal '*' 1-2) + ) +) + +-- grammar.n.l.S.v.t.sexpr -- +(Grammars 0-108 'G OC \n Iter\n = Pred "*" -- sta...' + (Grammar 0-108 'G OC \n Iter\n = Pred "*" -- sta...' _opt + (Rule 7-93 'Iter\n = Pred "*" -- star\n | ...' + (Rule_define 7-93 'Iter\n = Pred "*" -- star\n | ...' _opt _opt + (RuleBody 18-93 'Pred "*" -- star\n | Pred "+" --...' _opt + (NonemptyListOf 18-93 'Pred "*" -- star\n | Pred "+" --...' + (TopLevelTerm 18-36 'Pred "*" -- star\n' + (TopLevelTerm_inline 18-36 'Pred "*" -- star\n' + (Seq 18-26 'Pred "*"' + (Iter 18-22 'Pred' + (Pred 18-22 'Pred' + (Lex 18-22 'Pred' + (Base 18-22 'Pred' + (Base_application 18-22 'Pred' _opt))))) + (Iter 23-26 '"*"' + (Pred 23-26 '"*"' + (Lex 23-26 '"*"' + (Base 23-26 '"*"' Base_terminal))))))) + (TopLevelTerm 42-60 'Pred "+" -- plus\n' + (TopLevelTerm_inline 42-60 'Pred "+" -- plus\n' + (Seq 42-50 'Pred "+"' + (Iter 42-46 'Pred' + (Pred 42-46 'Pred' + (Lex 42-46 'Pred' + (Base 42-46 'Pred' + (Base_application 42-46 'Pred' _opt))))) + (Iter 47-50 '"+"' + (Pred 47-50 '"+"' + (Lex 47-50 '"+"' + (Base 47-50 '"+"' Base_terminal))))))) + (TopLevelTerm 66-83 'Pred "?" -- opt\n' + (TopLevelTerm_inline 66-83 'Pred "?" -- opt\n' + (Seq 66-74 'Pred "?"' + (Iter 66-70 'Pred' + (Pred 66-70 'Pred' + (Lex 66-70 'Pred' + (Base 66-70 'Pred' + (Base_application 66-70 'Pred' _opt))))) + (Iter 71-74 '"?"' + (Pred 71-74 '"?"' + (Lex 71-74 '"?"' + (Base 71-74 '"?"' Base_terminal))))))) + (TopLevelTerm 89-93 'Pred' + (Seq 89-93 'Pred' + (Iter 89-93 'Pred' + (Pred 89-93 'Pred' + (Lex 89-93 'Pred' + (Base 89-93 'Pred' + (Base_application 89-93 'Pred' _opt))))))))))) + (Rule 96-106 'Pred = "a"' + (Rule_define 96-106 'Pred = "a"' _opt _opt + (RuleBody 103-106 '"a"' _opt + (NonemptyListOf 103-106 '"a"' + (TopLevelTerm 103-106 '"a"' + (Seq 103-106 '"a"' + (Iter 103-106 '"a"' + (Pred 103-106 '"a"' + (Lex 103-106 '"a"' + (Base 103-106 '"a"' Base_terminal)))))))))))) \ No newline at end of file diff --git a/golang/cli/tests/grammar_mixed_05.txtar b/golang/cli/tests/grammar_mixed_05.txtar new file mode 100644 index 00000000..da9c3747 --- /dev/null +++ b/golang/cli/tests/grammar_mixed_05.txtar @@ -0,0 +1,186 @@ +-- grammar.ohm -- +G { + S = + | "B" C + | C "B" + C = "C" +} +-- file1.txt -- +B C +-- file1.c_and_p -- +(S (_terminal 'B' 0-1) + (C (_terminal 'C' 2-3) + ) +) +-- file2.txt -- +C B +-- file2.c_and_p -- +(S + (C (_terminal 'C' 0-1) + ) (_terminal 'B' 2-3) +) +-- grammar.sexpr -- +(Grammars + (_list + (Grammar + (ident + (name + (nameFirst + (letter + (upper (_terminal 'G' 0-1) + ) + ) + ) _list + ) + ) _opt (_terminal OC 2-3) + (_list + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'S' 7-8) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 9-10) + (RuleBody + (_opt (_terminal '|' 15-16) + ) + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 17-18) + (_list + (terminalChar (_terminal 'B' 18-19) + ) + ) (_terminal '"' 19-20) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'C' 21-22) + ) + ) + ) _list + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 27-28) + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'C' 29-30) + ) + ) + ) _list + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 31-32) + (_list + (terminalChar (_terminal 'B' 32-33) + ) + ) (_terminal '"' 33-34) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'C' 37-38) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 39-40) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 41-42) + (_list + (terminalChar (_terminal 'C' 42-43) + ) + ) (_terminal '"' 43-44) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) (_terminal CC 45-46) + ) + ) +) diff --git a/golang/cli/tests/grammar_mixed_06.txtar b/golang/cli/tests/grammar_mixed_06.txtar new file mode 100644 index 00000000..750d9123 --- /dev/null +++ b/golang/cli/tests/grammar_mixed_06.txtar @@ -0,0 +1,38 @@ +-- grammar.ohm -- +G { + escapeChar (an escape sequence) + = "\\\\" -- backslash + | "\\x" hexDigit hexDigit -- hexEscape +} + +-- grammar.n.l.S.v.t.sexpr -- +(Grammars 0-164 'G OC\n escapeChar OPan escape seque...' + (Grammar 0-164 'G OC\n escapeChar OPan escape seque...' _opt + (Rule 6-163 'escapeChar OPan escape sequenceCP\n ...' + (Rule_define 6-163 'escapeChar OPan escape sequenceCP\n ...' _opt _opt + (RuleBody 45-163 '"\\\\" ...' _opt + (NonemptyListOf 45-163 '"\\\\" ...' + (TopLevelTerm 45-101 '"\\\\" ...' + (TopLevelTerm_inline 45-101 '"\\\\" ...' + (Seq 45-51 '"\\\\"' + (Iter 45-51 '"\\\\"' + (Pred 45-51 '"\\\\"' + (Lex 45-51 '"\\\\"' + (Base 45-51 '"\\\\"' Base_terminal))))))) + (TopLevelTerm 107-163 '"\\x" hexDigit hexDigit ...' + (TopLevelTerm_inline 107-163 '"\\x" hexDigit hexDigit ...' + (Seq 107-130 '"\\x" hexDigit hexDigit' + (Iter 107-112 '"\\x"' + (Pred 107-112 '"\\x"' + (Lex 107-112 '"\\x"' + (Base 107-112 '"\\x"' Base_terminal)))) + (Iter 113-121 'hexDigit' + (Pred 113-121 'hexDigit' + (Lex 113-121 'hexDigit' + (Base 113-121 'hexDigit' + (Base_application 113-121 'hexDigit' _opt))))) + (Iter 122-130 'hexDigit' + (Pred 122-130 'hexDigit' + (Lex 122-130 'hexDigit' + (Base 122-130 'hexDigit' + (Base_application 122-130 'hexDigit' _opt)))))))))))))) \ No newline at end of file diff --git a/golang/cli/tests/grammar_nel_01.txtar b/golang/cli/tests/grammar_nel_01.txtar new file mode 100644 index 00000000..8492f4a6 --- /dev/null +++ b/golang/cli/tests/grammar_nel_01.txtar @@ -0,0 +1,83 @@ +-- grammar.ohm -- +G { S = NonemptyListOf<"a", ","> } +-- file1.txt -- +a,a,a +-- file1.c_and_p -- +(S + (NonemptyListOf<"a",","> (_terminal 'a' 0-1) + (_list (_terminal ',' 1-2) (_terminal 'a' 2-3) (_terminal ',' 3-4) (_terminal 'a' 4-5) + ) + ) +) +-- file1.l.c_and_p -- +(S + (NonemptyListOf<"a",","> (_terminal 'a' 0-1) (_terminal ',' 1-2) (_terminal 'a' 2-3) (_terminal ',' 3-4) (_terminal 'a' 4-5) + ) +) +-- grammar.S.t.sexpr -- +(Grammars + (_list + (Grammar _opt + (_list + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (_list + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/golang/cli/tests/grammar_nel_02.txtar b/golang/cli/tests/grammar_nel_02.txtar new file mode 100644 index 00000000..697e47d7 --- /dev/null +++ b/golang/cli/tests/grammar_nel_02.txtar @@ -0,0 +1,122 @@ +-- grammar.ohm -- +G { + S = NonemptyListOf + a = "a" +} +-- file1.txt -- +a,a,a +-- file1.c_and_p -- +(S + (NonemptyListOf + (a (_terminal 'a' 0-1) + ) + (_list (_terminal ',' 1-2) + (a (_terminal 'a' 2-3) + ) (_terminal ',' 3-4) + (a (_terminal 'a' 4-5) + ) + ) + ) +) +-- file1.l.c_and_p -- +(S + (NonemptyListOf + (a (_terminal 'a' 0-1) + ) (_terminal ',' 1-2) + (a (_terminal 'a' 2-3) + ) (_terminal ',' 3-4) + (a (_terminal 'a' 4-5) + ) + ) +) +-- grammar.S.t.sexpr -- +(Grammars + (_list + (Grammar _opt + (_list + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (_list + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) + ) + ) +) diff --git a/golang/cli/tests/grammar_nel_03.txtar b/golang/cli/tests/grammar_nel_03.txtar new file mode 100644 index 00000000..7f181721 --- /dev/null +++ b/golang/cli/tests/grammar_nel_03.txtar @@ -0,0 +1,314 @@ +-- grammar.ohm -- +G { + S = NonemptyListOf -- A + a = "a" +} +-- file1.txt -- +a,a,a +-- file1.c_and_p -- +(S + (S_A + (NonemptyListOf + (a (_terminal 'a' 0-1) + ) + (_list (_terminal ',' 1-2) + (a (_terminal 'a' 2-3) + ) (_terminal ',' 3-4) + (a (_terminal 'a' 4-5) + ) + ) + ) + ) +) +-- file1.l.c_and_p -- +(S + (S_A + (NonemptyListOf + (a (_terminal 'a' 0-1) + ) (_terminal ',' 1-2) + (a (_terminal 'a' 2-3) + ) (_terminal ',' 3-4) + (a (_terminal 'a' 4-5) + ) + ) + ) +) +-- grammar.sexpr -- +(Grammars + (_list + (Grammar + (ident + (name + (nameFirst + (letter + (upper (_terminal 'G' 0-1) + ) + ) + ) _list + ) + ) _opt (_terminal OC 2-3) + (_list + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'S' 7-8) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 9-10) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 11-12) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 12-13) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 13-14) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 14-15) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 15-16) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 16-17) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 17-18) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 18-19) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'L' 19-20) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'i' 20-21) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 21-22) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 22-23) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'O' 23-24) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'f' 24-25) + ) + ) + ) + ) + ) + ) + ) + (_opt + (Params (_terminal '<' 25-26) + (ListOf + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 26-27) + ) + ) + ) _list + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal ',' 27-28) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 29-30) + (_list + (terminalChar (_terminal ',' 30-31) + ) + ) (_terminal '"' 31-32) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '>' 32-33) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 34-36) + (_list + (space (_terminal ' ' 36-37) + ) + ) + (name + (nameFirst + (letter + (upper (_terminal 'A' 37-38) + ) + ) + ) _list + ) _list (_terminal NL 38-39) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 41-42) + ) + ) + ) _list + ) + ) _opt _opt (_terminal '=' 43-44) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 45-46) + (_list + (terminalChar (_terminal 'a' 46-47) + ) + ) (_terminal '"' 47-48) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) (_terminal CC 49-50) + ) + ) +) diff --git a/golang/cli/tests/grammar_nel_04.txtar b/golang/cli/tests/grammar_nel_04.txtar new file mode 100644 index 00000000..9a45a83e --- /dev/null +++ b/golang/cli/tests/grammar_nel_04.txtar @@ -0,0 +1,32 @@ +-- grammar.ohm -- +G { + S = ListOf + a = "a" +} +-- file1.txt -- +a a +-- file1.c_and_p -- +(S + (ListOf + (NonemptyListOf + (_list + (a (_terminal 'a' 0-1) + ) + (a (_terminal 'a' 2-3) + ) + ) _list + ) + ) +) + +-- file2.txt -- +,,, +-- file2.c_and_p -- +(S + (ListOf + (NonemptyListOf _list + (_list (_terminal ',' 0-1) _list (_terminal ',' 1-2) _list (_terminal ',' 2-3) _list + ) + ) + ) +) \ No newline at end of file diff --git a/golang/cli/tests/ohm-grammar.txtar b/golang/cli/tests/ohm-grammar.txtar new file mode 100644 index 00000000..f34d7436 --- /dev/null +++ b/golang/cli/tests/ohm-grammar.txtar @@ -0,0 +1,6900 @@ +-- @../../packages/ohm-js/src/ohm-grammar.ohm -- +relative to golang/cli directory + +-- file.txt -- +RuleAst { + Grammar = name #"\n" Rule* + Rule = name ruleDescr? rulecase "{" RuleDetails* "}" + RuleDetails = name Nodetype #("\n"|";") + Nodetype = + | #("node" (" "|"\t")*) -- node + | #("rule" (" "|"\t")+) name -- rule + | #("term" (" "|"\t")*) -- term + | #("list" (" "|"\t")+) Nodetype -- list + | #("opt" (" "|"\t")+) Nodetype -- opt + | #("hor" (" "|"\t")+) hor_id "<" ListOf ">" -- hor + + rulecase = + | "define" ~(alnum) + | "override" ~(alnum) + | "extend" ~(alnum) + ruleDescr = "(" ruleDescrText ")" + ruleDescrText = (~")" any)* + name = alnum+ + hor_id = alnum+ +} +-- file.S.v.c_and_p -- +(Grammars 0-661 'RuleAst OC\n Grammar = name #"\n...' + (_list 0-661 'RuleAst OC\n Grammar = name #"\n...' + (Grammar 0-661 'RuleAst OC\n Grammar = name #"\n...' _opt (_terminal OC 8-9) + (_list 9-659 '\n Grammar = name #"\n" Rule*\n ...' + (Rule 12-42 'Grammar = name #"\n" Rule*' + (Rule_define 12-42 'Grammar = name #"\n" Rule*' _opt _opt (_terminal '=' 20-21) + (RuleBody 26-42 'name #"\n" Rule*' _opt + (NonemptyListOf 26-42 'name #"\n" Rule*' + (TopLevelTerm 26-42 'name #"\n" Rule*' + (Seq 26-42 'name #"\n" Rule*' + (_list 26-42 'name #"\n" Rule*' + (Iter 26-30 'name' + (Pred 26-30 'name' + (Lex 26-30 'name' + (Base 26-30 'name' + (Base_application 26-30 'name' _opt + ) + ) + ) + ) + ) + (Iter 31-36 '#"\n"' + (Pred 31-36 '#"\n"' + (Lex 31-36 '#"\n"' + (Lex_lex 31-36 '#"\n"' (_terminal '#' 31-32) + (Base 32-36 '"\n"' Base_terminal + ) + ) + ) + ) + ) + (Iter 37-42 'Rule*' + (Iter_star 37-42 'Rule*' + (Pred 37-41 'Rule' + (Lex 37-41 'Rule' + (Base 37-41 'Rule' + (Base_application 37-41 'Rule' _opt + ) + ) + ) + ) (_terminal '*' 41-42) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 45-104 'Rule = name ruleDescr? rulecas...' + (Rule_define 45-104 'Rule = name ruleDescr? rulecas...' _opt _opt (_terminal '=' 50-51) + (RuleBody 59-104 'name ruleDescr? rulecase "OC" RuleDet...' _opt + (NonemptyListOf 59-104 'name ruleDescr? rulecase "OC" RuleDet...' + (TopLevelTerm 59-104 'name ruleDescr? rulecase "OC" RuleDet...' + (Seq 59-104 'name ruleDescr? rulecase "OC" RuleDet...' + (_list 59-104 'name ruleDescr? rulecase "OC" RuleDet...' + (Iter 59-63 'name' + (Pred 59-63 'name' + (Lex 59-63 'name' + (Base 59-63 'name' + (Base_application 59-63 'name' _opt + ) + ) + ) + ) + ) + (Iter 64-74 'ruleDescr?' + (Iter_opt 64-74 'ruleDescr?' + (Pred 64-73 'ruleDescr' + (Lex 64-73 'ruleDescr' + (Base 64-73 'ruleDescr' + (Base_application 64-73 'ruleDescr' _opt + ) + ) + ) + ) (_terminal '?' 73-74) + ) + ) + (Iter 75-83 'rulecase' + (Pred 75-83 'rulecase' + (Lex 75-83 'rulecase' + (Base 75-83 'rulecase' + (Base_application 75-83 'rulecase' _opt + ) + ) + ) + ) + ) + (Iter 84-87 '"OC"' + (Pred 84-87 '"OC"' + (Lex 84-87 '"OC"' + (Base 84-87 '"OC"' Base_terminal + ) + ) + ) + ) + (Iter 88-100 'RuleDetails*' + (Iter_star 88-100 'RuleDetails*' + (Pred 88-99 'RuleDetails' + (Lex 88-99 'RuleDetails' + (Base 88-99 'RuleDetails' + (Base_application 88-99 'RuleDetails' _opt + ) + ) + ) + ) (_terminal '*' 99-100) + ) + ) + (Iter 101-104 '"CC"' + (Pred 101-104 '"CC"' + (Lex 101-104 '"CC"' + (Base 101-104 '"CC"' Base_terminal + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 107-146 'RuleDetails = name Nodetype #OP"\n"|"...' + (Rule_define 107-146 'RuleDetails = name Nodetype #OP"\n"|"...' _opt _opt (_terminal '=' 119-120) + (RuleBody 121-146 'name Nodetype #OP"\n"|";"CP' _opt + (NonemptyListOf 121-146 'name Nodetype #OP"\n"|";"CP' + (TopLevelTerm 121-146 'name Nodetype #OP"\n"|";"CP' + (Seq 121-146 'name Nodetype #OP"\n"|";"CP' + (_list 121-146 'name Nodetype #OP"\n"|";"CP' + (Iter 121-125 'name' + (Pred 121-125 'name' + (Lex 121-125 'name' + (Base 121-125 'name' + (Base_application 121-125 'name' _opt + ) + ) + ) + ) + ) + (Iter 126-134 'Nodetype' + (Pred 126-134 'Nodetype' + (Lex 126-134 'Nodetype' + (Base 126-134 'Nodetype' + (Base_application 126-134 'Nodetype' _opt + ) + ) + ) + ) + ) + (Iter 135-146 '#OP"\n"|";"CP' + (Pred 135-146 '#OP"\n"|";"CP' + (Lex 135-146 '#OP"\n"|";"CP' + (Lex_lex 135-146 '#OP"\n"|";"CP' (_terminal '#' 135-136) + (Base 136-146 'OP"\n"|";"CP' + (Base_paren 136-146 'OP"\n"|";"CP' (_terminal OP 136-137) + (Alt 137-145 '"\n"|";"' + (NonemptyListOf 137-145 '"\n"|";"' + (Seq 137-141 '"\n"' + (_list 137-141 '"\n"' + (Iter 137-141 '"\n"' + (Pred 137-141 '"\n"' + (Lex 137-141 '"\n"' + (Base 137-141 '"\n"' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 141-145 '|";"' (_terminal '|' 141-142) + (Seq 142-145 '";"' + (_list 142-145 '";"' + (Iter 142-145 '";"' + (Pred 142-145 '";"' + (Lex 142-145 '";"' + (Base 142-145 '";"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 145-146) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 149-471 'Nodetype =\n | #OP"node" OP" "|"\t...' + (Rule_define 149-471 'Nodetype =\n | #OP"node" OP" "|"\t...' _opt _opt (_terminal '=' 158-159) + (RuleBody 164-471 '| #OP"node" OP" "|"\t"CP*CP ...' + (_opt 164-165 '|' (_terminal '|' 164-165) + ) + (NonemptyListOf 166-471 '#OP"node" OP" "|"\t"CP*CP ...' + (TopLevelTerm 166-208 '#OP"node" OP" "|"\t"CP*CP ...' + (TopLevelTerm_inline 166-208 '#OP"node" OP" "|"\t"CP*CP ...' + (Seq 166-187 '#OP"node" OP" "|"\t"CP*CP' + (_list 166-187 '#OP"node" OP" "|"\t"CP*CP' + (Iter 166-187 '#OP"node" OP" "|"\t"CP*CP' + (Pred 166-187 '#OP"node" OP" "|"\t"CP*CP' + (Lex 166-187 '#OP"node" OP" "|"\t"CP*CP' + (Lex_lex 166-187 '#OP"node" OP" "|"\t"CP*CP' (_terminal '#' 166-167) + (Base 167-187 'OP"node" OP" "|"\t"CP*CP' + (Base_paren 167-187 'OP"node" OP" "|"\t"CP*CP' (_terminal OP 167-168) + (Alt 168-186 '"node" OP" "|"\t"CP*' + (NonemptyListOf 168-186 '"node" OP" "|"\t"CP*' + (Seq 168-186 '"node" OP" "|"\t"CP*' + (_list 168-186 '"node" OP" "|"\t"CP*' + (Iter 168-174 '"node"' + (Pred 168-174 '"node"' + (Lex 168-174 '"node"' + (Base 168-174 '"node"' Base_terminal + ) + ) + ) + ) + (Iter 175-186 'OP" "|"\t"CP*' + (Iter_star 175-186 'OP" "|"\t"CP*' + (Pred 175-185 'OP" "|"\t"CP' + (Lex 175-185 'OP" "|"\t"CP' + (Base 175-185 'OP" "|"\t"CP' + (Base_paren 175-185 'OP" "|"\t"CP' (_terminal OP 175-176) + (Alt 176-184 '" "|"\t"' + (NonemptyListOf 176-184 '" "|"\t"' + (Seq 176-179 '" "' + (_list 176-179 '" "' + (Iter 176-179 '" "' + (Pred 176-179 '" "' + (Lex 176-179 '" "' + (Base 176-179 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 179-184 '|"\t"' (_terminal '|' 179-180) + (Seq 180-184 '"\t"' + (_list 180-184 '"\t"' + (Iter 180-184 '"\t"' + (Pred 180-184 '"\t"' + (Lex 180-184 '"\t"' + (Base 180-184 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 184-185) + ) + ) + ) + ) (_terminal '*' 185-186) + ) + ) + ) + ) _list + ) + ) (_terminal CP 186-187) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (_list 208-471 ' | #OP"rule" OP" "|"\t"CP+CP name...' (_terminal '|' 212-213) + (TopLevelTerm 214-255 '#OP"rule" OP" "|"\t"CP+CP name ...' + (TopLevelTerm_inline 214-255 '#OP"rule" OP" "|"\t"CP+CP name ...' + (Seq 214-241 '#OP"rule" OP" "|"\t"CP+CP name' + (_list 214-241 '#OP"rule" OP" "|"\t"CP+CP name' + (Iter 214-235 '#OP"rule" OP" "|"\t"CP+CP' + (Pred 214-235 '#OP"rule" OP" "|"\t"CP+CP' + (Lex 214-235 '#OP"rule" OP" "|"\t"CP+CP' + (Lex_lex 214-235 '#OP"rule" OP" "|"\t"CP+CP' (_terminal '#' 214-215) + (Base 215-235 'OP"rule" OP" "|"\t"CP+CP' + (Base_paren 215-235 'OP"rule" OP" "|"\t"CP+CP' (_terminal OP 215-216) + (Alt 216-234 '"rule" OP" "|"\t"CP+' + (NonemptyListOf 216-234 '"rule" OP" "|"\t"CP+' + (Seq 216-234 '"rule" OP" "|"\t"CP+' + (_list 216-234 '"rule" OP" "|"\t"CP+' + (Iter 216-222 '"rule"' + (Pred 216-222 '"rule"' + (Lex 216-222 '"rule"' + (Base 216-222 '"rule"' Base_terminal + ) + ) + ) + ) + (Iter 223-234 'OP" "|"\t"CP+' + (Iter_plus 223-234 'OP" "|"\t"CP+' + (Pred 223-233 'OP" "|"\t"CP' + (Lex 223-233 'OP" "|"\t"CP' + (Base 223-233 'OP" "|"\t"CP' + (Base_paren 223-233 'OP" "|"\t"CP' (_terminal OP 223-224) + (Alt 224-232 '" "|"\t"' + (NonemptyListOf 224-232 '" "|"\t"' + (Seq 224-227 '" "' + (_list 224-227 '" "' + (Iter 224-227 '" "' + (Pred 224-227 '" "' + (Lex 224-227 '" "' + (Base 224-227 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 227-232 '|"\t"' (_terminal '|' 227-228) + (Seq 228-232 '"\t"' + (_list 228-232 '"\t"' + (Iter 228-232 '"\t"' + (Pred 228-232 '"\t"' + (Lex 228-232 '"\t"' + (Base 228-232 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 232-233) + ) + ) + ) + ) (_terminal '+' 233-234) + ) + ) + ) + ) _list + ) + ) (_terminal CP 234-235) + ) + ) + ) + ) + ) + ) + (Iter 237-241 'name' + (Pred 237-241 'name' + (Lex 237-241 'name' + (Base 237-241 'name' + (Base_application 237-241 'name' _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 259-260) + (TopLevelTerm 261-303 '#OP"term" OP" "|"\t"CP*CP ...' + (TopLevelTerm_inline 261-303 '#OP"term" OP" "|"\t"CP*CP ...' + (Seq 261-282 '#OP"term" OP" "|"\t"CP*CP' + (_list 261-282 '#OP"term" OP" "|"\t"CP*CP' + (Iter 261-282 '#OP"term" OP" "|"\t"CP*CP' + (Pred 261-282 '#OP"term" OP" "|"\t"CP*CP' + (Lex 261-282 '#OP"term" OP" "|"\t"CP*CP' + (Lex_lex 261-282 '#OP"term" OP" "|"\t"CP*CP' (_terminal '#' 261-262) + (Base 262-282 'OP"term" OP" "|"\t"CP*CP' + (Base_paren 262-282 'OP"term" OP" "|"\t"CP*CP' (_terminal OP 262-263) + (Alt 263-281 '"term" OP" "|"\t"CP*' + (NonemptyListOf 263-281 '"term" OP" "|"\t"CP*' + (Seq 263-281 '"term" OP" "|"\t"CP*' + (_list 263-281 '"term" OP" "|"\t"CP*' + (Iter 263-269 '"term"' + (Pred 263-269 '"term"' + (Lex 263-269 '"term"' + (Base 263-269 '"term"' Base_terminal + ) + ) + ) + ) + (Iter 270-281 'OP" "|"\t"CP*' + (Iter_star 270-281 'OP" "|"\t"CP*' + (Pred 270-280 'OP" "|"\t"CP' + (Lex 270-280 'OP" "|"\t"CP' + (Base 270-280 'OP" "|"\t"CP' + (Base_paren 270-280 'OP" "|"\t"CP' (_terminal OP 270-271) + (Alt 271-279 '" "|"\t"' + (NonemptyListOf 271-279 '" "|"\t"' + (Seq 271-274 '" "' + (_list 271-274 '" "' + (Iter 271-274 '" "' + (Pred 271-274 '" "' + (Lex 271-274 '" "' + (Base 271-274 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 274-279 '|"\t"' (_terminal '|' 274-275) + (Seq 275-279 '"\t"' + (_list 275-279 '"\t"' + (Iter 275-279 '"\t"' + (Pred 275-279 '"\t"' + (Lex 275-279 '"\t"' + (Base 275-279 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 279-280) + ) + ) + ) + ) (_terminal '*' 280-281) + ) + ) + ) + ) _list + ) + ) (_terminal CP 281-282) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 307-308) + (TopLevelTerm 309-351 '#OP"list" OP" "|"\t"CP+CP Nodetype ...' + (TopLevelTerm_inline 309-351 '#OP"list" OP" "|"\t"CP+CP Nodetype ...' + (Seq 309-340 '#OP"list" OP" "|"\t"CP+CP Nodetype' + (_list 309-340 '#OP"list" OP" "|"\t"CP+CP Nodetype' + (Iter 309-330 '#OP"list" OP" "|"\t"CP+CP' + (Pred 309-330 '#OP"list" OP" "|"\t"CP+CP' + (Lex 309-330 '#OP"list" OP" "|"\t"CP+CP' + (Lex_lex 309-330 '#OP"list" OP" "|"\t"CP+CP' (_terminal '#' 309-310) + (Base 310-330 'OP"list" OP" "|"\t"CP+CP' + (Base_paren 310-330 'OP"list" OP" "|"\t"CP+CP' (_terminal OP 310-311) + (Alt 311-329 '"list" OP" "|"\t"CP+' + (NonemptyListOf 311-329 '"list" OP" "|"\t"CP+' + (Seq 311-329 '"list" OP" "|"\t"CP+' + (_list 311-329 '"list" OP" "|"\t"CP+' + (Iter 311-317 '"list"' + (Pred 311-317 '"list"' + (Lex 311-317 '"list"' + (Base 311-317 '"list"' Base_terminal + ) + ) + ) + ) + (Iter 318-329 'OP" "|"\t"CP+' + (Iter_plus 318-329 'OP" "|"\t"CP+' + (Pred 318-328 'OP" "|"\t"CP' + (Lex 318-328 'OP" "|"\t"CP' + (Base 318-328 'OP" "|"\t"CP' + (Base_paren 318-328 'OP" "|"\t"CP' (_terminal OP 318-319) + (Alt 319-327 '" "|"\t"' + (NonemptyListOf 319-327 '" "|"\t"' + (Seq 319-322 '" "' + (_list 319-322 '" "' + (Iter 319-322 '" "' + (Pred 319-322 '" "' + (Lex 319-322 '" "' + (Base 319-322 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 322-327 '|"\t"' (_terminal '|' 322-323) + (Seq 323-327 '"\t"' + (_list 323-327 '"\t"' + (Iter 323-327 '"\t"' + (Pred 323-327 '"\t"' + (Lex 323-327 '"\t"' + (Base 323-327 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 327-328) + ) + ) + ) + ) (_terminal '+' 328-329) + ) + ) + ) + ) _list + ) + ) (_terminal CP 329-330) + ) + ) + ) + ) + ) + ) + (Iter 332-340 'Nodetype' + (Pred 332-340 'Nodetype' + (Lex 332-340 'Nodetype' + (Base 332-340 'Nodetype' + (Base_application 332-340 'Nodetype' _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 355-356) + (TopLevelTerm 357-398 '#OP"opt" OP" "|"\t"CP+CP Nodetype ...' + (TopLevelTerm_inline 357-398 '#OP"opt" OP" "|"\t"CP+CP Nodetype ...' + (Seq 357-388 '#OP"opt" OP" "|"\t"CP+CP Nodetype' + (_list 357-388 '#OP"opt" OP" "|"\t"CP+CP Nodetype' + (Iter 357-378 '#OP"opt" OP" "|"\t"CP+CP' + (Pred 357-378 '#OP"opt" OP" "|"\t"CP+CP' + (Lex 357-378 '#OP"opt" OP" "|"\t"CP+CP' + (Lex_lex 357-378 '#OP"opt" OP" "|"\t"CP+CP' (_terminal '#' 357-358) + (Base 358-378 'OP"opt" OP" "|"\t"CP+CP' + (Base_paren 358-378 'OP"opt" OP" "|"\t"CP+CP' (_terminal OP 358-359) + (Alt 359-377 '"opt" OP" "|"\t"CP+' + (NonemptyListOf 359-377 '"opt" OP" "|"\t"CP+' + (Seq 359-377 '"opt" OP" "|"\t"CP+' + (_list 359-377 '"opt" OP" "|"\t"CP+' + (Iter 359-364 '"opt"' + (Pred 359-364 '"opt"' + (Lex 359-364 '"opt"' + (Base 359-364 '"opt"' Base_terminal + ) + ) + ) + ) + (Iter 366-377 'OP" "|"\t"CP+' + (Iter_plus 366-377 'OP" "|"\t"CP+' + (Pred 366-376 'OP" "|"\t"CP' + (Lex 366-376 'OP" "|"\t"CP' + (Base 366-376 'OP" "|"\t"CP' + (Base_paren 366-376 'OP" "|"\t"CP' (_terminal OP 366-367) + (Alt 367-375 '" "|"\t"' + (NonemptyListOf 367-375 '" "|"\t"' + (Seq 367-370 '" "' + (_list 367-370 '" "' + (Iter 367-370 '" "' + (Pred 367-370 '" "' + (Lex 367-370 '" "' + (Base 367-370 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 370-375 '|"\t"' (_terminal '|' 370-371) + (Seq 371-375 '"\t"' + (_list 371-375 '"\t"' + (Iter 371-375 '"\t"' + (Pred 371-375 '"\t"' + (Lex 371-375 '"\t"' + (Base 371-375 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 375-376) + ) + ) + ) + ) (_terminal '+' 376-377) + ) + ) + ) + ) _list + ) + ) (_terminal CP 377-378) + ) + ) + ) + ) + ) + ) + (Iter 380-388 'Nodetype' + (Pred 380-388 'Nodetype' + (Lex 380-388 'Nodetype' + (Base 380-388 'Nodetype' + (Base_application 380-388 'Nodetype' _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 402-403) + (TopLevelTerm 404-471 '#OP"hor" OP" "|"\t"CP+CP hor_id "<"...' + (TopLevelTerm_inline 404-471 '#OP"hor" OP" "|"\t"CP+CP hor_id "<"...' + (Seq 404-463 '#OP"hor" OP" "|"\t"CP+CP hor_id "<"...' + (_list 404-463 '#OP"hor" OP" "|"\t"CP+CP hor_id "<"...' + (Iter 404-425 '#OP"hor" OP" "|"\t"CP+CP' + (Pred 404-425 '#OP"hor" OP" "|"\t"CP+CP' + (Lex 404-425 '#OP"hor" OP" "|"\t"CP+CP' + (Lex_lex 404-425 '#OP"hor" OP" "|"\t"CP+CP' (_terminal '#' 404-405) + (Base 405-425 'OP"hor" OP" "|"\t"CP+CP' + (Base_paren 405-425 'OP"hor" OP" "|"\t"CP+CP' (_terminal OP 405-406) + (Alt 406-424 '"hor" OP" "|"\t"CP+' + (NonemptyListOf 406-424 '"hor" OP" "|"\t"CP+' + (Seq 406-424 '"hor" OP" "|"\t"CP+' + (_list 406-424 '"hor" OP" "|"\t"CP+' + (Iter 406-411 '"hor"' + (Pred 406-411 '"hor"' + (Lex 406-411 '"hor"' + (Base 406-411 '"hor"' Base_terminal + ) + ) + ) + ) + (Iter 413-424 'OP" "|"\t"CP+' + (Iter_plus 413-424 'OP" "|"\t"CP+' + (Pred 413-423 'OP" "|"\t"CP' + (Lex 413-423 'OP" "|"\t"CP' + (Base 413-423 'OP" "|"\t"CP' + (Base_paren 413-423 'OP" "|"\t"CP' (_terminal OP 413-414) + (Alt 414-422 '" "|"\t"' + (NonemptyListOf 414-422 '" "|"\t"' + (Seq 414-417 '" "' + (_list 414-417 '" "' + (Iter 414-417 '" "' + (Pred 414-417 '" "' + (Lex 414-417 '" "' + (Base 414-417 '" "' Base_terminal + ) + ) + ) + ) + ) + ) + (_list 417-422 '|"\t"' (_terminal '|' 417-418) + (Seq 418-422 '"\t"' + (_list 418-422 '"\t"' + (Iter 418-422 '"\t"' + (Pred 418-422 '"\t"' + (Lex 418-422 '"\t"' + (Base 418-422 '"\t"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 422-423) + ) + ) + ) + ) (_terminal '+' 423-424) + ) + ) + ) + ) _list + ) + ) (_terminal CP 424-425) + ) + ) + ) + ) + ) + ) + (Iter 427-433 'hor_id' + (Pred 427-433 'hor_id' + (Lex 427-433 'hor_id' + (Base 427-433 'hor_id' + (Base_application 427-433 'hor_id' _opt + ) + ) + ) + ) + ) + (Iter 434-437 '"<"' + (Pred 434-437 '"<"' + (Lex 434-437 '"<"' + (Base 434-437 '"<"' Base_terminal + ) + ) + ) + ) + (Iter 438-459 'ListOf' + (Pred 438-459 'ListOf' + (Lex 438-459 'ListOf' + (Base 438-459 'ListOf' + (Base_application 438-459 'ListOf' + (_opt 444-459 '' + (Params 444-459 '' (_terminal '<' 444-445) + (ListOf 445-458 'Nodetype, ","' + (NonemptyListOf 445-458 'Nodetype, ","' + (Seq 445-453 'Nodetype' + (_list 445-453 'Nodetype' + (Iter 445-453 'Nodetype' + (Pred 445-453 'Nodetype' + (Lex 445-453 'Nodetype' + (Base 445-453 'Nodetype' + (Base_application 445-453 'Nodetype' _opt + ) + ) + ) + ) + ) + ) + ) + (_list 453-458 ', ","' (_terminal ',' 453-454) + (Seq 455-458 '","' + (_list 455-458 '","' + (Iter 455-458 '","' + (Pred 455-458 '","' + (Lex 455-458 '","' + (Base 455-458 '","' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '>' 458-459) + ) + ) + ) + ) + ) + ) + ) + (Iter 460-463 '">"' + (Pred 460-463 '">"' + (Lex 460-463 '">"' + (Base 460-463 '">"' Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule 474-558 'rulecase =\n | "define" ~OPalnumCP...' + (Rule_define 474-558 'rulecase =\n | "define" ~OPalnumCP...' _opt _opt (_terminal '=' 483-484) + (RuleBody 489-558 '| "define" ~OPalnumCP\n | "overrid...' + (_opt 489-490 '|' (_terminal '|' 489-490) + ) + (NonemptyListOf 491-558 '"define" ~OPalnumCP\n | "override"...' + (TopLevelTerm 491-508 '"define" ~OPalnumCP' + (Seq 491-508 '"define" ~OPalnumCP' + (_list 491-508 '"define" ~OPalnumCP' + (Iter 491-499 '"define"' + (Pred 491-499 '"define"' + (Lex 491-499 '"define"' + (Base 491-499 '"define"' Base_terminal + ) + ) + ) + ) + (Iter 500-508 '~OPalnumCP' + (Pred 500-508 '~OPalnumCP' + (Pred_not 500-508 '~OPalnumCP' (_terminal '~' 500-501) + (Lex 501-508 'OPalnumCP' + (Base 501-508 'OPalnumCP' + (Base_paren 501-508 'OPalnumCP' (_terminal OP 501-502) + (Alt 502-507 'alnum' + (NonemptyListOf 502-507 'alnum' + (Seq 502-507 'alnum' + (_list 502-507 'alnum' + (Iter 502-507 'alnum' + (Pred 502-507 'alnum' + (Lex 502-507 'alnum' + (Base 502-507 'alnum' + (Base_application 502-507 'alnum' _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 507-508) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (_list 508-558 '\n | "override" ~OPalnumCP\n | ...' (_terminal '|' 513-514) + (TopLevelTerm 515-534 '"override" ~OPalnumCP' + (Seq 515-534 '"override" ~OPalnumCP' + (_list 515-534 '"override" ~OPalnumCP' + (Iter 515-525 '"override"' + (Pred 515-525 '"override"' + (Lex 515-525 '"override"' + (Base 515-525 '"override"' Base_terminal + ) + ) + ) + ) + (Iter 526-534 '~OPalnumCP' + (Pred 526-534 '~OPalnumCP' + (Pred_not 526-534 '~OPalnumCP' (_terminal '~' 526-527) + (Lex 527-534 'OPalnumCP' + (Base 527-534 'OPalnumCP' + (Base_paren 527-534 'OPalnumCP' (_terminal OP 527-528) + (Alt 528-533 'alnum' + (NonemptyListOf 528-533 'alnum' + (Seq 528-533 'alnum' + (_list 528-533 'alnum' + (Iter 528-533 'alnum' + (Pred 528-533 'alnum' + (Lex 528-533 'alnum' + (Base 528-533 'alnum' + (Base_application 528-533 'alnum' _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 533-534) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 539-540) + (TopLevelTerm 541-558 '"extend" ~OPalnumCP' + (Seq 541-558 '"extend" ~OPalnumCP' + (_list 541-558 '"extend" ~OPalnumCP' + (Iter 541-549 '"extend"' + (Pred 541-549 '"extend"' + (Lex 541-549 '"extend"' + (Base 541-549 '"extend"' Base_terminal + ) + ) + ) + ) + (Iter 550-558 '~OPalnumCP' + (Pred 550-558 '~OPalnumCP' + (Pred_not 550-558 '~OPalnumCP' (_terminal '~' 550-551) + (Lex 551-558 'OPalnumCP' + (Base 551-558 'OPalnumCP' + (Base_paren 551-558 'OPalnumCP' (_terminal OP 551-552) + (Alt 552-557 'alnum' + (NonemptyListOf 552-557 'alnum' + (Seq 552-557 'alnum' + (_list 552-557 'alnum' + (Iter 552-557 'alnum' + (Pred 552-557 'alnum' + (Lex 552-557 'alnum' + (Base 552-557 'alnum' + (Base_application 552-557 'alnum' _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 557-558) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule 561-595 'ruleDescr = "OP" ruleDescrText "CP"' + (Rule_define 561-595 'ruleDescr = "OP" ruleDescrText "CP"' _opt _opt (_terminal '=' 572-573) + (RuleBody 574-595 '"OP" ruleDescrText "CP"' _opt + (NonemptyListOf 574-595 '"OP" ruleDescrText "CP"' + (TopLevelTerm 574-595 '"OP" ruleDescrText "CP"' + (Seq 574-595 '"OP" ruleDescrText "CP"' + (_list 574-595 '"OP" ruleDescrText "CP"' + (Iter 574-577 '"OP"' + (Pred 574-577 '"OP"' + (Lex 574-577 '"OP"' + (Base 574-577 '"OP"' Base_terminal + ) + ) + ) + ) + (Iter 578-591 'ruleDescrText' + (Pred 578-591 'ruleDescrText' + (Lex 578-591 'ruleDescrText' + (Base 578-591 'ruleDescrText' + (Base_application 578-591 'ruleDescrText' _opt + ) + ) + ) + ) + ) + (Iter 592-595 '"CP"' + (Pred 592-595 '"CP"' + (Lex 592-595 '"CP"' + (Base 592-595 '"CP"' Base_terminal + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 598-625 'ruleDescrText = OP~"CP" anyCP*' + (Rule_define 598-625 'ruleDescrText = OP~"CP" anyCP*' _opt _opt (_terminal '=' 612-613) + (RuleBody 614-625 'OP~"CP" anyCP*' _opt + (NonemptyListOf 614-625 'OP~"CP" anyCP*' + (TopLevelTerm 614-625 'OP~"CP" anyCP*' + (Seq 614-625 'OP~"CP" anyCP*' + (_list 614-625 'OP~"CP" anyCP*' + (Iter 614-625 'OP~"CP" anyCP*' + (Iter_star 614-625 'OP~"CP" anyCP*' + (Pred 614-624 'OP~"CP" anyCP' + (Lex 614-624 'OP~"CP" anyCP' + (Base 614-624 'OP~"CP" anyCP' + (Base_paren 614-624 'OP~"CP" anyCP' (_terminal OP 614-615) + (Alt 615-623 '~"CP" any' + (NonemptyListOf 615-623 '~"CP" any' + (Seq 615-623 '~"CP" any' + (_list 615-623 '~"CP" any' + (Iter 615-619 '~"CP"' + (Pred 615-619 '~"CP"' + (Pred_not 615-619 '~"CP"' (_terminal '~' 615-616) + (Lex 616-619 '"CP"' + (Base 616-619 '"CP"' Base_terminal + ) + ) + ) + ) + ) + (Iter 620-623 'any' + (Pred 620-623 'any' + (Lex 620-623 'any' + (Base 620-623 'any' + (Base_application 620-623 'any' _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 623-624) + ) + ) + ) + ) (_terminal '*' 624-625) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 628-641 'name = alnum+' + (Rule_define 628-641 'name = alnum+' _opt _opt (_terminal '=' 633-634) + (RuleBody 635-641 'alnum+' _opt + (NonemptyListOf 635-641 'alnum+' + (TopLevelTerm 635-641 'alnum+' + (Seq 635-641 'alnum+' + (_list 635-641 'alnum+' + (Iter 635-641 'alnum+' + (Iter_plus 635-641 'alnum+' + (Pred 635-640 'alnum' + (Lex 635-640 'alnum' + (Base 635-640 'alnum' + (Base_application 635-640 'alnum' _opt + ) + ) + ) + ) (_terminal '+' 640-641) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule 644-659 'hor_id = alnum+' + (Rule_define 644-659 'hor_id = alnum+' _opt _opt (_terminal '=' 651-652) + (RuleBody 653-659 'alnum+' _opt + (NonemptyListOf 653-659 'alnum+' + (TopLevelTerm 653-659 'alnum+' + (Seq 653-659 'alnum+' + (_list 653-659 'alnum+' + (Iter 653-659 'alnum+' + (Iter_plus 653-659 'alnum+' + (Pred 653-658 'alnum' + (Lex 653-658 'alnum' + (Base 653-658 'alnum' + (Base_application 653-658 'alnum' _opt + ) + ) + ) + ) (_terminal '+' 658-659) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) (_terminal CC 660-661) + ) + ) +) +-- ohm-grammar.S.t.l.sexpr -- +(Grammars + (Grammar _opt + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_opt + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_opt + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application + (_opt + (Params + (ListOf + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Pred_lookahead + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_range + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_extend _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_lookahead + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren + (Alt + (NonemptyListOf + (Seq + (Iter + (Pred + (Pred_not + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base + (Base_application _opt + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define _opt _opt + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + (TopLevelTerm + (Seq + (Iter + (Pred + (Lex + (Base Base_terminal + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) +) + +-- file.c_and_p -- + +(Grammars + (_list + (Grammar + (ident + (name + (nameFirst + (letter + (upper (_terminal 'R' 0-1) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 1-2) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 2-3) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 3-4) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'A' 4-5) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 5-6) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 6-7) + ) + ) + ) + ) + ) + ) + ) _opt (_terminal OC 8-9) + (_list + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'G' 12-13) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'r' 13-14) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 14-15) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 15-16) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 16-17) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 17-18) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 18-19) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 20-21) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'n' 26-27) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'a' 27-28) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 28-29) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 29-30) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 31-32) + (Base + (Base_terminal + (terminal (_terminal '"' 32-33) + (_list + (terminalChar + (escapeChar + (escapeChar_lineFeed (_terminal '\n' 33-35) + ) + ) + ) + ) (_terminal '"' 35-36) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'R' 37-38) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 38-39) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 39-40) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 40-41) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) (_terminal '*' 41-42) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'R' 45-46) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 46-47) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 47-48) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 48-49) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 50-51) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'n' 59-60) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'a' 60-61) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 61-62) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 62-63) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Iter_opt + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 64-65) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 65-66) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 66-67) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 67-68) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 68-69) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 69-70) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 70-71) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 71-72) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 72-73) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) (_terminal '?' 73-74) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 75-76) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 76-77) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 77-78) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 78-79) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 79-80) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 80-81) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 81-82) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 82-83) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 84-85) + (_list + (terminalChar (_terminal OC 85-86) + ) + ) (_terminal '"' 86-87) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'R' 88-89) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 89-90) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 90-91) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 91-92) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 92-93) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 93-94) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 94-95) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 95-96) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'i' 96-97) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 97-98) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 98-99) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) (_terminal '*' 99-100) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 101-102) + (_list + (terminalChar (_terminal CC 102-103) + ) + ) (_terminal '"' 103-104) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'R' 107-108) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 108-109) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 109-110) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 110-111) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 111-112) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 112-113) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 113-114) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 114-115) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'i' 115-116) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 116-117) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 117-118) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 119-120) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'n' 121-122) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'a' 122-123) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 123-124) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 124-125) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 126-127) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 127-128) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 128-129) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 129-130) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 130-131) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 131-132) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 132-133) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 133-134) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 135-136) + (Base + (Base_paren (_terminal OP 136-137) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 137-138) + (_list + (terminalChar + (escapeChar + (escapeChar_lineFeed (_terminal '\n' 138-140) + ) + ) + ) + ) (_terminal '"' 140-141) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 141-142) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 142-143) + (_list + (terminalChar (_terminal ';' 143-144) + ) + ) (_terminal '"' 144-145) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 145-146) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 149-150) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 150-151) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 151-152) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 152-153) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 153-154) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 154-155) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 155-156) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 156-157) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 158-159) + (RuleBody + (_opt (_terminal '|' 164-165) + ) + (NonemptyListOf + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 166-167) + (Base + (Base_paren (_terminal OP 167-168) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 168-169) + (_list + (terminalChar (_terminal 'n' 169-170) + ) + (terminalChar (_terminal 'o' 170-171) + ) + (terminalChar (_terminal 'd' 171-172) + ) + (terminalChar (_terminal 'e' 172-173) + ) + ) (_terminal '"' 173-174) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren (_terminal OP 175-176) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 176-177) + (_list + (terminalChar (_terminal ' ' 177-178) + ) + ) (_terminal '"' 178-179) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 179-180) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 180-181) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 181-183) + ) + ) + ) + ) (_terminal '"' 183-184) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 184-185) + ) + ) + ) + ) (_terminal '*' 185-186) + ) + ) + ) + ) _list + ) + ) (_terminal CP 186-187) + ) + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 200-202) + (_list + (space (_terminal ' ' 202-203) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 'n' 203-204) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 204-205) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 205-206) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 206-207) + ) + ) + ) + ) + ) + ) _list (_terminal NL 207-208) + ) + ) + ) + (_list (_terminal '|' 212-213) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 214-215) + (Base + (Base_paren (_terminal OP 215-216) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 216-217) + (_list + (terminalChar (_terminal 'r' 217-218) + ) + (terminalChar (_terminal 'u' 218-219) + ) + (terminalChar (_terminal 'l' 219-220) + ) + (terminalChar (_terminal 'e' 220-221) + ) + ) (_terminal '"' 221-222) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_paren (_terminal OP 223-224) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 224-225) + (_list + (terminalChar (_terminal ' ' 225-226) + ) + ) (_terminal '"' 226-227) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 227-228) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 228-229) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 229-231) + ) + ) + ) + ) (_terminal '"' 231-232) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 232-233) + ) + ) + ) + ) (_terminal '+' 233-234) + ) + ) + ) + ) _list + ) + ) (_terminal CP 234-235) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'n' 237-238) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'a' 238-239) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 239-240) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 240-241) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 247-249) + (_list + (space (_terminal ' ' 249-250) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 'r' 250-251) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 251-252) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 252-253) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 253-254) + ) + ) + ) + ) + ) + ) _list (_terminal NL 254-255) + ) + ) + ) (_terminal '|' 259-260) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 261-262) + (Base + (Base_paren (_terminal OP 262-263) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 263-264) + (_list + (terminalChar (_terminal 't' 264-265) + ) + (terminalChar (_terminal 'e' 265-266) + ) + (terminalChar (_terminal 'r' 266-267) + ) + (terminalChar (_terminal 'm' 267-268) + ) + ) (_terminal '"' 268-269) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren (_terminal OP 270-271) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 271-272) + (_list + (terminalChar (_terminal ' ' 272-273) + ) + ) (_terminal '"' 273-274) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 274-275) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 275-276) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 276-278) + ) + ) + ) + ) (_terminal '"' 278-279) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 279-280) + ) + ) + ) + ) (_terminal '*' 280-281) + ) + ) + ) + ) _list + ) + ) (_terminal CP 281-282) + ) + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 295-297) + (_list + (space (_terminal ' ' 297-298) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 't' 298-299) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'e' 299-300) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 300-301) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 301-302) + ) + ) + ) + ) + ) + ) _list (_terminal NL 302-303) + ) + ) + ) (_terminal '|' 307-308) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 309-310) + (Base + (Base_paren (_terminal OP 310-311) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 311-312) + (_list + (terminalChar (_terminal 'l' 312-313) + ) + (terminalChar (_terminal 'i' 313-314) + ) + (terminalChar (_terminal 's' 314-315) + ) + (terminalChar (_terminal 't' 315-316) + ) + ) (_terminal '"' 316-317) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_paren (_terminal OP 318-319) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 319-320) + (_list + (terminalChar (_terminal ' ' 320-321) + ) + ) (_terminal '"' 321-322) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 322-323) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 323-324) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 324-326) + ) + ) + ) + ) (_terminal '"' 326-327) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 327-328) + ) + ) + ) + ) (_terminal '+' 328-329) + ) + ) + ) + ) _list + ) + ) (_terminal CP 329-330) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 332-333) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 333-334) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 334-335) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 335-336) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 336-337) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 337-338) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 338-339) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 339-340) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 343-345) + (_list + (space (_terminal ' ' 345-346) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 'l' 346-347) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'i' 347-348) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 348-349) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 349-350) + ) + ) + ) + ) + ) + ) _list (_terminal NL 350-351) + ) + ) + ) (_terminal '|' 355-356) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 357-358) + (Base + (Base_paren (_terminal OP 358-359) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 359-360) + (_list + (terminalChar (_terminal 'o' 360-361) + ) + (terminalChar (_terminal 'p' 361-362) + ) + (terminalChar (_terminal 't' 362-363) + ) + ) (_terminal '"' 363-364) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_paren (_terminal OP 366-367) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 367-368) + (_list + (terminalChar (_terminal ' ' 368-369) + ) + ) (_terminal '"' 369-370) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 370-371) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 371-372) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 372-374) + ) + ) + ) + ) (_terminal '"' 374-375) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 375-376) + ) + ) + ) + ) (_terminal '+' 376-377) + ) + ) + ) + ) _list + ) + ) (_terminal CP 377-378) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 380-381) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 381-382) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 382-383) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 383-384) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 384-385) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 385-386) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 386-387) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 387-388) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 391-393) + (_list + (space (_terminal ' ' 393-394) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 'o' 394-395) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'p' 395-396) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 396-397) + ) + ) + ) + ) + ) + ) _list (_terminal NL 397-398) + ) + ) + ) (_terminal '|' 402-403) + (TopLevelTerm + (TopLevelTerm_inline + (Seq + (_list + (Iter + (Pred + (Lex + (Lex_lex (_terminal '#' 404-405) + (Base + (Base_paren (_terminal OP 405-406) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 406-407) + (_list + (terminalChar (_terminal 'h' 407-408) + ) + (terminalChar (_terminal 'o' 408-409) + ) + (terminalChar (_terminal 'r' 409-410) + ) + ) (_terminal '"' 410-411) + ) + ) + ) + ) + ) + ) + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_paren (_terminal OP 413-414) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 414-415) + (_list + (terminalChar (_terminal ' ' 415-416) + ) + ) (_terminal '"' 416-417) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 417-418) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 418-419) + (_list + (terminalChar + (escapeChar + (escapeChar_tab (_terminal '\t' 419-421) + ) + ) + ) + ) (_terminal '"' 421-422) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal CP 422-423) + ) + ) + ) + ) (_terminal '+' 423-424) + ) + ) + ) + ) _list + ) + ) (_terminal CP 424-425) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'h' 427-428) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 428-429) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 429-430) + ) + ) + ) + ) + (nameRest (_terminal '_' 430-431) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'i' 431-432) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 432-433) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 434-435) + (_list + (terminalChar (_terminal '<' 435-436) + ) + ) (_terminal '"' 436-437) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'L' 438-439) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'i' 439-440) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 440-441) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 441-442) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'O' 442-443) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'f' 443-444) + ) + ) + ) + ) + ) + ) + ) + (_opt + (Params (_terminal '<' 444-445) + (ListOf + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (upper (_terminal 'N' 445-446) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 446-447) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 447-448) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 448-449) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 449-450) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 450-451) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'p' 451-452) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 452-453) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal ',' 453-454) + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 455-456) + (_list + (terminalChar (_terminal ',' 456-457) + ) + ) (_terminal '"' 457-458) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '>' 458-459) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 460-461) + (_list + (terminalChar (_terminal '>' 461-462) + ) + ) (_terminal '"' 462-463) + ) + ) + ) + ) + ) + ) + ) + ) + (caseName (_terminal '--' 464-466) + (_list + (space (_terminal ' ' 466-467) + ) + ) + (name + (nameFirst + (letter + (lower (_terminal 'h' 467-468) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 468-469) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 469-470) + ) + ) + ) + ) + ) + ) _list (_terminal NL 470-471) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 474-475) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 475-476) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 476-477) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 477-478) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 478-479) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'a' 479-480) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 480-481) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 481-482) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 483-484) + (RuleBody + (_opt (_terminal '|' 489-490) + ) + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 491-492) + (_list + (terminalChar (_terminal 'd' 492-493) + ) + (terminalChar (_terminal 'e' 493-494) + ) + (terminalChar (_terminal 'f' 494-495) + ) + (terminalChar (_terminal 'i' 495-496) + ) + (terminalChar (_terminal 'n' 496-497) + ) + (terminalChar (_terminal 'e' 497-498) + ) + ) (_terminal '"' 498-499) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not (_terminal '~' 500-501) + (Lex + (Base + (Base_paren (_terminal OP 501-502) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 502-503) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'l' 503-504) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 504-505) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'u' 505-506) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 506-507) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 507-508) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (_list (_terminal '|' 513-514) + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 515-516) + (_list + (terminalChar (_terminal 'o' 516-517) + ) + (terminalChar (_terminal 'v' 517-518) + ) + (terminalChar (_terminal 'e' 518-519) + ) + (terminalChar (_terminal 'r' 519-520) + ) + (terminalChar (_terminal 'r' 520-521) + ) + (terminalChar (_terminal 'i' 521-522) + ) + (terminalChar (_terminal 'd' 522-523) + ) + (terminalChar (_terminal 'e' 523-524) + ) + ) (_terminal '"' 524-525) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not (_terminal '~' 526-527) + (Lex + (Base + (Base_paren (_terminal OP 527-528) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 528-529) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'l' 529-530) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 530-531) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'u' 531-532) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 532-533) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 533-534) + ) + ) + ) + ) + ) + ) + ) + ) + ) (_terminal '|' 539-540) + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 541-542) + (_list + (terminalChar (_terminal 'e' 542-543) + ) + (terminalChar (_terminal 'x' 543-544) + ) + (terminalChar (_terminal 't' 544-545) + ) + (terminalChar (_terminal 'e' 545-546) + ) + (terminalChar (_terminal 'n' 546-547) + ) + (terminalChar (_terminal 'd' 547-548) + ) + ) (_terminal '"' 548-549) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Pred_not (_terminal '~' 550-551) + (Lex + (Base + (Base_paren (_terminal OP 551-552) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 552-553) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'l' 553-554) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 554-555) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'u' 555-556) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 556-557) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 557-558) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 561-562) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 562-563) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 563-564) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 564-565) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 565-566) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 566-567) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 567-568) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 568-569) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 569-570) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 572-573) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 574-575) + (_list + (terminalChar (_terminal OP 575-576) + ) + ) (_terminal '"' 576-577) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 578-579) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 579-580) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 580-581) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 581-582) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 582-583) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 583-584) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 584-585) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 585-586) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 586-587) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'T' 587-588) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 588-589) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'x' 589-590) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 590-591) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 592-593) + (_list + (terminalChar (_terminal CP 593-594) + ) + ) (_terminal '"' 594-595) + ) + ) + ) + ) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'r' 598-599) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'u' 599-600) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'l' 600-601) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 601-602) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'D' 602-603) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 603-604) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 's' 604-605) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'c' 605-606) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 606-607) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (upper (_terminal 'T' 607-608) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 608-609) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'x' 609-610) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 't' 610-611) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 612-613) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Iter_star + (Pred + (Lex + (Base + (Base_paren (_terminal OP 614-615) + (Alt + (NonemptyListOf + (Seq + (_list + (Iter + (Pred + (Pred_not (_terminal '~' 615-616) + (Lex + (Base + (Base_terminal + (terminal (_terminal '"' 616-617) + (_list + (terminalChar (_terminal CP 617-618) + ) + ) (_terminal '"' 618-619) + ) + ) + ) + ) + ) + ) + ) + (Iter + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 620-621) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'n' 621-622) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'y' 622-623) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) + ) + ) + ) _list + ) + ) (_terminal CP 623-624) + ) + ) + ) + ) (_terminal '*' 624-625) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'n' 628-629) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'a' 629-630) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 630-631) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'e' 631-632) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 633-634) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 635-636) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'l' 636-637) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 637-638) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'u' 638-639) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 639-640) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) (_terminal '+' 640-641) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + (Rule + (Rule_define + (ident + (name + (nameFirst + (letter + (lower (_terminal 'h' 644-645) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'o' 645-646) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'r' 646-647) + ) + ) + ) + ) + (nameRest (_terminal '_' 647-648) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'i' 648-649) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'd' 649-650) + ) + ) + ) + ) + ) + ) + ) _opt _opt (_terminal '=' 651-652) + (RuleBody _opt + (NonemptyListOf + (TopLevelTerm + (Seq + (_list + (Iter + (Iter_plus + (Pred + (Lex + (Base + (Base_application + (ident + (name + (nameFirst + (letter + (lower (_terminal 'a' 653-654) + ) + ) + ) + (_list + (nameRest + (alnum + (letter + (lower (_terminal 'l' 654-655) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'n' 655-656) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'u' 656-657) + ) + ) + ) + ) + (nameRest + (alnum + (letter + (lower (_terminal 'm' 657-658) + ) + ) + ) + ) + ) + ) + ) _opt + ) + ) + ) + ) (_terminal '+' 658-659) + ) + ) + ) + ) + ) _list + ) + ) + ) + ) + ) (_terminal CC 660-661) + ) + ) +) diff --git a/golang/cli/tests/ruleast.txtar b/golang/cli/tests/ruleast.txtar new file mode 100644 index 00000000..91607408 --- /dev/null +++ b/golang/cli/tests/ruleast.txtar @@ -0,0 +1,86 @@ +this grammar is not currently used, and does not match the output of rule_ast + +-- ruleast.ohm -- +RuleAst { + Grammar = name #"\n" Rule* + Rule = name ruleDescr? rulecase "{" RuleDetails* "}" + RuleDetails = name Nodetype #("\n"|";") + Nodetype = + | #("node" (" "|"\t")*) -- node + | #("rule" (" "|"\t")+) name -- rule + | #("term" (" "|"\t")*) -- term + | #("list" (" "|"\t")+) Nodetype -- list + | #("opt" (" "|"\t")+) Nodetype -- opt + | #("hor" (" "|"\t")+) hor_id "<" ListOf ">" -- hor + + rulecase = + | "define" ~(alnum) + | "override" ~(alnum) + | "extend" ~(alnum) + ruleDescr = "(" ruleDescrText ")" + ruleDescrText = (~")" any)* + name = alnum+ + hor_id = alnum+ +} + +-- file1.txt -- +G +a (x) define { + b rule b + c hor nel + d hor nel , term> +} +b define { + d opt term +} +-- file1.b.t.l.n.c_and_p -- +(Grammar + (name) + (Rule + (name) + (_opt + (ruleDescr + (ruleDescrText))) rulecase + (RuleDetails + (name) + (Nodetype + (Nodetype_rule + (name)))) + (RuleDetails + (name) + (Nodetype + (Nodetype_hor + (hor_id) + (ListOf + (NonemptyListOf + (Nodetype + (Nodetype_rule + (name))) + (Nodetype + (Nodetype_term))))))) + (RuleDetails + (name) + (Nodetype + (Nodetype_hor + (hor_id) + (ListOf + (NonemptyListOf + (Nodetype + (Nodetype_hor + (hor_id) + (ListOf + (NonemptyListOf + (Nodetype + (Nodetype_term)) + (Nodetype + (Nodetype_term)))))) + (Nodetype + (Nodetype_term)))))))) + (Rule + (name) _opt rulecase + (RuleDetails + (name) + (Nodetype + (Nodetype_opt + (Nodetype + (Nodetype_term))))))) \ No newline at end of file diff --git a/golang/cli/tests/ruleast_01.txtar b/golang/cli/tests/ruleast_01.txtar new file mode 100644 index 00000000..66b44980 --- /dev/null +++ b/golang/cli/tests/ruleast_01.txtar @@ -0,0 +1,524 @@ +-- @../../packages/ohm-js/src/ohm-grammar.ohm -- +relative to golang/cli directory +ony needed if using sexpr and c_and_p tests + +-- gmr1.txt -- +G { + S = "a" +} +-- gmr1.s.l.rule_ast -- +G // ruleast/build_rule_ast_exec.go:88 +S @bare { // ruleast/build_rule_ast_exec.go:99 + term @term // ruleast/build_rule_ast_exec.go:101 +} // ruleast/build_rule_ast_exec.go:103 + +-- gmr1_1.txt -- +G { + S (a note) = "a" +} +-- gmr1_1.s.rule_ast -- +G +S @bare (a note) { + term @term +} + +-- gmr2.txt -- +G { + S = a + a = "a" +} +-- gmr2.s.rule_ast -- +G +S @bare { + a @rule a +} +a @bare { + term @term +} + +-- gmr2_1.txt -- +G { + S = a a | a a + a = "a" +} +-- gmr2_1.s.rule_ast -- +G +S @bare { + a1 @rule a + a2 @rule a +} +a @bare { + term @term +} + +-- gmr2_2.txt -- +G { + S = a a | b b + a = "a" + b = "b" +} + +-- gmr2_2.s.rule_ast -- +G +S @bare { + arg1 @node + arg2 @node +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr2_2.n.l.S.v.t.c_and_p -- +(Grammars 0-47 'G OC\n S = a a | b b\n a = "a"\...' + (Grammar 0-47 'G OC\n S = a a | b b\n a = "a"\...' _opt + (Rule 8-21 'S = a a | b b' + (Rule_define 8-21 'S = a a | b b' _opt _opt + (RuleBody 12-21 'a a | b b' _opt + (NonemptyListOf 12-21 'a a | b b' + (TopLevelTerm 12-15 'a a' + (Seq 12-15 'a a' + (Iter 12-13 'a' + (Pred 12-13 'a' + (Lex 12-13 'a' + (Base 12-13 'a' + (Base_application 12-13 'a' _opt))))) + (Iter 14-15 'a' + (Pred 14-15 'a' + (Lex 14-15 'a' + (Base 14-15 'a' + (Base_application 14-15 'a' _opt))))))) + (TopLevelTerm 18-21 'b b' + (Seq 18-21 'b b' + (Iter 18-19 'b' + (Pred 18-19 'b' + (Lex 18-19 'b' + (Base 18-19 'b' + (Base_application 18-19 'b' _opt))))) + (Iter 20-21 'b' + (Pred 20-21 'b' + (Lex 20-21 'b' + (Base 20-21 'b' + (Base_application 20-21 'b' _opt))))))))))) + (Rule 26-33 'a = "a"' + (Rule_define 26-33 'a = "a"' _opt _opt + (RuleBody 30-33 '"a"' _opt + (NonemptyListOf 30-33 '"a"' + (TopLevelTerm 30-33 '"a"' + (Seq 30-33 '"a"' + (Iter 30-33 '"a"' + (Pred 30-33 '"a"' + (Lex 30-33 '"a"' + (Base 30-33 '"a"' Base_terminal)))))))))) + (Rule 38-45 'b = "b"' + (Rule_define 38-45 'b = "b"' _opt _opt + (RuleBody 42-45 '"b"' _opt + (NonemptyListOf 42-45 '"b"' + (TopLevelTerm 42-45 '"b"' + (Seq 42-45 '"b"' + (Iter 42-45 '"b"' + (Pred 42-45 '"b"' + (Lex 42-45 '"b"' + (Base 42-45 '"b"' Base_terminal)))))))))))) + +-- gmr2_3.txt -- +G { + S = a "1" | "2" b + a = "a" + b = "b" +} + +-- gmr2_3.s.rule_ast -- +G +S @bare { + arg1 @node + arg2 @node +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr2_4.txt -- +G { + S = a "1" | a b + a = "a" + b = "b" +} + +-- gmr2_4.s.rule_ast -- +G +S @bare { + a @rule a + arg @node +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr3.txt -- +G { + S (a note) = a -- one + a = "a" +} +-- gmr3.s.rule_ast -- +G +S @cases (a note) { + one @inline +} +S @virt one { + a @rule a +} +a @bare { + term @term +} + +-- gmr3.rule_ast -- +G +``` +S (a note) = a -- one + +``` +S @cases (a note) { + one @inline +} +``` +a +``` +S @virt one { + a @rule a +} +``` +a = "a" +``` +a @bare { + term @term +} + +-- gmr4.txt -- +G { + S = a -- one + | a + a = "a" +} +-- gmr4.s.rule_ast -- +G +S @cases { + one @inline + a @rule a +} +S @virt one { + a @rule a +} +a @bare { + term @term +} + +-- gmr5.txt -- +G { + S = a b -- one + | a + a = "a" + b = "b" +} +-- gmr5.s.rule_ast -- +G +S @cases { + one @inline + a @rule a +} +S @virt one { + a @rule a + b @rule b +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr6.txt -- +G { + S = + | a b -- one + | b a -- two + | a + a = "a" + b = "b" +} +-- gmr6.s.rule_ast -- +G +S @cases { + one @inline + two @inline + a @rule a +} +S @virt one { + a @rule a + b @rule b +} +S @virt two { + b @rule b + a @rule a +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr7.txt -- +G { + S = + | a b -- one + | b a -- two + | a + | b + a = "a" + b = "b" +} +-- gmr7.s.rule_ast -- +G +S @cases { + one @inline + two @inline + arg @node +} +S @virt one { + a @rule a + b @rule b +} +S @virt two { + b @rule b + a @rule a +} +a @bare { + term @term +} +b @bare { + term @term +} + +-- gmr8.txt -- +G { + S = ListOf + a = "a" +} +-- gmr8.s.rule_ast -- +G +S @bare { + listOf @hor ListOf<@rule a, @term> +} +a @bare { + term @term +} + +-- gmr8.n.v.b.c_and_p -- +(Grammars 0-40 'G OC\n S = ListOf\n a =...' + (_list 0-40 'G OC\n S = ListOf\n a =...' + (Grammar 0-40 'G OC\n S = ListOf\n a =...' + (ident 0-1 'G' + (name 0-1 'G' nameFirst _list)) _opt (_terminal OC 2-3) + (_list 3-38 '\n S = ListOf\n a = "a"' + (Rule 8-26 'S = ListOf' + (Rule_define 8-26 'S = ListOf' + (ident 8-9 'S' + (name 8-9 'S' nameFirst _list)) _opt _opt (_terminal '=' 10-11) + (RuleBody 12-26 'ListOf' _opt + (NonemptyListOf 12-26 'ListOf' + (TopLevelTerm 12-26 'ListOf' + (Seq 12-26 'ListOf' + (_list 12-26 'ListOf' + (Iter 12-26 'ListOf' + (Pred 12-26 'ListOf' + (Lex 12-26 'ListOf' + (Base 12-26 'ListOf' + (Base_application 12-26 'ListOf' + (ident 12-18 'ListOf' + (name 12-18 'ListOf' nameFirst + (_list 13-18 'istOf' nameRest nameRest nameRest nameRest nameRest))) + (_opt 18-26 '' + (Params 18-26 '' (_terminal '<' 18-19) + (ListOf 19-25 'a, ","' + (NonemptyListOf 19-25 'a, ","' + (Seq 19-20 'a' + (_list 19-20 'a' + (Iter 19-20 'a' + (Pred 19-20 'a' + (Lex 19-20 'a' + (Base 19-20 'a' + (Base_application 19-20 'a' + (ident 19-20 'a' + (name 19-20 'a' nameFirst _list)) _opt))))))) + (_list 20-25 ', ","' (_terminal ',' 20-21) + (Seq 22-25 '","' + (_list 22-25 '","' + (Iter 22-25 '","' + (Pred 22-25 '","' + (Lex 22-25 '","' + (Base 22-25 '","' + (Base_terminal 22-25 '","' + (terminal 22-25 '","' (_terminal '"' 22-23) + (_list 23-24 ',' + (terminalChar 23-24 ',' (_terminal ',' 23-24))) (_terminal '"' 24-25)))))))))))) (_terminal '>' 25-26))))))))))) _list)))) + (Rule 31-38 'a = "a"' + (Rule_define 31-38 'a = "a"' + (ident 31-32 'a' + (name 31-32 'a' nameFirst _list)) _opt _opt (_terminal '=' 33-34) + (RuleBody 35-38 '"a"' _opt + (NonemptyListOf 35-38 '"a"' + (TopLevelTerm 35-38 '"a"' + (Seq 35-38 '"a"' + (_list 35-38 '"a"' + (Iter 35-38 '"a"' + (Pred 35-38 '"a"' + (Lex 35-38 '"a"' + (Base 35-38 '"a"' + (Base_terminal 35-38 '"a"' + (terminal 35-38 '"a"' (_terminal '"' 35-36) + (_list 36-37 'a' + (terminalChar 36-37 'a' (_terminal 'a' 36-37))) (_terminal '"' 37-38)))))))))) _list))))) (_terminal CC 39-40)))) + +-- gmr8_1.txt -- +G { + S = ListOf + a = "a" +} +-- gmr8_1.s.rule_ast -- +G +S @bare { + listOf @hor ListOf<@rule a, @rule a> +} +a @bare { + term @term +} + +-- gmr8_2.txt -- +G { + S = ListOf? + a = "a" +} +-- gmr8_2.s.rule_ast -- +G +S @bare { + listOf @opt @hor ListOf<@list @rule a, @opt @term> +} +a @bare { + term @term +} + +-- gmr8_5.txt -- +G { + S = ListOf<(a|a), ","> -- one + a = "a" +} +-- gmr8_5.s.rule_ast -- +G +S @cases { + one @inline +} +S @virt one { + listOf @hor ListOf<@node, @term> +} +a @bare { + term @term +} + +-- gmr9.txt -- +G { + S = a<"a"> + a = x +} +-- gmr9.s.rule_ast -- +G +S @bare { + a @node +} +a @bare { + x @rule x +} + +-- gmr9.n.v.b.t.S.l.c_and_p -- +(Grammars 0-33 'G OC\n S = a<"a">\n a = x\nCC' + (Grammar 0-33 'G OC\n S = a<"a">\n a = x\nCC' _opt + (Rule 8-18 'S = a<"a">' + (Rule_define 8-18 'S = a<"a">' _opt _opt + (RuleBody 12-18 'a<"a">' _opt + (NonemptyListOf 12-18 'a<"a">' + (TopLevelTerm 12-18 'a<"a">' + (Seq 12-18 'a<"a">' + (Iter 12-18 'a<"a">' + (Pred 12-18 'a<"a">' + (Lex 12-18 'a<"a">' + (Base 12-18 'a<"a">' + (Base_application 12-18 'a<"a">' + (_opt 13-18 '<"a">' + (Params 13-18 '<"a">' + (ListOf 14-17 '"a"' + (NonemptyListOf 14-17 '"a"' + (Seq 14-17 '"a"' + (Iter 14-17 '"a"' + (Pred 14-17 '"a"' + (Lex 14-17 '"a"' + (Base 14-17 '"a"' Base_terminal)))))))))))))))))))) + (Rule 23-31 'a = x' + (Rule_define 23-31 'a = x' + (_opt 24-27 '' + (Formals 24-27 '' + (ListOf 25-26 'x' + (NonemptyListOf 25-26 'x')))) _opt + (RuleBody 30-31 'x' _opt + (NonemptyListOf 30-31 'x' + (TopLevelTerm 30-31 'x' + (Seq 30-31 'x' + (Iter 30-31 'x' + (Pred 30-31 'x' + (Lex 30-31 'x' + (Base 30-31 'x' + (Base_application 30-31 'x' _opt))))))))))))) + +-- gmr10.txt -- +G1 { + S = "a" +} +G2 { + S = "a" +} +-- gmr10.s.rule_ast -- +G1 +S @bare { + term @term +} +G2 +S @bare { + term @term +} + +-- grammar_mixed_03.txt -- +G { + S = "A" -- A + | "B" + | C + C = "C" +} +-- grammar_mixed_03.s.rule_ast -- +G +S @cases { + A @inline + arg @node +} +S @virt A { + term @term +} +C @bare { + term @term +} diff --git a/golang/cli/tests/tests.go b/golang/cli/tests/tests.go new file mode 100644 index 00000000..3e332582 --- /dev/null +++ b/golang/cli/tests/tests.go @@ -0,0 +1,247 @@ +package tests + +import ( + _ "embed" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/google/go-cmp/cmp" + "github.com/ohmjs/ohmgo/candp" + "github.com/ohmjs/ohmgo/ruleast" + "github.com/ohmjs/ohmgo/sexpr" + "golang.org/x/tools/txtar" +) + +type testGmrCmd struct { + ReMatchTest string + TxTarFile []string `opts:"mode=arg"` +} + +func NewTestGmrCmd() *testGmrCmd { + return &testGmrCmd{} +} + +type Processor interface { + Process() (string, error) +} + +type Expect struct { + file txtar.File + process Processor +} + +func (cm *testGmrCmd) Run() error { + for _, f := range cm.TxTarFile { + err := cm.TestFile(f) + if err != nil { + return err + } + } + return nil +} + +func (cm *testGmrCmd) TestFile(txTarFile string) error { + ar, err := txtar.ParseFile(txTarFile) + if err != nil { + return err + } + var gmr *txtar.File + // var gmr *string + sepxrs := []Expect{} + candps := map[string][]Expect{} + txtsMap := map[string]struct { + GrammarFile string + Source string + }{} + txtKeys := []string{} + for _, fi := range ar.Files { + parts := strings.Split(fi.Name, ".") + ext := parts[len(parts)-1] + testName := parts[0] + if ext != "ohm" && cm.ReMatchTest != "" { + ok, err := regexp.MatchString(cm.ReMatchTest, testName) + if err != nil { + return err + } + if !ok { + continue + } + } + if fi.Name[:1] == "!" { + fmt.Fprintf(os.Stderr, "skipping %s\n", fi.Name) + continue + } + switch ext { + case "ohm": + if gmr != nil { + panic(fmt.Errorf("only one grammar file per txtar. %v", txTarFile)) + } + if strings.HasPrefix(fi.Name, "@") { + data, err := os.ReadFile(fi.Name[1:]) + if err != nil { + panic(err) + } + paths := strings.Split(fi.Name, "/") + name := strings.TrimPrefix(paths[len(paths)-1], "@") + gmr = &txtar.File{ + Name: name, + Data: data, + } + continue + } + gmr = &fi + case "sexpr": + toSexpr := &sexpr.ToSexprCmd{ + Grammar: string(gmr.Data), + } + for _, flag := range parts[1 : len(parts)-1] { + switch flag { + case "t": + toSexpr.ExcludeTerminals = true + case "S": + toSexpr.SyntacticRulesOnly = true + case "b": + toSexpr.ExcludeBuiltin = true + case "l": + toSexpr.PruneLists = true + case "v": + toSexpr.Verbose = true + case "n": + toSexpr.NoClosingNewline = true + default: + panic("unkown short flag : " + flag) + } + } + sepxrs = append(sepxrs, Expect{ + file: fi, + process: toSexpr, + }) + case "txt": + if _, ok := txtsMap[parts[0]]; ok { + panic(fmt.Errorf("duplicate txt file. %s", parts[0])) + } + if gmr == nil { + panic(fmt.Errorf("expected grammar file before txt file. %v", txTarFile)) + } + tempdir, err := os.MkdirTemp("", "ohm-compile-*") + if err != nil { + return fmt.Errorf("creating tempdir: %v", err) + } + gmrp := filepath.Join(tempdir, gmr.Name) + gmrf, err := os.Create(gmrp) + if err != nil { + return fmt.Errorf("creating file: %v", err) + } + _, err = gmrf.Write(gmr.Data) + if err != nil { + return fmt.Errorf("creating writing: %v", err) + } + gmrf.Close() + defer os.RemoveAll(tempdir) + txtKeys = append(txtKeys, parts[0]) + txtsMap[parts[0]] = struct { + GrammarFile string + Source string + }{ + GrammarFile: gmrp, + Source: string(fi.Data), + } + case "c_and_p": + if _, ok := txtsMap[parts[0]]; !ok { + panic(fmt.Errorf("txt file doesn't exist for c and p. %s", parts[0])) + } + candp := &candp.CompileAndParseCmd{ + GrammarFile: txtsMap[parts[0]].GrammarFile, + Source: txtsMap[parts[0]].Source, + } + for _, flag := range parts[1 : len(parts)-1] { + switch flag { + case "t": + candp.ExcludeTerminals = true + case "S": + candp.SyntacticRulesOnly = true + case "b": + candp.ExcludeBuiltin = true + case "l": + candp.PruneLists = true + case "v": + candp.Verbose = true + case "n": + candp.NoClosingNewline = true + default: + panic("unkown short flag : " + flag) + } + } + candps[parts[0]] = append(candps[parts[0]], Expect{ + file: fi, + process: candp, + }) + case "rule_ast": + if _, ok := txtsMap[parts[0]]; !ok { + panic(fmt.Errorf("txt file doesn't exist for rule ast. %s", parts[0])) + } + rast := &ruleast.RuleAstCmd{ + Grammar: txtsMap[parts[0]].Source, + } + for _, flag := range parts[1 : len(parts)-1] { + switch flag { + case "s": + rast.SkipSource = true + case "l": + rast.SuffixOutfLineNos = true + default: + panic("unkown short flag : " + flag) + } + } + candps[parts[0]] = append(candps[parts[0]], Expect{ + file: fi, + process: rast, + }) + } + } + if gmr == nil { + panic(fmt.Errorf("expected one grammar file per txtar. %v", txTarFile)) + } + RunTests(txTarFile, gmr, sepxrs) + for _, f := range txtKeys { + candp := candps[f] + RunTests(txTarFile, gmr, candp) + } + return nil +} + +func RunTests( + txTarFile string, + gmr *txtar.File, + tests []Expect, +) { + for _, exp := range tests { + var ( + rec string + err error + ) + rec, err = exp.process.Process() + if err != nil { + fmt.Fprintf(os.Stderr, "gen result error for %s, err : %v\n", exp.file.Name, err) + fmt.Fprintf(os.Stderr, " gmr '%s'\n", string(gmr.Data)) + fmt.Fprintf(os.Stderr, " text '%s'\n'%s'\n", exp.file.Name, string(exp.file.Data)) + continue + } + expected := strings.TrimSpace(string(exp.file.Data)) + received := strings.TrimSpace(rec) + if expected != received { + fmt.Fprintf(os.Stderr, "! vv sexpr doesn't match %s %s\n", txTarFile, exp.file.Name) + fmt.Fprintf(os.Stderr, "expected:\n") + fmt.Fprintf(os.Stderr, "%s\n", expected) + fmt.Fprintf(os.Stderr, "received:\n") + fmt.Fprintf(os.Stdout, "%s\n", received) + fmt.Fprintf(os.Stderr, "diff :\n%s\n", cmp.Diff(expected, received)) + fmt.Fprintf(os.Stderr, "! ^^ sexpr doesn't match %s %s\n", txTarFile, exp.file.Name) + } else { + fmt.Fprintf(os.Stderr, "+ matches %s %s\n", txTarFile, exp.file.Name) + } + } +} diff --git a/golang/cli/utils/dev.go b/golang/cli/utils/dev.go new file mode 100644 index 00000000..331c6d90 --- /dev/null +++ b/golang/cli/utils/dev.go @@ -0,0 +1,17 @@ +//go:build dev + +package utils + +import ( + "fmt" + "os" +) + +func OhmGrammarWasmBytes() []byte { + // expected to be run from cli dir + barr, err := os.ReadFile("utils/ohm-grammar.wasm") + if err != nil { + panic(fmt.Errorf("dev mode error %v", err)) + } + return barr +} diff --git a/golang/cli/utils/embed.go b/golang/cli/utils/embed.go new file mode 100644 index 00000000..66ed5607 --- /dev/null +++ b/golang/cli/utils/embed.go @@ -0,0 +1,16 @@ +//go:build !dev + +package utils + +import ( + _ "embed" +) + +//go:generate docker run --rm -v "$PWD/../../../packages/ohm-js/src:/local" -v "$PWD:/dst" ohmjs/ohm:18.0.0-beta.15 compile ohm-grammar.ohm + +var ( + //go:embed ohm-grammar.wasm + ohmGrammarWasmBytes []byte +) + +func OhmGrammarWasmBytes() []byte { return ohmGrammarWasmBytes } diff --git a/golang/examples/.gitignore b/golang/examples/.gitignore new file mode 100644 index 00000000..b432a803 --- /dev/null +++ b/golang/examples/.gitignore @@ -0,0 +1,2 @@ +my-grammar.wasm +ohmgo-examples \ No newline at end of file diff --git a/golang/examples/generate.go b/golang/examples/generate.go new file mode 100644 index 00000000..955e22e8 --- /dev/null +++ b/golang/examples/generate.go @@ -0,0 +1,4 @@ +package main + +// The docker image tag needs to take into account the version of the goohm runtime library. +//go:generate docker run --rm -v "$PWD:/local" ohmjs/ohm:18.0.0-beta.15 compile my-grammar.ohm diff --git a/golang/examples/go.mod b/golang/examples/go.mod new file mode 100644 index 00000000..9f35cbeb --- /dev/null +++ b/golang/examples/go.mod @@ -0,0 +1,3 @@ +module github.com/ohmjs/ohmgo-examples + +go 1.24.2 diff --git a/golang/examples/load_and_use.go b/golang/examples/load_and_use.go new file mode 100644 index 00000000..7898a435 --- /dev/null +++ b/golang/examples/load_and_use.go @@ -0,0 +1,39 @@ +package main + +import ( + "context" + _ "embed" + "log" + "os" + + goohm "github.com/ohmjs/goohm" +) + +//go:embed my-grammar.wasm +var wasmBytes []byte + +func main() { + // or, if you prefer, read the .wasm file from disk + // wasmBytes, err := os.ReadFile("my-grammar.wasm") + ctx := context.Background() + grmr, err := goohm.NewGrammar(ctx, wasmBytes) + if err != nil { + log.Fatalf("creating grammar: %v", err) + } + defer grmr.Close() + // use the grammar to match some input text + input := "Hello, world!" + if len(os.Args) > 1 && os.Args[1] != "" { + input = os.Args[1] + } + result, err := grmr.Match(input) + if err != nil { + log.Fatalf("matching: %v", err) + } + defer result.Close() + if !result.Succeeded() { + log.Printf("match failed") + os.Exit(1) + } + log.Printf("match succeeded") +} diff --git a/golang/examples/my-grammar.ohm b/golang/examples/my-grammar.ohm new file mode 100644 index 00000000..42637aaf --- /dev/null +++ b/golang/examples/my-grammar.ohm @@ -0,0 +1,9 @@ +MyGrammar { + Start = hello name "!"? + hello = + | "hello," + | "Hello," + | "hello" + | "Hello" + name = letter+ +} diff --git a/golang/runtime/.gitignore b/golang/runtime/.gitignore new file mode 100644 index 00000000..32e6b260 --- /dev/null +++ b/golang/runtime/.gitignore @@ -0,0 +1 @@ +es5.wasm diff --git a/packages/compiler/test/go/README.md b/golang/runtime/README.md similarity index 100% rename from packages/compiler/test/go/README.md rename to golang/runtime/README.md diff --git a/packages/compiler/test/go/cst.go b/golang/runtime/cst.go similarity index 69% rename from packages/compiler/test/go/cst.go rename to golang/runtime/cst.go index b3c5da0d..39d83a5f 100644 --- a/packages/compiler/test/go/cst.go +++ b/golang/runtime/cst.go @@ -1,6 +1,8 @@ -package main +package goohm import ( + "fmt" + "strings" "unicode/utf16" "unsafe" @@ -16,7 +18,6 @@ const ( CstNodeTypeList CstNodeType = 2 CstNodeTypeOpt CstNodeType = 3 ) - const ( matchRecordTypeMask = 3 cstNodeHeaderSize = 16 @@ -45,8 +46,149 @@ type CstNode struct { startIdx int // position in the input (UTF-16 code units) } -func newCstNode(ctx *cstContext, base uint32, startIdx int) *CstNode { - return &CstNode{ctx: ctx, base: base, startIdx: startIdx} +type cstRuleNode struct { + *CstNode +} +type cstTerminalNode struct { + *CstNode +} +type cstListNode struct { + *CstNode +} +type cstOptNode struct { + *CstNode +} +type cstSeqNode struct { + *CstNode +} + +// type cstBHorNode struct { +// *CstNode +// } + +func (node *cstRuleNode) Elems() []Node { + return ListOfElement(node) +} + +func (c *cstRuleNode) Seps() []Node { + panic("not implemented") + // return []Node{} +} + +func (c *cstRuleNode) bhor() {} + +func (n CstNode) String() string { return NodeString(n) } + +// func (n cstNonterminalNode) String() string { return NodeString(*n.CstNode) } +// func (n cstTerminalNode) String() string { return NodeString(*n.CstNode) } +// func (n cstListNode) String() string { return NodeString(*n.CstNode) } +// func (n cstOptNode) String() string { return NodeString(*n.CstNode) } +// func (n cstSeqNode) String() string { return NodeString(*n.CstNode) } + +// func (n cstNonterminalNode) String() string { return n.CtorName() } +// func (n cstTerminalNode) String() string { return n.SourceString() } + +func NodeString(n CstNode) string { + s, f := n.Source() + val := n.SourceString() + val = strings.ReplaceAll(val, "\n", "\\n") + val = strings.ReplaceAll(val, "(", "OP") + val = strings.ReplaceAll(val, ")", "CP") + val = strings.ReplaceAll(val, "{", "OC") + val = strings.ReplaceAll(val, "}", "CC") + if len(val) > 100 { + val = val[:97] + "..." + } + return fmt.Sprintf("%s %d-%d '%s'", n.CtorName(), s, f, val) +} + +var ( + _ Node = &CstNode{} + _ TerminalNode = &cstTerminalNode{} + _ RuleNode = &cstRuleNode{} + _ ListNode = &cstListNode{} + _ OptNode = &cstOptNode{} + _ SeqNode = &cstSeqNode{} + _ BHorNode = &cstRuleNode{} +) + +func (c *cstTerminalNode) terminal() {} +func (c *cstRuleNode) rule() {} +func (c *cstListNode) list() {} +func (c *cstOptNode) optional() {} +func (c *cstSeqNode) seq() {} + +// func (n *CstNode) NumChildren() int { +// panic("unimplemented") +// } + +func (c *cstOptNode) IsPresent() bool { + return c.count() > 0 +} + +func (n *CstNode) StartIdx() int { + return n.startIdx +} + +func (n *CstNode) CstCtx() *cstContext { + return n.ctx +} + +// Children returns the child nodes, with startIdx properly tracked. +// For children of syntactic rules, implicit leading spaces are accounted +// for when computing startIdx. +func (n *CstNode) Children() []Node { + if isTerminal(n.base) { + return nil + } + count := n.count() + if count == 0 { + return nil + } + children := make([]Node, count) + startIdx := n.startIdx + endIdx := n.startIdx + n.MatchLength() + for i := uint32(0); i < count; i++ { + slotOffset := n.base + cstNodeHeaderSize + i*slotSize + data, ok := n.ctx.memory.Read(slotOffset, 4) + if !ok { + return children[:i] + } + slot := readUint32(data, 0) + // Bit 1 is the HAS_LEADING_SPACES edge flag. + hasLeadingSpaces := slot&2 != 0 + // Strip the edge flag to get the actual value. + raw := slot & ^uint32(2) + // Account for implicit leading spaces. + // Only apply if spaces were actually recorded at this position + // and the result stays within the parent's span. + if hasLeadingSpaces && n.ctx.getSpacesLenAt != nil && n.hasParentSpaces(raw) { + spacesLen := n.ctx.getSpacesLenAt(startIdx) + if spacesLen > 0 && startIdx+spacesLen <= endIdx { + startIdx += spacesLen + } + } + child := newCstNode(n.ctx, raw, startIdx) + children[i] = child + startIdx += child.MatchLength() + } + return children +} + +func newCstNode(ctx *cstContext, base uint32, startIdx int) Node { + node := &CstNode{ctx: ctx, base: base, startIdx: startIdx} + switch node.Type() { + case CstNodeTypeNonterminal: + return &cstRuleNode{node} + case CstNodeTypeTerminal: + return &cstTerminalNode{node} + case CstNodeTypeList: + return &cstListNode{node} + case CstNodeTypeOpt: + return &cstOptNode{node} + default: + return node + } } func isTerminal(raw uint32) bool { @@ -54,7 +196,6 @@ func isTerminal(raw uint32) bool { } // --- internal field accessors --- - func (n *CstNode) typeAndDetails() int32 { data, ok := n.ctx.memory.Read(n.base+4, 4) if !ok { @@ -83,7 +224,6 @@ func (n *CstNode) count() uint32 { } // --- public API (matches the ohm-js CstNode interface) --- - // Type returns the CstNodeType for this node. func (n *CstNode) Type() CstNodeType { if isTerminal(n.base) { @@ -114,6 +254,14 @@ func (n *CstNode) CtorName() string { } } +func (n *CstNode) RuleName() string { + id := n.ruleID() + if int(id) < len(n.ctx.ruleNames) { + return n.ctx.ruleNames[id] + } + return "" +} + // MatchLength returns the number of UTF-16 code units consumed by this node. func (n *CstNode) MatchLength() int { if isTerminal(n.base) { @@ -149,7 +297,7 @@ func (n *CstNode) SourceString() string { } // Value returns the matched text. -func (n *CstNode) Value() string { +func (n *cstTerminalNode) Value() string { return n.SourceString() } @@ -193,50 +341,6 @@ func readNodeType(mem api.Memory, ptr uint32) CstNodeType { return CstNodeType(readInt32(data, 0) & matchRecordTypeMask) } -// Children returns the child nodes, with startIdx properly tracked. -// For children of syntactic rules, implicit leading spaces are accounted -// for when computing startIdx. -func (n *CstNode) Children() []*CstNode { - if isTerminal(n.base) { - return nil - } - count := n.count() - if count == 0 { - return nil - } - children := make([]*CstNode, count) - startIdx := n.startIdx - endIdx := n.startIdx + n.MatchLength() - for i := uint32(0); i < count; i++ { - slotOffset := n.base + cstNodeHeaderSize + i*slotSize - data, ok := n.ctx.memory.Read(slotOffset, 4) - if !ok { - return children[:i] - } - slot := readUint32(data, 0) - - // Bit 1 is the HAS_LEADING_SPACES edge flag. - hasLeadingSpaces := slot&2 != 0 - // Strip the edge flag to get the actual value. - raw := slot & ^uint32(2) - - // Account for implicit leading spaces. - // Only apply if spaces were actually recorded at this position - // and the result stays within the parent's span. - if hasLeadingSpaces && n.ctx.getSpacesLenAt != nil && n.hasParentSpaces(raw) { - spacesLen := n.ctx.getSpacesLenAt(startIdx) - if spacesLen > 0 && startIdx+spacesLen <= endIdx { - startIdx += spacesLen - } - } - - child := newCstNode(n.ctx, raw, startIdx) - children[i] = child - startIdx += child.MatchLength() - } - return children -} - // Helper functions for reading little-endian values from memory. func readUint32(data []byte, offset uint32) uint32 { return *(*uint32)(unsafe.Pointer(&data[offset])) diff --git a/golang/runtime/cst_types.go b/golang/runtime/cst_types.go new file mode 100644 index 00000000..1e28a2be --- /dev/null +++ b/golang/runtime/cst_types.go @@ -0,0 +1,78 @@ +package goohm + +// type Source struct { +// StartIdx uint32 +// EndIdx uint32 +// } + +type Node interface { + CtorName() string + // RuleName() string + StartIdx() int + Source() (startIdx, endIdx int) + SourceString() string + MatchLength() int + Children() []Node + // NumChildren() int + // IsNonterminal() bool + // IsTerminal() bool + // IsOptional() bool + // IsSeq() bool + // IsList() bool + CstCtx() *cstContext +} + +type RuleNode interface { + rule() + Node + // Children() []Node + // LeadingSpaces() NonterminalNode // nil if absent + IsSyntactic() bool + IsLexical() bool +} + +// built-in higher order rules +// currently these are [Ll]istOf [Nn]onemptyListOf +type BHorNode interface { + bhor() + Node + Elems() []Node + Seps() []Node + // Children() []Node + // LeadingSpaces() NonterminalNode // nil if absent +} + +type TerminalNode interface { + terminal() + Node + // // For terminals, Children() returns an empty slice. + // Children() []Node + // LeadingSpaces() NonterminalNode // nil if absent + Value() string +} + +type ListNode interface { + list() + Node + // Children() []Node + // // maybe this should be generic + // Collect(cb func(children ...Node) any) []any +} + +type OptNode interface { + optional() + Node + Children() []Node + IsPresent() bool + // IsEmpty() bool + // // IfPresent calls consume with the child (unpacking a SeqNode's children if applicable). + // // orElse may be nil. Returns the consume/orElse result, or nil if absent and orElse is nil. + // IfPresent(consume func(children ...Node) any, orElse func() any) any +} + +type SeqNode interface { + seq() + Node + // Children() []Node + // Unpack(cb func(children ...Node) any) any +} diff --git a/golang/runtime/generate.sh b/golang/runtime/generate.sh new file mode 100755 index 00000000..207b4651 --- /dev/null +++ b/golang/runtime/generate.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +REPO_ROOT=$(git rev-parse --show-toplevel) + +if [ "$OHM_DOCKER_IMAGE_VERSION" != "" ]; then + VERSION="$OHM_DOCKER_IMAGE_VERSION" +else + VERSION=$(cat "${REPO_ROOT}/packages/compiler/package.json" | jq -r '.version') +fi +echo "Using Ohm Docker image version: ${VERSION}" +docker run --rm -v "${REPO_ROOT}:/local" ohmjs/ohm:${VERSION} compile -o golang/runtime/es5.wasm examples/ecmascript/src/es5.ohm \ No newline at end of file diff --git a/golang/runtime/go.mod b/golang/runtime/go.mod new file mode 100644 index 00000000..eaffd370 --- /dev/null +++ b/golang/runtime/go.mod @@ -0,0 +1,7 @@ +module github.com/ohmjs/goohm + +go 1.24.2 + +require github.com/tetratelabs/wazero v1.11.0 + +require golang.org/x/sys v0.38.0 // indirect diff --git a/golang/runtime/go.sum b/golang/runtime/go.sum new file mode 100644 index 00000000..6cfca8b4 --- /dev/null +++ b/golang/runtime/go.sum @@ -0,0 +1,4 @@ +github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA= +github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/packages/compiler/test/go/grammar.go b/golang/runtime/grammar.go similarity index 87% rename from packages/compiler/test/go/grammar.go rename to golang/runtime/grammar.go index 7b93a814..963da2f6 100644 --- a/packages/compiler/test/go/grammar.go +++ b/golang/runtime/grammar.go @@ -1,4 +1,4 @@ -package main +package goohm import ( "context" @@ -6,6 +6,7 @@ import ( "fmt" "io" "regexp" + "strings" "unicode" "unicode/utf16" @@ -13,17 +14,31 @@ import ( "github.com/tetratelabs/wazero/api" ) +// Needs to manually be kept in sync (updated) as packages/compiler changes. +// The cli uses the head of the list is the recommended tag when generating a generate command (eg docker run ohmjs/ohm:). +var acceptedVersions = []string{ + "18.0.0-beta.15", + "18.0.0-beta.14", + "18.0.0-beta.13", +} + // Grammar is a Go implementation of the JavaScript Grammar class from miniohm. type Grammar struct { - runtime wazero.Runtime - module api.Module - input string - inputUTF16 []uint16 // UTF-16 code units of the current input - ctx context.Context - ruleIds map[string]int - ruleNames []string - strings []string // strings table from the custom section - resultStack []*MatchResult + runtime wazero.Runtime + module api.Module + input string + inputUTF16 []uint16 // UTF-16 code units of the current input + ctx context.Context + ruleIds map[string]int + ruleNames []string + strings []string // strings table from the custom section + compilerVersion []string // version string from the custom section + resultStack []*MatchResult +} + +// MatchingDockerImageTags, list of docker image tags which generate wasm parsers which work with this runtime version. +func (*Grammar) MatchingDockerImageTags() []string { + return acceptedVersions } // GetModule returns the WebAssembly module @@ -35,13 +50,11 @@ func (g *Grammar) GetModule() api.Module { // This parallels Grammar.instantiate() in the JS API. func NewGrammar(ctx context.Context, wasmBytes []byte) (*Grammar, error) { config := wazero.NewRuntimeConfig().WithCustomSections(true) - g := &Grammar{ runtime: wazero.NewRuntimeWithConfig(ctx, config), ctx: ctx, ruleIds: make(map[string]int), } - // Create the env module with the abort function _, err := g.runtime.NewHostModuleBuilder("env"). NewFunctionBuilder(). @@ -53,41 +66,26 @@ func NewGrammar(ctx context.Context, wasmBytes []byte) (*Grammar, error) { if err != nil { return nil, fmt.Errorf("failed to create env module: %v", err) } - // Create the ohmRuntime module with required host functions + // Note: referring to a method, without calling it is a function with the receiver curried. _, err = g.runtime.NewHostModuleBuilder("ohmRuntime"). - NewFunctionBuilder(). - WithFunc(func(ctx context.Context, mod api.Module, dest, length uint32) uint32 { - return g.fillInputBuffer(ctx, mod, dest, length) - }). - Export("fillInputBuffer"). - NewFunctionBuilder(). - WithFunc(func(ctx context.Context, mod api.Module, categoryBitmap uint32) uint32 { - return g.matchUnicodeChar(ctx, mod, categoryBitmap) - }). - Export("matchUnicodeChar"). - NewFunctionBuilder(). - WithFunc(func(ctx context.Context, mod api.Module, stringIdx uint32) uint32 { - return g.matchCaseInsensitive(ctx, mod, stringIdx) - }). - Export("matchCaseInsensitive"). + NewFunctionBuilder().WithFunc(g.fillInputBuffer).Export("fillInputBuffer"). + NewFunctionBuilder().WithFunc(g.matchUnicodeChar).Export("matchUnicodeChar"). + NewFunctionBuilder().WithFunc(g.matchCaseInsensitive).Export("matchCaseInsensitive"). Instantiate(g.ctx) if err != nil { return nil, fmt.Errorf("failed to create ohmRuntime module: %v", err) } - // Compile the module to access the custom sections compiledModule, err := g.runtime.CompileModule(g.ctx, wasmBytes) if err != nil { return nil, fmt.Errorf("error compiling module: %v", err) } - // Parse custom sections customSections := compiledModule.CustomSections() if customSections == nil { return nil, fmt.Errorf("no custom sections found in module") } - for _, section := range customSections { switch section.Name() { case "ruleNames": @@ -100,25 +98,44 @@ func NewGrammar(ctx context.Context, wasmBytes []byte) (*Grammar, error) { if err != nil { return nil, fmt.Errorf("failed to parse strings: %v", err) } + case "version": + g.compilerVersion, err = parseLEB128Strings(section.Data()) + if err != nil { + return nil, fmt.Errorf("failed to parse version: %v", err) + } } } - + if g.compilerVersion == nil { + return nil, fmt.Errorf("Using a .wasm file compiled with an incompatible compiler version. Required custom section 'version' not found.") + } + versionMatches := false +outter: + for _, acceptVersion := range g.MatchingDockerImageTags() { + for _, compilerVersion := range g.compilerVersion { + if compilerVersion == acceptVersion { + versionMatches = true + break outter + } + } + } + if !versionMatches { + return nil, fmt.Errorf("Compiler version(s) no match found. Accepted: '%v'. Found: '%v'", + strings.Join(g.MatchingDockerImageTags(), ", "), strings.Join(g.compilerVersion, ", "), + ) + } if g.ruleNames == nil { return nil, fmt.Errorf("required custom section 'ruleNames' not found") } - // Instantiate the module g.module, err = g.runtime.InstantiateModule(g.ctx, compiledModule, wazero.NewModuleConfig()) if err != nil { return nil, fmt.Errorf("error instantiating module: %v", err) } - // Build the ruleIds map g.ruleIds = make(map[string]int, len(g.ruleNames)) for i, name := range g.ruleNames { g.ruleIds[name] = i } - return g, nil } @@ -128,7 +145,6 @@ func parseLEB128Strings(data []byte) ([]string, error) { if len(data) == 0 { return nil, fmt.Errorf("empty custom section data") } - numUint64, bytesRead := binary.Uvarint(data) if bytesRead <= 0 { return nil, fmt.Errorf("failed to read count: %v", io.ErrUnexpectedEOF) @@ -136,10 +152,8 @@ func parseLEB128Strings(data []byte) ([]string, error) { if numUint64 > uint64(^uint32(0)) { return nil, fmt.Errorf("count exceeds maximum uint32 value") } - num := uint32(numUint64) data = data[bytesRead:] - result := make([]string, num) for i := uint32(0); i < num; i++ { lenUint64, bytesRead := binary.Uvarint(data) @@ -149,18 +163,14 @@ func parseLEB128Strings(data []byte) ([]string, error) { if lenUint64 > uint64(^uint32(0)) { return nil, fmt.Errorf("string length exceeds maximum uint32 value") } - strLen := uint32(lenUint64) data = data[bytesRead:] - if uint64(len(data)) < uint64(strLen) { return nil, fmt.Errorf("buffer too small to read string bytes") } - result[i] = string(data[:strLen]) data = data[strLen:] } - return result, nil } @@ -204,7 +214,6 @@ func (g *Grammar) writeOffset(val uint64) { func (g *Grammar) Match(input string, startRule ...string) (*MatchResult, error) { g.input = input g.inputUTF16 = utf16.Encode([]rune(input)) - // Resolve the rule ID var ruleId uint64 startExpr := "" @@ -216,22 +225,18 @@ func (g *Grammar) Match(input string, startRule ...string) (*MatchResult, error) } ruleId = uint64(id) } - // Snapshot the heap bump pointer before the match. heapWatermark := g.readOffset() - // Call match(inputLength, startRuleId) matchFunc := g.module.ExportedFunction("match") if matchFunc == nil { return nil, fmt.Errorf("match function not exported by module") } - inputLength := uint64(len(g.inputUTF16)) results, err := matchFunc.Call(g.ctx, inputLength, ruleId) if err != nil { return nil, fmt.Errorf("error calling match function: %v", err) } - result := &MatchResult{ grammar: g, input: input, @@ -301,31 +306,26 @@ func (r *MatchResult) cstContext() *cstContext { // GetCstRoot returns the root CST node by using bindingsAt(0) and handling // the $spaces leading node, mirroring miniohm.ts _getCstRoot. -func (r *MatchResult) GetCstRoot() (*CstNode, error) { +func (r *MatchResult) GetCstRoot() (Node, error) { g := r.grammar ctx := r.cstContext() - bindingsAtFunc := g.module.ExportedFunction("bindingsAt") if bindingsAtFunc == nil { return nil, fmt.Errorf("bindingsAt function not exported") } - getBindingsLengthFunc := g.module.ExportedFunction("getBindingsLength") if getBindingsLengthFunc == nil { return nil, fmt.Errorf("getBindingsLength function not exported") } - // Get first binding results, err := bindingsAtFunc.Call(g.ctx, 0) if err != nil { return nil, fmt.Errorf("error calling bindingsAt(0): %v", err) } firstNode := newCstNode(ctx, uint32(results[0]), 0) - if firstNode.CtorName() != "$spaces" { return firstNode, nil } - // If first node is $spaces, the actual root is at binding 1 lenResults, err := getBindingsLengthFunc.Call(g.ctx) if err != nil { @@ -334,7 +334,6 @@ func (r *MatchResult) GetCstRoot() (*CstNode, error) { if lenResults[0] <= 1 { return nil, fmt.Errorf("expected more than 1 binding, got %d", lenResults[0]) } - results, err = bindingsAtFunc.Call(g.ctx, 1) if err != nil { return nil, fmt.Errorf("error calling bindingsAt(1): %v", err) @@ -345,26 +344,22 @@ func (r *MatchResult) GetCstRoot() (*CstNode, error) { // GetAllBindings returns all top-level binding nodes from the match. // For syntactic start rules, this is [$spaces, root]. // For lexical start rules, this is just [root]. -func (r *MatchResult) GetAllBindings() ([]*CstNode, error) { +func (r *MatchResult) GetAllBindings() ([]Node, error) { g := r.grammar ctx := r.cstContext() - bindingsAtFunc := g.module.ExportedFunction("bindingsAt") if bindingsAtFunc == nil { return nil, fmt.Errorf("bindingsAt function not exported") } - getBindingsLengthFunc := g.module.ExportedFunction("getBindingsLength") if getBindingsLengthFunc == nil { return nil, fmt.Errorf("getBindingsLength function not exported") } - lenResults, err := getBindingsLengthFunc.Call(g.ctx) if err != nil { return nil, fmt.Errorf("error calling getBindingsLength: %v", err) } numBindings := int(lenResults[0]) - // Determine leading spaces offset (for syntactic start rules in pos-only mode, // there is no $spaces binding, but the root node starts after leading spaces). startIdx := 0 @@ -374,8 +369,7 @@ func (r *MatchResult) GetAllBindings() ([]*CstNode, error) { startIdx = spacesLen } } - - nodes := make([]*CstNode, numBindings) + nodes := make([]Node, numBindings) for i := 0; i < numBindings; i++ { results, err := bindingsAtFunc.Call(g.ctx, uint64(i)) if err != nil { @@ -385,7 +379,6 @@ func (r *MatchResult) GetAllBindings() ([]*CstNode, error) { nodes[i] = node startIdx += node.MatchLength() } - return nodes, nil } @@ -418,18 +411,15 @@ func (g *Grammar) fillInputBuffer(ctx context.Context, mod api.Module, dest, len if memory == nil { panic("WebAssembly module has no memory") } - // Write UTF-16LE code units numUnits := uint32(len(g.inputUTF16)) if length < numUnits { numUnits = length } - for i := uint32(0); i < numUnits; i++ { offset := dest + i*2 memory.WriteUint16Le(offset, g.inputUTF16[i]) } - return numUnits } @@ -456,7 +446,6 @@ func (g *Grammar) matchUnicodeChar(ctx context.Context, mod api.Module, category if int(pos) >= len(g.inputUTF16) { return 0 } - // Decode the rune at pos (may be a surrogate pair) codeUnit := g.inputUTF16[pos] var r rune @@ -467,7 +456,6 @@ func (g *Grammar) matchUnicodeChar(ctx context.Context, mod api.Module, category } else { r = rune(codeUnit) } - // Check each category bit for bit := 0; bit < 32; bit++ { if categoryBitmap&(1<= len(g.strings) { return 0 } - str := g.strings[stringIdx] pos := g.readPos() - // Build a regex for case-insensitive match pattern := "(?i)" + regexp.QuoteMeta(str) re := regexp.MustCompile(pattern) - // Convert input from pos onward back to a Go string for matching remaining := g.inputUTF16[pos:] remainingStr := string(utf16.Decode(remaining)) - loc := re.FindStringIndex(remainingStr) if loc == nil || loc[0] != 0 { return 0 } - // Advance pos by the number of UTF-16 code units consumed matched := remainingStr[:loc[1]] matchedUTF16 := utf16.Encode([]rune(matched)) @@ -524,12 +506,10 @@ func (g *Grammar) Close() error { return err } } - if g.runtime != nil { if err := g.runtime.Close(g.ctx); err != nil { return err } } - return nil } diff --git a/packages/compiler/test/go/grammar_test.go b/golang/runtime/grammar_test.go similarity index 71% rename from packages/compiler/test/go/grammar_test.go rename to golang/runtime/grammar_test.go index e7d6ae0a..bada5d69 100644 --- a/packages/compiler/test/go/grammar_test.go +++ b/golang/runtime/grammar_test.go @@ -1,4 +1,4 @@ -package main +package goohm import ( "context" @@ -10,20 +10,20 @@ import ( // unparseAll walks all binding nodes and reconstructs the full input text. // It includes implicit leading/trailing spaces. -func unparseAll(nodes []*CstNode) string { +func unparseAll(nodes []Node) string { if len(nodes) == 0 { return "" } var result strings.Builder - ctx := nodes[0].ctx + ctx := nodes[0].CstCtx() startIdx := 0 for _, node := range nodes { // Emit leading spaces before this binding node. - if node.startIdx > startIdx { - result.WriteString(string(utf16.Decode(ctx.inputUTF16[startIdx:node.startIdx]))) + if node.StartIdx() > startIdx { + result.WriteString(string(utf16.Decode(ctx.inputUTF16[startIdx:node.StartIdx()]))) } unparseNode(node, &result) - startIdx = node.startIdx + node.MatchLength() + startIdx = node.StartIdx() + node.MatchLength() } // Emit any trailing content (e.g., trailing whitespace after the last binding). if startIdx < len(ctx.inputUTF16) { @@ -31,46 +31,43 @@ func unparseAll(nodes []*CstNode) string { } return result.String() } - -func unparseNode(node *CstNode, result *strings.Builder) { - if node.IsTerminal() { - result.WriteString(node.Value()) +func unparseNode(node Node, result *strings.Builder) { + if term, is := node.(TerminalNode); is { + result.WriteString(term.Value()) return } children := node.Children() - startIdx := node.startIdx + startIdx := node.StartIdx() for _, child := range children { // Emit any implicit spaces before this child. - if child.startIdx > startIdx { - spacesLen := child.startIdx - startIdx - if spacesLen > 0 && spacesLen+startIdx <= len(node.ctx.inputUTF16) { - result.WriteString(string(utf16.Decode(node.ctx.inputUTF16[startIdx : startIdx+spacesLen]))) + if int(child.StartIdx()) > startIdx { + spacesLen := int(child.StartIdx()) - startIdx + if spacesLen > 0 && spacesLen+startIdx <= len(node.CstCtx().inputUTF16) { + result.WriteString(string(utf16.Decode(node.CstCtx().inputUTF16[startIdx : startIdx+spacesLen]))) } } unparseNode(child, result) - startIdx = child.startIdx + child.MatchLength() + startIdx = int(child.StartIdx()) + child.MatchLength() } } +//go:generate sh ./generate.sh func BenchmarkES5Match(b *testing.B) { ctx := context.Background() - wasmPath := os.Getenv("OHM_WASM") if wasmPath == "" { - wasmPath = "../../build/es5.wasm" + wasmPath = "./es5.wasm" } wasmBytes, err := os.ReadFile(wasmPath) if err != nil { b.Fatalf("reading wasm file: %v", err) } - g, err := NewGrammar(ctx, wasmBytes) if err != nil { b.Fatalf("instantiating grammar: %v", err) } defer g.Close() - - input, err := os.ReadFile("../data/_underscore-1.8.3.js") + input, err := os.ReadFile("../../packages/compiler/test/data/_underscore-1.8.3.js") if err != nil { b.Fatalf("reading input file: %v", err) } @@ -87,45 +84,37 @@ func BenchmarkES5Match(b *testing.B) { result.Close() } } - func TestES5Match(t *testing.T) { ctx := context.Background() - wasmPath := os.Getenv("OHM_WASM") if wasmPath == "" { - wasmPath = "../../build/es5.wasm" + wasmPath = "./es5.wasm" } wasmBytes, err := os.ReadFile(wasmPath) if err != nil { t.Fatalf("reading wasm file: %v", err) } - g, err := NewGrammar(ctx, wasmBytes) if err != nil { t.Fatalf("instantiating grammar: %v", err) } defer g.Close() - - input, err := os.ReadFile("../data/_html5shiv-3.7.3.js") + input, err := os.ReadFile("../../packages/compiler/test/data/_html5shiv-3.7.3.js") if err != nil { t.Fatalf("reading input file: %v", err) } - result, err := g.Match(string(input)) if err != nil { t.Fatalf("matching: %v", err) } defer result.Close() - if !result.Succeeded() { t.Fatal("match failed") } - nodes, err := result.GetAllBindings() if err != nil { t.Fatalf("getting bindings: %v", err) } - unparsed := unparseAll(nodes) if unparsed != string(input) { t.Errorf("unparsed text does not match input (got %d bytes, want %d bytes)", len(unparsed), len(input)) diff --git a/golang/runtime/visitor_utils.go b/golang/runtime/visitor_utils.go new file mode 100644 index 00000000..71db382e --- /dev/null +++ b/golang/runtime/visitor_utils.go @@ -0,0 +1,225 @@ +package goohm + +import ( + "fmt" + "reflect" + "runtime" + "strings" +) + +// type TerminalVisitor[P, R any] interface { +// Terminal(payload P, node *TerminalNode) (result R) +// } + +type TerminalVisitor interface { + Terminal(node TerminalNode) +} + +type Acceptor[P, R any] interface { + Accept(visitor any, payload P) (result R) +} + +type BuiltinVisitor interface { + BuiltInRule(node Node) +} + +// SkipCheckName is a marker interface that opts a visitor type out of the +// runtime method-signature validation performed by [CheckName]. +// +// Implement this interface on a visitor struct when you want to bypass the +// check — for example, while prototyping a visitor whose Visit* methods are +// not yet in their final form, or when a visitor intentionally deviates from +// the expected signature conventions. +// +// Usage: +// +// var _ goohm.SkipCheckName = MyVisitor{} +// +// func (MyVisitor) SkipCheckName() {} +type SkipCheckName interface { + SkipCheckName() +} + +// Extract elements from a NonemptyListOf/EmptyListOf/ListOf CST node. +// see packages/compiler/src/buildGrammar.ts:46 +func ListOfElement(node Node) []Node { + // fmt.Printf("\n\n") + name := node.CtorName() + idx := strings.Index(name, "<") + name = name[:idx] + switch name { + case "EmptyListOf": + fallthrough + case "emptyListOf": + return []Node{} + case "NonemptyListOf": + fallthrough + case "nonemptyListOf": + first := node.Children()[0] + restList := node.Children()[1] // (sep elem)* + kids := make([]Node, 0, len(restList.Children())+1) + kids = append(kids, first) + // fmt.Printf("!%v\n", first) + // TODO implement using i % 2 != 0 + for i, seqNode := range restList.Children() { + ctor := seqNode.CtorName() + if ctor == "_list" { + panic("????") + } + if ctor[:1] != "_" { + _ = i + // fmt.Printf("* %d %v\n", i, seqNode) + kids = append(kids, seqNode) + } + // fmt.Printf("!!%d %d %v\n", i, len(seqNode.Children()), seqNode) + // if seqNode.Children() == nil || len(seqNode.Children()) == 0 { + // continue + // } + // fmt.Printf("*%v\n", seqNode.Children()[0]) + // kids = append(kids, seqNode.Children()[0]) + } + return kids + case "ListOf": + fallthrough + case "listOf": + // fmt.Printf("!!!%v\n", node.Children()[0]) + return ListOfElement(node.Children()[0]) + } + panic(fmt.Sprintf("Expected ListOf node, got %s", name)) +} + +func AcceptBuiltinHOR[R any](node Node, fn_elem func(Node) R, fn_sep func(Node) R) { + name := node.CtorName() + idx := strings.Index(name, "<") + name = name[:idx] + switch name { + case "EmptyListOf": + fallthrough + case "emptyListOf": + return + case "NonemptyListOf": + fallthrough + case "nonemptyListOf": + first := node.Children()[0] + fn_elem(first) + restList := node.Children()[1] // (sep elem)* + kids := make([]Node, 0, len(restList.Children())+1) + kids = append(kids, first) + // fmt.Printf("!%v\n", first) + // TODO implement using i % 2 != 0 + for i, n := range restList.Children() { + if i%2 == 0 { + fn_sep(n) + } else { + fn_elem(n) + } + // ctor := n.CtorName() + // if ctor == "_list" { + // panic("????") + // } + // if ctor[:1] != "_" { + // _ = i + // // fmt.Printf("* %d %v\n", i, seqNode) + // kids = append(kids, n) + // } + // // fmt.Printf("!!%d %d %v\n", i, len(seqNode.Children()), seqNode) + // // if seqNode.Children() == nil || len(seqNode.Children()) == 0 { + // // continue + // // } + // // fmt.Printf("*%v\n", seqNode.Children()[0]) + // // kids = append(kids, seqNode.Children()[0]) + } + return + case "ListOf": + fallthrough + case "listOf": + // fmt.Printf("!!!%v\n", node.Children()[0]) + AcceptBuiltinHOR(node.Children()[0], fn_elem, fn_sep) + return + } + panic(fmt.Sprintf("Expected ListOf node, got %s", name)) +} + +func AssertRule(node Node, rule string) { + if node.CtorName() != rule { + s, f := node.Source() + panic(fmt.Errorf("excepted %s, got %s. %d-%d", rule, node.CtorName(), s, f)) + } +} + +func CheckName[T any](v any) { + if _, skip := v.(SkipCheckName); skip { + return + } + if v == nil { + return + } + typeStr := fmt.Sprintf("%v", reflect.TypeFor[T]()) + dotIdx := strings.Index(typeStr, ".") + osbIdx := strings.Index(typeStr, "[") + csbIdx := strings.LastIndex(typeStr, "]") + var ( + methodName string + ) + if dotIdx > -1 && osbIdx > -1 && csbIdx > -1 { + methodName = "Visit" + typeStr[dotIdx+1+len("Visitor"):osbIdx] + } else { + panic("unable to extract method name a signature from type. " + typeStr) + } + if meth, exist := reflect.TypeOf(v).MethodByName(methodName); exist { + var ( + signature string + payload string + result string + ) + signature = typeStr[osbIdx+1 : csbIdx] + payload, result = getTypeNames(signature) + rule := methodName[len("Visit"):] + received := fmt.Sprintf("%v", meth.Type) + // get the stack trace and add the 4th frame to the error message to help debugging + _, file, line, _ := runtime.Caller(3) + see := fmt.Sprintf("%s:%d", file, line) + panic(fmt.Sprintf(`%[1]s. Found method by name match, but incompatibles types. + expected func(, %[3]s, %[5]s[%[3]s,%[4]s]) %[4]s + received %[2]s + For the likely call sight see: + %[6]s + + Note: + **For advanced use-cases** with a heterogeneous set of visitor methods a cast of the node can be useful. + Note that the cast is generally on the parent node in the CST, and a specific Accept method will be called. + eg from the collect_vast visitor code: + ((*RuleDefine[any, string])(unsafe.Pointer(node))).AcceptRuleDescr(c, payload) + + **To skip this check**, which is not advised, the visitor can implement the SkipCheckName interface. + ie implement the method SkipCheckName(). + `, methodName, received, payload, result, rule, see)) + } +} + +func AssertName(this Node, name string) { + if this.CtorName() != name { + panic(fmt.Errorf(`name didn't name. +expected '%s' +received '%s' +`, name, this.CtorName())) + } +} + +// parse "type, type" into two strings, where type could contain generics ie "name[*,*]" +func getTypeNames(inner string) (string, string) { + depth := 0 + for i, c := range inner { + switch c { + case '[': + depth++ + case ']': + depth-- + case ',': + if depth == 0 { + return strings.TrimSpace(inner[:i]), strings.TrimSpace(inner[i+1:]) + } + } + } + panic("getTypeNames: could not find comma separator in: " + inner) +} diff --git a/packages/compiler/package.json b/packages/compiler/package.json index d70fc15a..3ccee5b6 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@ohm-js/compiler", - "version": "18.0.0-beta.10", + "version": "18.0.0-beta.15", "description": "Compile Ohm.js grammars to WebAssembly", "main": "dist/index.js", "exports": { diff --git a/packages/compiler/src/Compiler.ts b/packages/compiler/src/Compiler.ts index 3b6af036..8c911257 100644 --- a/packages/compiler/src/Compiler.ts +++ b/packages/compiler/src/Compiler.ts @@ -3,6 +3,7 @@ import * as pexprs from 'ohm-js-legacy/src/pexprs-build.js'; import {Grammar as ParsedGrammar} from 'ohm-js-legacy/src/Grammar.js'; // import wabt from 'wabt'; +import pkg from '../package.json' with {type: 'json'}; import * as ir from './ir.ts'; import type {Expr} from './ir.ts'; import * as prebuilt from '../build/ohmRuntime.wasm_sections.ts'; @@ -1698,6 +1699,7 @@ export class Compiler { mergeSections(w.SECTION_ID_CODE, adjustedCodesec, codes), w.customsec(this.buildStringTable('ruleNames', ruleNames)), w.customsec(this.buildStringTable('strings', this._strings)), + w.customsec(this.buildStringTable('version', [pkg.version])), w.customsec( w.custom( w.name('syntacticRules'), diff --git a/packages/compiler/test/go/go.mod b/packages/compiler/test/go/go.mod deleted file mode 100644 index 431e736e..00000000 --- a/packages/compiler/test/go/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/ohmjs/ohm/packages/compiler/test/go - -go 1.20 - -require github.com/tetratelabs/wazero v1.6.0 diff --git a/packages/compiler/test/go/go.sum b/packages/compiler/test/go/go.sum deleted file mode 100644 index a9e284f5..00000000 --- a/packages/compiler/test/go/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g= -github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= diff --git a/packages/compiler/tsconfig.json b/packages/compiler/tsconfig.json index 8717b89f..09272f63 100644 --- a/packages/compiler/tsconfig.json +++ b/packages/compiler/tsconfig.json @@ -17,6 +17,7 @@ // [end overrides] }, "include": [ + "package.json", "src/**/*", "test/**/*.ts", "scripts/**/*.ts", diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 60296b47..0bfedfde 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "ohm-js", - "version": "18.0.0-beta.10", + "version": "18.0.0-beta.13", "description": "Ohm runtime — CST nodes, Grammar, and MatchResult", "keywords": ["parser", "parsing", "ohm", "ohm-js", "runtime"], "homepage": "https://github.com/ohmjs/ohm#readme",