mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
go.mod attempt
This commit is contained in:
parent
11f61615ea
commit
343bc13612
958 changed files with 474 additions and 229701 deletions
29
go/build-dsl
29
go/build-dsl
|
|
@ -13,27 +13,28 @@ if [ $# -eq 1 ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
export GOPATH=$(pwd)
|
||||
|
||||
# Build the bin/gocc executable:
|
||||
go get github.com/goccmack/gocc
|
||||
###### go get github.com/goccmack/gocc
|
||||
mkdir -p ./bin
|
||||
go build github.com/goccmack/gocc
|
||||
mv gocc ./bin/
|
||||
|
||||
rm -f src/miller/parsing/*.txt
|
||||
rm -f src/parsing/*.txt
|
||||
if [ "$verbose" = "true" ]; then
|
||||
lr1="src/miller/parsing/LR1_conflicts.txt"
|
||||
bin/gocc -v -o src/miller/parsing src/miller/parsing/mlr.bnf || expand -2 $lr1
|
||||
lr1="src/parsing/LR1_conflicts.txt"
|
||||
./bin/gocc -v -o ./src/parsing -p miller/src/parsing src/parsing/mlr.bnf || expand -2 $lr1
|
||||
else
|
||||
bin/gocc -o src/miller/parsing src/miller/parsing/mlr.bnf
|
||||
./bin/gocc -o ./src/parsing -p miller/src/parsing src/parsing/mlr.bnf
|
||||
fi
|
||||
|
||||
# Code-gen directories:
|
||||
# src/miller/parsing/errors/
|
||||
# src/miller/parsing/lexer/
|
||||
# src/miller/parsing/parser/
|
||||
# src/miller/parsing/token/
|
||||
# src/miller/parsing/util/
|
||||
# src/parsing/errors/
|
||||
# src/parsing/lexer/
|
||||
# src/parsing/parser/
|
||||
# src/parsing/token/
|
||||
# src/parsing/util/
|
||||
|
||||
# Override GOCC codegen with customized error handling
|
||||
cp src/miller/parsing/errors.go.template src/miller/parsing/errors/errors.go
|
||||
cp src/parsing/errors.go.template src/parsing/errors/errors.go
|
||||
|
||||
for x in src/miller/parsing/*/*.go; do gofmt -w $x; done
|
||||
for x in src/parsing/*/*.go; do gofmt -w $x; done
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
export GOPATH=$(pwd)
|
||||
|
||||
# Override GOCC codegen with customized error handling
|
||||
cp src/miller/parsing/errors.go.template src/miller/parsing/errors/errors.go
|
||||
cp src/parsing/errors.go.template src/parsing/errors/errors.go
|
||||
|
||||
go build mlr.go
|
||||
cp mlr mlrgo
|
||||
|
|
|
|||
8
go/go.mod
Normal file
8
go/go.mod
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
module miller
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/goccmack/gocc v0.0.0-20210201103733-1bd198f09019 // indirect
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
|
||||
)
|
||||
35
go/go.sum
Normal file
35
go/go.sum
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
github.com/goccmack/gocc v0.0.0-20210201103733-1bd198f09019 h1:frVuW4LszXD/AjX9dC1y4I+GwTjZMl6153O2mk/lmHo=
|
||||
github.com/goccmack/gocc v0.0.0-20210201103733-1bd198f09019/go.mod h1:ZjwYs2UwOh6NiluQ1XCoKNLVECdeFf33rrGEZ+IpNq4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
|
@ -6,9 +6,9 @@ import (
|
|||
"runtime"
|
||||
"runtime/pprof"
|
||||
|
||||
"miller/auxents"
|
||||
"miller/cli"
|
||||
"miller/stream"
|
||||
"miller/src/auxents"
|
||||
"miller/src/cli"
|
||||
"miller/src/stream"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/src/dsl"
|
||||
|
||||
"experimental/lexer"
|
||||
"experimental/parser"
|
||||
|
|
|
|||
6
go/src/README-old.mv
Normal file
6
go/src/README-old.mv
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
* Miller dependencies are all in the Go standard library, except a local one:
|
||||
* `src/github.com/goccmack`
|
||||
* GOCC lexer/parser code-generator from [github.com/goccmack/gocc](https://github.com/goccmack/gocc):
|
||||
* This package defines the grammar for Miller's domain-specific language (DSL) for the Miller `put` and `filter` verbs. And, GOCC is a joy to use. :)
|
||||
* Note on the path: `go get github.com/goccmack/gocc` uses this directory path, and is nice enough to also create `bin/gocc` for me -- so I thought I would just let it continue to do that by using that local path. :)
|
||||
* I kept this locally so I could source-control it along with Miller and guarantee its stability. It is used on the terms of its open-source license.
|
||||
|
|
@ -1,6 +1 @@
|
|||
* Miller dependencies are all in the Go standard library, except a local one:
|
||||
* `src/github.com/goccmack`
|
||||
* GOCC lexer/parser code-generator from [github.com/goccmack/gocc](https://github.com/goccmack/gocc):
|
||||
* This package defines the grammar for Miller's domain-specific language (DSL) for the Miller `put` and `filter` verbs. And, GOCC is a joy to use. :)
|
||||
* Note on the path: `go get github.com/goccmack/gocc` uses this directory path, and is nice enough to also create `bin/gocc` for me -- so I thought I would just let it continue to do that by using that local path. :)
|
||||
* I kept this locally so I could source-control it along with Miller and guarantee its stability. It is used on the terms of its open-source license.
|
||||
Please see [go/README.md](https://github.com/johnkerl/miller/blob/master/go/README.md) for an overview; please see each subdirectory for details about it.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
|
||||
"miller/auxents/repl"
|
||||
"miller/src/auxents/repl"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,10 +8,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/parsing/lexer"
|
||||
"miller/parsing/parser"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/parsing/lexer"
|
||||
"miller/src/parsing/parser"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"miller/types"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -27,8 +27,8 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"miller/cli"
|
||||
"miller/cliutil"
|
||||
"miller/src/cli"
|
||||
"miller/src/cliutil"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
"golang.org/x/term"
|
||||
|
||||
"miller/version"
|
||||
"miller/src/version"
|
||||
)
|
||||
|
||||
const ENV_PRIMARY_PROMPT = "MLR_REPL_PS1"
|
||||
|
|
@ -26,12 +26,12 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
|
||||
"miller/cliutil"
|
||||
"miller/dsl/cst"
|
||||
"miller/input"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/cliutil"
|
||||
"miller/src/dsl/cst"
|
||||
"miller/src/input"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -7,12 +7,12 @@ package repl
|
|||
import (
|
||||
"os"
|
||||
|
||||
"miller/cliutil"
|
||||
"miller/dsl/cst"
|
||||
"miller/input"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/cliutil"
|
||||
"miller/src/dsl/cst"
|
||||
"miller/src/input"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -10,9 +10,9 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"miller/dsl/cst"
|
||||
"miller/lib"
|
||||
"miller/types"
|
||||
"miller/src/dsl/cst"
|
||||
"miller/src/lib"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,12 +8,12 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"miller/cliutil"
|
||||
"miller/dsl/cst"
|
||||
"miller/lib"
|
||||
"miller/transformers"
|
||||
"miller/transforming"
|
||||
"miller/version"
|
||||
"miller/src/cliutil"
|
||||
"miller/src/dsl/cst"
|
||||
"miller/src/lib"
|
||||
"miller/src/transformers"
|
||||
"miller/src/transforming"
|
||||
"miller/src/version"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -4,9 +4,9 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/lib"
|
||||
"miller/transformers"
|
||||
"miller/transforming"
|
||||
"miller/src/lib"
|
||||
"miller/src/transformers"
|
||||
"miller/src/transforming"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/lib"
|
||||
"miller/version"
|
||||
"miller/src/lib"
|
||||
"miller/src/version"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/lib"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// For flags with values, e.g. ["-n" "10"], while we're looking at the "-n"
|
||||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/lib"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
const ASV_FS = "\x1f"
|
||||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
|
||||
"miller/lib"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// For flags with values, e.g. ["-n" "10"], while we're looking at the "-n" this let us see if the "10" slot exists.
|
||||
|
|
@ -10,8 +10,8 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"miller/lib"
|
||||
"miller/parsing/token"
|
||||
"miller/src/lib"
|
||||
"miller/src/parsing/token"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -6,9 +6,9 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/parsing/lexer"
|
||||
"miller/parsing/parser"
|
||||
"miller/src/dsl"
|
||||
"miller/src/parsing/lexer"
|
||||
"miller/src/parsing/parser"
|
||||
)
|
||||
|
||||
func testSingle(sourceString []byte) (*dsl.AST, error) {
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
package dsl
|
||||
|
||||
import (
|
||||
"miller/parsing/token"
|
||||
"miller/src/parsing/token"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -5,9 +5,9 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -8,9 +8,9 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -11,8 +11,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"miller/lib"
|
||||
"miller/types"
|
||||
"miller/src/lib"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
type TFunctionClass string
|
||||
|
|
@ -8,10 +8,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -6,10 +6,10 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,10 +8,10 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
type CondBlockNode struct {
|
||||
|
|
@ -22,11 +22,11 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -34,11 +34,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -9,11 +9,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -10,10 +10,10 @@ package cst
|
|||
import (
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
type EnvironmentVariableNode struct {
|
||||
|
|
@ -11,10 +11,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -5,9 +5,9 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -7,10 +7,10 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -7,10 +7,10 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,10 +8,10 @@ import (
|
|||
"errors"
|
||||
"math"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -10,10 +10,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -10,11 +10,11 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -11,12 +11,12 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/cliutil"
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/cliutil"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/types"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,7 +8,7 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/src/dsl"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
package cst
|
||||
|
||||
import (
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,11 +8,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/output"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/output"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -7,10 +7,10 @@ package cst
|
|||
import (
|
||||
"container/list"
|
||||
|
||||
"miller/cliutil"
|
||||
"miller/dsl"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/cliutil"
|
||||
"miller/src/dsl"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -9,10 +9,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -8,10 +8,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/types"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
"miller/src/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -10,8 +10,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -7,9 +7,9 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
"miller/src/dsl"
|
||||
"miller/src/lib"
|
||||
"miller/src/runtime"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -1 +0,0 @@
|
|||
fmt.Fprintf
|
||||
3
go/src/github.com/goccmack/gocc/.gitignore
vendored
3
go/src/github.com/goccmack/gocc/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
gocc
|
||||
sm_*
|
||||
.vscode
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
Copyright 2012 Vastech SA (PTY) LTD
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
# New
|
||||
Have a look at [https://github.com/goccmack/gogll](https://github.com/goccmack/gogll) for scannerless GLL parser generation.
|
||||
# Gocc
|
||||
|
||||
[](https://travis-ci.org/goccmack/gocc)
|
||||
|
||||
## Introduction
|
||||
|
||||
Gocc is a compiler kit for Go written in Go.
|
||||
|
||||
Gocc generates lexers and parsers or stand-alone DFAs or parsers from a BNF.
|
||||
|
||||
Lexers are DFAs, which recognise regular languages. Gocc lexers accept UTF-8 input.
|
||||
|
||||
Gocc parsers are PDAs, which recognise LR-1 languages. Optional LR1 conflict handling automatically resolves shift / reduce and reduce / reduce conflicts.
|
||||
|
||||
Generating a lexer and parser starts with creating a bnf file. Action expressions embedded in the BNF allows the user to specify semantic actions for syntax productions.
|
||||
|
||||
For complex applications the user typically uses an abstract syntax tree (AST) to represent the derivation of the input. The user provides a set of functions to construct the AST, which are called from the action expressions specified in the BNF.
|
||||
|
||||
See the [README](example/bools/README) for an included example.
|
||||
|
||||
[User Guide (PDF): Learn You a gocc for Great Good](https://raw.githubusercontent.com/goccmack/gocc/master/doc/gocc_user_guide.pdf) (gocc3 user guide will be published shortly)
|
||||
|
||||
## Installation
|
||||
|
||||
* First download and Install Go From http://golang.org/
|
||||
* Setup your GOPATH environment variable.
|
||||
* Next in your command line run: go get github.com/goccmack/gocc (go get will git clone gocc into GOPATH/src/github.com/goccmack/gocc and run go install)
|
||||
* Alternatively clone the source: https://github.com/goccmack/gocc . Followed by go install github.com/goccmack/gocc
|
||||
* Finally make sure that the bin folder where the gocc binary is located is in your PATH environment variable.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Once installed start by creating your BNF in a package folder.
|
||||
|
||||
For example GOPATH/src/foo/bar.bnf:
|
||||
|
||||
```
|
||||
/* Lexical Part */
|
||||
|
||||
id : 'a'-'z' {'a'-'z'} ;
|
||||
|
||||
!whitespace : ' ' | '\t' | '\n' | '\r' ;
|
||||
|
||||
/* Syntax Part */
|
||||
|
||||
<< import "foo/ast" >>
|
||||
|
||||
Hello: "hello" id << ast.NewWorld($1) >> ;
|
||||
```
|
||||
|
||||
Next to use gocc, run:
|
||||
|
||||
```sh
|
||||
cd $GOPATH/src/foo
|
||||
gocc bar.bnf
|
||||
```
|
||||
|
||||
This will generate a scanner, parser and token package inside GOPATH/src/foo Following times you might only want to run gocc without the scanner flag, since you might want to start making the scanner your own. Gocc is after all only a parser generator even if the default scanner is quite useful.
|
||||
|
||||
Next create ast.go file at $GOPATH/src/foo/ast with the following contents:
|
||||
|
||||
```go
|
||||
package ast
|
||||
|
||||
import (
|
||||
"foo/token"
|
||||
)
|
||||
|
||||
type Attrib interface {}
|
||||
|
||||
type World struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func NewWorld(id Attrib) (*World, error) {
|
||||
return &World{string(id.(*token.Token).Lit)}, nil
|
||||
}
|
||||
|
||||
func (this *World) String() string {
|
||||
return "hello " + this.Name
|
||||
}
|
||||
```
|
||||
|
||||
Finally we want to parse a string into the ast, so let us write a test at $GOPATH/src/foo/test/parse_test.go with the following contents:
|
||||
|
||||
```go
|
||||
package test
|
||||
|
||||
import (
|
||||
"foo/ast"
|
||||
"foo/lexer"
|
||||
"foo/parser"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWorld(t *testing.T) {
|
||||
input := []byte(`hello gocc`)
|
||||
lex := lexer.NewLexer(input)
|
||||
p := parser.NewParser()
|
||||
st, err := p.Parse(lex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w, ok := st.(*ast.World)
|
||||
if !ok {
|
||||
t.Fatalf("This is not a world")
|
||||
}
|
||||
if w.Name != `gocc` {
|
||||
t.Fatalf("Wrong world %v", w.Name)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally run the test:
|
||||
|
||||
```sh
|
||||
cd $GOPATH/src/foo/test
|
||||
go test -v
|
||||
```
|
||||
|
||||
You have now created your first grammar with gocc. This should now be relatively easy to change into the grammar you actually want to create or an existing LR1 grammar you would like to parse.
|
||||
|
||||
## BNF
|
||||
|
||||
The Gocc BNF is specified [here](spec/gocc2.ebnf)
|
||||
|
||||
An example bnf with action expressions can be found [here](example/bools/example.bnf)
|
||||
|
||||
## Action Expressions and AST
|
||||
|
||||
An action expression is specified as "<", "<", goccExpressionList , ">", ">" . The goccExpressionList is equivalent to a [goExpressionList](https://golang.org/ref/spec#ExpressionList). This expression list should return an Attrib and an error. Where Attrib is:
|
||||
|
||||
```go
|
||||
type Attrib interface {}
|
||||
```
|
||||
|
||||
Also parsed elements of the corresponding bnf rule can be represented in the expressionList as "$", digit.
|
||||
|
||||
Some action expression examples:
|
||||
|
||||
```
|
||||
<< $0, nil >>
|
||||
<< ast.NewFoo($1) >>
|
||||
<< ast.NewBar($3, $1) >>
|
||||
<< ast.TRUE, nil >>
|
||||
```
|
||||
|
||||
Contants, functions, etc. that are returned or called should be programmed by the user in his ast (Abstract Syntax Tree) package. The ast package requires that you define your own Attrib interface as shown above. All parameters passed to functions will be of this type.
|
||||
|
||||
Some example of functions:
|
||||
|
||||
```go
|
||||
func NewFoo(a Attrib) (*Foo, error) { ... }
|
||||
func NewBar(a, b Attrib) (*Bar, error) { ... }
|
||||
```
|
||||
|
||||
An example of an ast can be found [here](example/bools/ast/ast.go)
|
||||
|
||||
## Release Notes for gocc 2.1
|
||||
|
||||
### Changes
|
||||
|
||||
1. no_lexer option added to suppress generation of lexer. See the user guide.
|
||||
|
||||
2. Unreachable code removed from generated code.
|
||||
|
||||
### Bugs fixed:
|
||||
|
||||
1. gocc 2.1 does not support string_lit symbols with the same value as production names of the BNF. E.g. (t2.bnf):
|
||||
|
||||
```
|
||||
A : "a" | "A" ;
|
||||
```
|
||||
|
||||
string_lit "A" is not allowed.
|
||||
|
||||
Previously gocc silently ignored the conflicting string_lit. Now it generates an ugly panic:
|
||||
|
||||
```
|
||||
$ gocc t2.bnf
|
||||
panic: string_lit "A" conflicts with production name A
|
||||
```
|
||||
|
||||
This issue will be properly resolved in a future release.
|
||||
|
||||
## Users
|
||||
|
||||
These projects use gocc:
|
||||
|
||||
* [gogo](https://github.com/shivansh/gogo) - [BNF file](https://github.com/shivansh/gogo/blob/master/src/lang.bnf) - a Go to MIPS compiler written in Go
|
||||
* [gonum/gonum](https://github.com/gonum/gonum) - [BNF file](https://github.com/gonum/gonum/blob/master/graph/formats/dot/internal/dot.bnf) - DOT decoder (part of the graph library of Gonum)
|
||||
* [llir/llvm](https://github.com/llir/llvm) - [BNF file](https://github.com/llir/llvm/blob/master/asm/internal/ll.bnf) - LLVM IR library in pure Go
|
||||
* [mewmew/uc](https://github.com/mewmew/uc) - [BNF file](https://github.com/mewmew/uc/blob/master/gocc/uc.bnf) - A compiler for the µC language
|
||||
* [gographviz](https://github.com/awalterschulze/gographviz) - [BNF file](https://github.com/awalterschulze/gographviz/blob/master/dot.bnf) - Parses the Graphviz DOT language in golang
|
||||
* [katydid/relapse](http://katydid.github.io/) - [BNF file](https://github.com/katydid/katydid/blob/master/relapse/bnf/all.bnf) - Encoding agnostic validation language
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
*.aux
|
||||
*.log
|
||||
*.out
|
||||
*.toc
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 190 KiB |
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
pdflatex gocc_user_guide && pdflatex gocc_user_guide && pdflatex gocc_user_guide
|
||||
|
|
@ -1 +0,0 @@
|
|||
sm_*
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/* Lexical elements */
|
||||
|
||||
_letter : 'a'-'z' | 'A'-'Z' ;
|
||||
|
||||
_digit : '0'-'9' ;
|
||||
|
||||
_idchar : _letter | _digit | '_' ;
|
||||
|
||||
id : (_letter | '_') {_idchar} ;
|
||||
|
||||
!whitespace : ' ' | '\t' | '\n' | '\r' ;
|
||||
|
||||
/* Syntax elements */
|
||||
|
||||
<< import "github.com/goccmack/gocc/example/astx/ast" >>
|
||||
|
||||
StmtList :
|
||||
Stmt << ast.NewStmtList($0) >>
|
||||
| StmtList Stmt << ast.AppendStmt($0, $1) >>
|
||||
;
|
||||
|
||||
Stmt :
|
||||
id << ast.NewStmt($0) >>
|
||||
;
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"github.com/goccmack/gocc/example/astx/token"
|
||||
)
|
||||
|
||||
type (
|
||||
StmtList []Stmt
|
||||
Stmt string
|
||||
)
|
||||
|
||||
func NewStmtList(stmt interface{}) (StmtList, error) {
|
||||
return StmtList{stmt.(Stmt)}, nil
|
||||
}
|
||||
|
||||
func AppendStmt(stmtList, stmt interface{}) (StmtList, error) {
|
||||
return append(stmtList.(StmtList), stmt.(Stmt)), nil
|
||||
}
|
||||
|
||||
func NewStmt(stmtList interface{}) (Stmt, error) {
|
||||
return Stmt(stmtList.(*token.Token).Lit), nil
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package astx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/goccmack/gocc/example/astx/ast"
|
||||
"github.com/goccmack/gocc/example/astx/lexer"
|
||||
"github.com/goccmack/gocc/example/astx/parser"
|
||||
)
|
||||
|
||||
func TestPass(t *testing.T) {
|
||||
sml, err := test([]byte("a b c d e f"))
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
fmt.Printf("output: %s\n", sml)
|
||||
}
|
||||
|
||||
func TestFail(t *testing.T) {
|
||||
_, err := test([]byte("a b ; d e f"))
|
||||
if err == nil {
|
||||
t.Fatal("expected parse error")
|
||||
} else {
|
||||
fmt.Printf("Parsing failed as expected: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func test(src []byte) (astree ast.StmtList, err error) {
|
||||
fmt.Printf("input: %s\n", src)
|
||||
s := lexer.NewLexer(src)
|
||||
p := parser.NewParser()
|
||||
a, err := p.Parse(s)
|
||||
if err == nil {
|
||||
astree = a.(ast.StmtList)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
package astx
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/goccmack/gocc/example/astx/token"
|
||||
)
|
||||
|
||||
type ErrorSymbol interface {
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Err error
|
||||
ErrorToken *token.Token
|
||||
ErrorSymbols []ErrorSymbol
|
||||
ExpectedTokens []string
|
||||
StackTop int
|
||||
}
|
||||
|
||||
func (e *Error) String() string {
|
||||
w := new(strings.Builder)
|
||||
fmt.Fprintf(w, "Error")
|
||||
if e.Err != nil {
|
||||
fmt.Fprintf(w, " %s\n", e.Err)
|
||||
} else {
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit)
|
||||
fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column)
|
||||
fmt.Fprintf(w, "Expected one of: ")
|
||||
for _, sym := range e.ExpectedTokens {
|
||||
fmt.Fprintf(w, "%s ", sym)
|
||||
}
|
||||
fmt.Fprintf(w, "ErrorSymbol:\n")
|
||||
for _, sym := range e.ErrorSymbols {
|
||||
fmt.Fprintf(w, "%v\n", sym)
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
w := new(strings.Builder)
|
||||
fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String())
|
||||
if e.Err != nil {
|
||||
fmt.Fprintf(w, ": %+v", e.Err)
|
||||
} else {
|
||||
fmt.Fprintf(w, ", expected one of: ")
|
||||
for _, expected := range e.ExpectedTokens {
|
||||
fmt.Fprintf(w, "%s ", expected)
|
||||
}
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goccmack/gocc/example/astx/token"
|
||||
)
|
||||
|
||||
type ActionTable [NumStates]ActionRow
|
||||
|
||||
type ActionRow struct {
|
||||
Accept token.Type
|
||||
Ignore string
|
||||
}
|
||||
|
||||
func (a ActionRow) String() string {
|
||||
return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore)
|
||||
}
|
||||
|
||||
var ActTab = ActionTable{
|
||||
ActionRow{ // S0
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S1
|
||||
Accept: -1,
|
||||
Ignore: "!whitespace",
|
||||
},
|
||||
ActionRow{ // S2
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S3
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S4
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S5
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S6
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/goccmack/gocc/example/astx/token"
|
||||
)
|
||||
|
||||
const (
|
||||
NoState = -1
|
||||
NumStates = 7
|
||||
NumSymbols = 10
|
||||
)
|
||||
|
||||
type Lexer struct {
|
||||
src []byte
|
||||
pos int
|
||||
line int
|
||||
column int
|
||||
}
|
||||
|
||||
func NewLexer(src []byte) *Lexer {
|
||||
lexer := &Lexer{
|
||||
src: src,
|
||||
pos: 0,
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
return lexer
|
||||
}
|
||||
|
||||
func NewLexerFile(fpath string) (*Lexer, error) {
|
||||
src, err := ioutil.ReadFile(fpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewLexer(src), nil
|
||||
}
|
||||
|
||||
func (l *Lexer) Scan() (tok *token.Token) {
|
||||
tok = new(token.Token)
|
||||
if l.pos >= len(l.src) {
|
||||
tok.Type = token.EOF
|
||||
tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column
|
||||
return
|
||||
}
|
||||
start, startLine, startColumn, end := l.pos, l.line, l.column, 0
|
||||
tok.Type = token.INVALID
|
||||
state, rune1, size := 0, rune(-1), 0
|
||||
for state != -1 {
|
||||
if l.pos >= len(l.src) {
|
||||
rune1 = -1
|
||||
} else {
|
||||
rune1, size = utf8.DecodeRune(l.src[l.pos:])
|
||||
l.pos += size
|
||||
}
|
||||
|
||||
nextState := -1
|
||||
if rune1 != -1 {
|
||||
nextState = TransTab[state](rune1)
|
||||
}
|
||||
state = nextState
|
||||
|
||||
if state != -1 {
|
||||
|
||||
switch rune1 {
|
||||
case '\n':
|
||||
l.line++
|
||||
l.column = 1
|
||||
case '\r':
|
||||
l.column = 1
|
||||
case '\t':
|
||||
l.column += 4
|
||||
default:
|
||||
l.column++
|
||||
}
|
||||
|
||||
switch {
|
||||
case ActTab[state].Accept != -1:
|
||||
tok.Type = ActTab[state].Accept
|
||||
end = l.pos
|
||||
case ActTab[state].Ignore != "":
|
||||
start, startLine, startColumn = l.pos, l.line, l.column
|
||||
state = 0
|
||||
if start >= len(l.src) {
|
||||
tok.Type = token.EOF
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if tok.Type == token.INVALID {
|
||||
end = l.pos
|
||||
}
|
||||
}
|
||||
}
|
||||
if end > start {
|
||||
l.pos = end
|
||||
tok.Lit = l.src[start:end]
|
||||
} else {
|
||||
tok.Lit = []byte{}
|
||||
}
|
||||
tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Lexer) Reset() {
|
||||
l.pos = 0
|
||||
}
|
||||
|
||||
/*
|
||||
Lexer symbols:
|
||||
0: '_'
|
||||
1: '_'
|
||||
2: ' '
|
||||
3: '\t'
|
||||
4: '\n'
|
||||
5: '\r'
|
||||
6: 'a'-'z'
|
||||
7: 'A'-'Z'
|
||||
8: '0'-'9'
|
||||
9: .
|
||||
*/
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package lexer
|
||||
|
||||
/*
|
||||
Let s be the current state
|
||||
Let r be the current input rune
|
||||
transitionTable[s](r) returns the next state.
|
||||
*/
|
||||
type TransitionTable [NumStates]func(rune) int
|
||||
|
||||
var TransTab = TransitionTable{
|
||||
// S0
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case r == 9: // ['\t','\t']
|
||||
return 1
|
||||
case r == 10: // ['\n','\n']
|
||||
return 1
|
||||
case r == 13: // ['\r','\r']
|
||||
return 1
|
||||
case r == 32: // [' ',' ']
|
||||
return 1
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 2
|
||||
case r == 95: // ['_','_']
|
||||
return 3
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 2
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S1
|
||||
func(r rune) int {
|
||||
switch {
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S2
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case 48 <= r && r <= 57: // ['0','9']
|
||||
return 4
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 5
|
||||
case r == 95: // ['_','_']
|
||||
return 6
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 5
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S3
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case 48 <= r && r <= 57: // ['0','9']
|
||||
return 4
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 5
|
||||
case r == 95: // ['_','_']
|
||||
return 6
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 5
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S4
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case 48 <= r && r <= 57: // ['0','9']
|
||||
return 4
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 5
|
||||
case r == 95: // ['_','_']
|
||||
return 6
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 5
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S5
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case 48 <= r && r <= 57: // ['0','9']
|
||||
return 4
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 5
|
||||
case r == 95: // ['_','_']
|
||||
return 6
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 5
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
// S6
|
||||
func(r rune) int {
|
||||
switch {
|
||||
case 48 <= r && r <= 57: // ['0','9']
|
||||
return 4
|
||||
case 65 <= r && r <= 90: // ['A','Z']
|
||||
return 5
|
||||
case r == 95: // ['_','_']
|
||||
return 6
|
||||
case 97 <= r && r <= 122: // ['a','z']
|
||||
return 5
|
||||
}
|
||||
return NoState
|
||||
},
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
type (
|
||||
actionTable [numStates]actionRow
|
||||
actionRow struct {
|
||||
canRecover bool
|
||||
actions [numSymbols]action
|
||||
}
|
||||
)
|
||||
|
||||
var actionTab = actionTable{
|
||||
actionRow{ // S0
|
||||
canRecover: false,
|
||||
actions: [numSymbols]action{
|
||||
nil, // INVALID
|
||||
nil, // $
|
||||
shift(3), // id
|
||||
},
|
||||
},
|
||||
actionRow{ // S1
|
||||
canRecover: false,
|
||||
actions: [numSymbols]action{
|
||||
nil, // INVALID
|
||||
accept(true), // $
|
||||
shift(3), // id
|
||||
},
|
||||
},
|
||||
actionRow{ // S2
|
||||
canRecover: false,
|
||||
actions: [numSymbols]action{
|
||||
nil, // INVALID
|
||||
reduce(1), // $, reduce: StmtList
|
||||
reduce(1), // id, reduce: StmtList
|
||||
},
|
||||
},
|
||||
actionRow{ // S3
|
||||
canRecover: false,
|
||||
actions: [numSymbols]action{
|
||||
nil, // INVALID
|
||||
reduce(3), // $, reduce: Stmt
|
||||
reduce(3), // id, reduce: Stmt
|
||||
},
|
||||
},
|
||||
actionRow{ // S4
|
||||
canRecover: false,
|
||||
actions: [numSymbols]action{
|
||||
nil, // INVALID
|
||||
reduce(2), // $, reduce: StmtList
|
||||
reduce(2), // id, reduce: StmtList
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
const numNTSymbols = 3
|
||||
|
||||
type (
|
||||
gotoTable [numStates]gotoRow
|
||||
gotoRow [numNTSymbols]int
|
||||
)
|
||||
|
||||
var gotoTab = gotoTable{
|
||||
gotoRow{ // S0
|
||||
-1, // S'
|
||||
1, // StmtList
|
||||
2, // Stmt
|
||||
},
|
||||
gotoRow{ // S1
|
||||
-1, // S'
|
||||
-1, // StmtList
|
||||
4, // Stmt
|
||||
},
|
||||
gotoRow{ // S2
|
||||
-1, // S'
|
||||
-1, // StmtList
|
||||
-1, // Stmt
|
||||
},
|
||||
gotoRow{ // S3
|
||||
-1, // S'
|
||||
-1, // StmtList
|
||||
-1, // Stmt
|
||||
},
|
||||
gotoRow{ // S4
|
||||
-1, // S'
|
||||
-1, // StmtList
|
||||
-1, // Stmt
|
||||
},
|
||||
}
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
parseError "github.com/goccmack/gocc/example/astx/errors"
|
||||
"github.com/goccmack/gocc/example/astx/token"
|
||||
)
|
||||
|
||||
const (
|
||||
numProductions = 4
|
||||
numStates = 5
|
||||
numSymbols = 6
|
||||
)
|
||||
|
||||
// Stack
|
||||
|
||||
type stack struct {
|
||||
state []int
|
||||
attrib []Attrib
|
||||
}
|
||||
|
||||
const iNITIAL_STACK_SIZE = 100
|
||||
|
||||
func newStack() *stack {
|
||||
return &stack{
|
||||
state: make([]int, 0, iNITIAL_STACK_SIZE),
|
||||
attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stack) reset() {
|
||||
s.state = s.state[:0]
|
||||
s.attrib = s.attrib[:0]
|
||||
}
|
||||
|
||||
func (s *stack) push(state int, a Attrib) {
|
||||
s.state = append(s.state, state)
|
||||
s.attrib = append(s.attrib, a)
|
||||
}
|
||||
|
||||
func (s *stack) top() int {
|
||||
return s.state[len(s.state)-1]
|
||||
}
|
||||
|
||||
func (s *stack) peek(pos int) int {
|
||||
return s.state[pos]
|
||||
}
|
||||
|
||||
func (s *stack) topIndex() int {
|
||||
return len(s.state) - 1
|
||||
}
|
||||
|
||||
func (s *stack) popN(items int) []Attrib {
|
||||
lo, hi := len(s.state)-items, len(s.state)
|
||||
|
||||
attrib := s.attrib[lo:hi]
|
||||
|
||||
s.state = s.state[:lo]
|
||||
s.attrib = s.attrib[:lo]
|
||||
|
||||
return attrib
|
||||
}
|
||||
|
||||
func (s *stack) String() string {
|
||||
w := new(strings.Builder)
|
||||
fmt.Fprintf(w, "stack:\n")
|
||||
for i, st := range s.state {
|
||||
fmt.Fprintf(w, "\t%d: %d , ", i, st)
|
||||
if s.attrib[i] == nil {
|
||||
fmt.Fprintf(w, "nil")
|
||||
} else {
|
||||
switch attr := s.attrib[i].(type) {
|
||||
case *token.Token:
|
||||
fmt.Fprintf(w, "%s", attr.Lit)
|
||||
default:
|
||||
fmt.Fprintf(w, "%v", attr)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
||||
type Parser struct {
|
||||
stack *stack
|
||||
nextToken *token.Token
|
||||
pos int
|
||||
}
|
||||
|
||||
type Scanner interface {
|
||||
Scan() (tok *token.Token)
|
||||
}
|
||||
|
||||
func NewParser() *Parser {
|
||||
p := &Parser{stack: newStack()}
|
||||
p.Reset()
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) Reset() {
|
||||
p.stack.reset()
|
||||
p.stack.push(0, nil)
|
||||
}
|
||||
|
||||
func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) {
|
||||
errorAttrib = &parseError.Error{
|
||||
Err: err,
|
||||
ErrorToken: p.nextToken,
|
||||
ErrorSymbols: p.popNonRecoveryStates(),
|
||||
ExpectedTokens: make([]string, 0, 8),
|
||||
}
|
||||
for t, action := range actionTab[p.stack.top()].actions {
|
||||
if action != nil {
|
||||
errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t)))
|
||||
}
|
||||
}
|
||||
|
||||
if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil {
|
||||
p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil {
|
||||
recovered = true
|
||||
}
|
||||
for !recovered && p.nextToken.Type != token.EOF {
|
||||
p.nextToken = scanner.Scan()
|
||||
if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil {
|
||||
recovered = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) {
|
||||
if rs, ok := p.firstRecoveryState(); ok {
|
||||
errorSymbols := p.stack.popN(p.stack.topIndex() - rs)
|
||||
removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols))
|
||||
for i, e := range errorSymbols {
|
||||
removedAttribs[i] = e
|
||||
}
|
||||
} else {
|
||||
removedAttribs = []parseError.ErrorSymbol{}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// recoveryState points to the highest state on the stack, which can recover
|
||||
func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) {
|
||||
recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover
|
||||
for recoveryState > 0 && !canRecover {
|
||||
recoveryState--
|
||||
canRecover = actionTab[p.stack.peek(recoveryState)].canRecover
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Parser) newError(err error) error {
|
||||
e := &parseError.Error{
|
||||
Err: err,
|
||||
StackTop: p.stack.top(),
|
||||
ErrorToken: p.nextToken,
|
||||
}
|
||||
actRow := actionTab[p.stack.top()]
|
||||
for i, t := range actRow.actions {
|
||||
if t != nil {
|
||||
e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i)))
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) {
|
||||
p.Reset()
|
||||
p.nextToken = scanner.Scan()
|
||||
for acc := false; !acc; {
|
||||
action := actionTab[p.stack.top()].actions[p.nextToken.Type]
|
||||
if action == nil {
|
||||
if recovered, errAttrib := p.Error(nil, scanner); !recovered {
|
||||
p.nextToken = errAttrib.ErrorToken
|
||||
return nil, p.newError(nil)
|
||||
}
|
||||
if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil {
|
||||
panic("Error recovery led to invalid action")
|
||||
}
|
||||
}
|
||||
|
||||
switch act := action.(type) {
|
||||
case accept:
|
||||
res = p.stack.popN(1)[0]
|
||||
acc = true
|
||||
case shift:
|
||||
p.stack.push(int(act), p.nextToken)
|
||||
p.nextToken = scanner.Scan()
|
||||
case reduce:
|
||||
prod := productionsTable[int(act)]
|
||||
attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols))
|
||||
if err != nil {
|
||||
return nil, p.newError(err)
|
||||
} else {
|
||||
p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib)
|
||||
}
|
||||
default:
|
||||
panic("unknown action: " + action.String())
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
import "github.com/goccmack/gocc/example/astx/ast"
|
||||
|
||||
type (
|
||||
//TODO: change type and variable names to be consistent with other tables
|
||||
ProdTab [numProductions]ProdTabEntry
|
||||
ProdTabEntry struct {
|
||||
String string
|
||||
Id string
|
||||
NTType int
|
||||
Index int
|
||||
NumSymbols int
|
||||
ReduceFunc func([]Attrib) (Attrib, error)
|
||||
}
|
||||
Attrib interface {
|
||||
}
|
||||
)
|
||||
|
||||
var productionsTable = ProdTab{
|
||||
ProdTabEntry{
|
||||
String: `S' : StmtList << >>`,
|
||||
Id: "S'",
|
||||
NTType: 0,
|
||||
Index: 0,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return X[0], nil
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `StmtList : Stmt << ast.NewStmtList(X[0]) >>`,
|
||||
Id: "StmtList",
|
||||
NTType: 1,
|
||||
Index: 1,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return ast.NewStmtList(X[0])
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `StmtList : StmtList Stmt << ast.AppendStmt(X[0], X[1]) >>`,
|
||||
Id: "StmtList",
|
||||
NTType: 1,
|
||||
Index: 2,
|
||||
NumSymbols: 2,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return ast.AppendStmt(X[0], X[1])
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `Stmt : id << ast.NewStmt(X[0]) >>`,
|
||||
Id: "Stmt",
|
||||
NTType: 2,
|
||||
Index: 3,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return ast.NewStmt(X[0])
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
Type
|
||||
Lit []byte
|
||||
Pos
|
||||
}
|
||||
|
||||
type Type int
|
||||
|
||||
const (
|
||||
INVALID Type = iota
|
||||
EOF
|
||||
)
|
||||
|
||||
type Pos struct {
|
||||
Offset int
|
||||
Line int
|
||||
Column int
|
||||
}
|
||||
|
||||
func (p Pos) String() string {
|
||||
return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column)
|
||||
}
|
||||
|
||||
type TokenMap struct {
|
||||
typeMap []string
|
||||
idMap map[string]Type
|
||||
}
|
||||
|
||||
func (m TokenMap) Id(tok Type) string {
|
||||
if int(tok) < len(m.typeMap) {
|
||||
return m.typeMap[tok]
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (m TokenMap) Type(tok string) Type {
|
||||
if typ, exist := m.idMap[tok]; exist {
|
||||
return typ
|
||||
}
|
||||
return INVALID
|
||||
}
|
||||
|
||||
func (m TokenMap) TokenString(tok *Token) string {
|
||||
//TODO: refactor to print pos & token string properly
|
||||
return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit)
|
||||
}
|
||||
|
||||
func (m TokenMap) StringType(typ Type) string {
|
||||
return fmt.Sprintf("%s(%d)", m.Id(typ), typ)
|
||||
}
|
||||
|
||||
var TokMap = TokenMap{
|
||||
typeMap: []string{
|
||||
"INVALID",
|
||||
"$",
|
||||
"id",
|
||||
},
|
||||
|
||||
idMap: map[string]Type{
|
||||
"INVALID": 0,
|
||||
"$": 1,
|
||||
"id": 2,
|
||||
},
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
Generating a parser starts with creating a bnf file.
|
||||
We have created an example.bnf file to illustrate this.
|
||||
Running gen.sh will generate the parser, scanner and token code
|
||||
needed to parse the language.
|
||||
|
||||
The ast (abstract syntax tree) package needs to created by the user.
|
||||
This package should contain the corresponding function calls
|
||||
required by the syntax directed translation rules.
|
||||
See the example/ast package we have created.
|
||||
|
||||
Parsing a string with the generated code and evaluating the ast is
|
||||
shown in example/example_test.go with some corresponding tests.
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
//Copyright 2012 Vastech SA (PTY) LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/goccmack/gocc/example/bools/token"
|
||||
"github.com/goccmack/gocc/example/bools/util"
|
||||
)
|
||||
|
||||
type Attrib interface{}
|
||||
|
||||
type Val interface {
|
||||
Attrib
|
||||
Eval() bool
|
||||
String() string
|
||||
}
|
||||
|
||||
type Op int
|
||||
|
||||
func (o Op) String() string {
|
||||
switch o {
|
||||
case OR:
|
||||
return "|"
|
||||
case AND:
|
||||
return "&"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const (
|
||||
NOOP = Op(0)
|
||||
OR = Op(1)
|
||||
AND = Op(2)
|
||||
)
|
||||
|
||||
type BoolExpr struct {
|
||||
A Val
|
||||
B Val
|
||||
Op Op
|
||||
}
|
||||
|
||||
func NewBoolAndExpr(a, b Attrib) (*BoolExpr, error) {
|
||||
return &BoolExpr{a.(Val), b.(Val), AND}, nil
|
||||
}
|
||||
|
||||
func NewBoolOrExpr(a, b Attrib) (*BoolExpr, error) {
|
||||
return &BoolExpr{a.(Val), b.(Val), OR}, nil
|
||||
}
|
||||
|
||||
func NewBoolGroupExpr(a Attrib) (*BoolExpr, error) {
|
||||
return &BoolExpr{a.(Val), nil, NOOP}, nil
|
||||
}
|
||||
|
||||
func (this *BoolExpr) Eval() bool {
|
||||
switch this.Op {
|
||||
case OR:
|
||||
return this.A.Eval() || this.B.Eval()
|
||||
case AND:
|
||||
return this.A.Eval() && this.B.Eval()
|
||||
}
|
||||
return this.A.Eval()
|
||||
}
|
||||
|
||||
func (this *BoolExpr) String() string {
|
||||
return this.A.String() + " " + this.Op.String() + " " + this.B.String()
|
||||
}
|
||||
|
||||
type val bool
|
||||
|
||||
func (v val) Eval() bool {
|
||||
return bool(v)
|
||||
}
|
||||
|
||||
func (v val) String() string {
|
||||
if v {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
}
|
||||
|
||||
var (
|
||||
TRUE = val(true)
|
||||
FALSE = val(false)
|
||||
)
|
||||
|
||||
type LessThanExpr struct {
|
||||
A int64
|
||||
B int64
|
||||
}
|
||||
|
||||
func NewLessThanExpr(a, b Attrib) (*LessThanExpr, error) {
|
||||
aint, err := util.IntValue(a.(*token.Token).Lit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bint, err := util.IntValue(b.(*token.Token).Lit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &LessThanExpr{aint, bint}, nil
|
||||
}
|
||||
|
||||
func (this *LessThanExpr) Eval() bool {
|
||||
return this.A < this.B
|
||||
}
|
||||
|
||||
func (this *LessThanExpr) String() string {
|
||||
return strconv.FormatInt(this.A, 10) + " < " + strconv.FormatInt(this.B, 10)
|
||||
}
|
||||
|
||||
type SubStringExpr struct {
|
||||
A string
|
||||
B string
|
||||
}
|
||||
|
||||
func NewSubStringExpr(a, b Attrib) (*SubStringExpr, error) {
|
||||
astr, err := strconv.Unquote(string(a.(*token.Token).Lit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bstr, err := strconv.Unquote(string(b.(*token.Token).Lit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SubStringExpr{astr, bstr}, nil
|
||||
}
|
||||
|
||||
func (this *SubStringExpr) Eval() bool {
|
||||
return strings.Contains(this.B, this.A)
|
||||
}
|
||||
|
||||
func (this *SubStringExpr) String() string {
|
||||
return this.A + " in " + this.B
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
package example
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/goccmack/gocc/example/bools/token"
|
||||
)
|
||||
|
||||
type ErrorSymbol interface {
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Err error
|
||||
ErrorToken *token.Token
|
||||
ErrorSymbols []ErrorSymbol
|
||||
ExpectedTokens []string
|
||||
StackTop int
|
||||
}
|
||||
|
||||
func (e *Error) String() string {
|
||||
w := new(strings.Builder)
|
||||
fmt.Fprintf(w, "Error")
|
||||
if e.Err != nil {
|
||||
fmt.Fprintf(w, " %s\n", e.Err)
|
||||
} else {
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit)
|
||||
fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column)
|
||||
fmt.Fprintf(w, "Expected one of: ")
|
||||
for _, sym := range e.ExpectedTokens {
|
||||
fmt.Fprintf(w, "%s ", sym)
|
||||
}
|
||||
fmt.Fprintf(w, "ErrorSymbol:\n")
|
||||
for _, sym := range e.ErrorSymbols {
|
||||
fmt.Fprintf(w, "%v\n", sym)
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
w := new(strings.Builder)
|
||||
fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String())
|
||||
if e.Err != nil {
|
||||
fmt.Fprintf(w, ": %+v", e.Err)
|
||||
} else {
|
||||
fmt.Fprintf(w, ", expected one of: ")
|
||||
for _, expected := range e.ExpectedTokens {
|
||||
fmt.Fprintf(w, "%s ", expected)
|
||||
}
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//Copyright 2012 Vastech SA (PTY) LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
int_lit : _digit {_digit} ;
|
||||
|
||||
_digit : '0'-'9' ;
|
||||
|
||||
string_lit : '"' {.} '"' ;
|
||||
|
||||
!whitespace : ' ' | '\t' | '\n' | '\r' ;
|
||||
|
||||
<<import ( "github.com/goccmack/gocc/example/bools/ast" )>>
|
||||
|
||||
BoolExpr
|
||||
: BoolExpr1 << $0, nil >>
|
||||
;
|
||||
|
||||
BoolExpr1
|
||||
: Val << $0, nil >>
|
||||
| BoolExpr "&" BoolExpr1 << ast.NewBoolAndExpr($0, $2) >>
|
||||
| BoolExpr "|" BoolExpr1 << ast.NewBoolOrExpr($0, $2) >>
|
||||
| "(" BoolExpr ")" << ast.NewBoolGroupExpr($1) >>
|
||||
;
|
||||
|
||||
Val
|
||||
: "true" << ast.TRUE, nil >>
|
||||
| "false" << ast.FALSE, nil >>
|
||||
| CompareExpr << $0, nil >>
|
||||
| SubStringExpr << $0, nil >>
|
||||
;
|
||||
|
||||
CompareExpr
|
||||
: int_lit "<" int_lit << ast.NewLessThanExpr($0, $2) >>
|
||||
| int_lit ">" int_lit << ast.NewLessThanExpr($2, $0) >>
|
||||
;
|
||||
|
||||
SubStringExpr
|
||||
: string_lit "in" string_lit << ast.NewSubStringExpr($0, $2) >>
|
||||
;
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
//Copyright 2012 Vastech SA (PTY) LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package example
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goccmack/gocc/example/bools/ast"
|
||||
"github.com/goccmack/gocc/example/bools/lexer"
|
||||
"github.com/goccmack/gocc/example/bools/parser"
|
||||
)
|
||||
|
||||
func testEval(t *testing.T, exampleStr string, output bool) {
|
||||
lex := lexer.NewLexer([]byte(exampleStr))
|
||||
p := parser.NewParser()
|
||||
st, err := p.Parse(lex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if st.(ast.Val).Eval() != output {
|
||||
t.Fatalf("Should be %v for %v", output, exampleStr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOr(t *testing.T) {
|
||||
testEval(t, "true | false", true)
|
||||
}
|
||||
|
||||
func TestAnd(t *testing.T) {
|
||||
testEval(t, "true & false", false)
|
||||
}
|
||||
|
||||
func TestSubString(t *testing.T) {
|
||||
testEval(t, `"true" in "false"`, false)
|
||||
testEval(t, `"true" in "trues"`, true)
|
||||
}
|
||||
|
||||
func TestLess(t *testing.T) {
|
||||
testEval(t, "0 < 5", true)
|
||||
testEval(t, "0 > 5", false)
|
||||
}
|
||||
|
||||
func TestMixed(t *testing.T) {
|
||||
testEval(t, "0 < 5 | false", true)
|
||||
}
|
||||
|
||||
func TestGroup(t *testing.T) {
|
||||
testEval(t, "( true | false ) & ( true & true )", true)
|
||||
}
|
||||
|
||||
func TestGroupMixed(t *testing.T) {
|
||||
testEval(t, `( true | false ) & 0 > 100000 | "t" in "taddle"`, true)
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
gocc -a example.bnf
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
// Code generated by gocc; DO NOT EDIT.
|
||||
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goccmack/gocc/example/bools/token"
|
||||
)
|
||||
|
||||
type ActionTable [NumStates]ActionRow
|
||||
|
||||
type ActionRow struct {
|
||||
Accept token.Type
|
||||
Ignore string
|
||||
}
|
||||
|
||||
func (a ActionRow) String() string {
|
||||
return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore)
|
||||
}
|
||||
|
||||
var ActTab = ActionTable{
|
||||
ActionRow{ // S0
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S1
|
||||
Accept: -1,
|
||||
Ignore: "!whitespace",
|
||||
},
|
||||
ActionRow{ // S2
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S3
|
||||
Accept: 2,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S4
|
||||
Accept: 4,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S5
|
||||
Accept: 5,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S6
|
||||
Accept: 8,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S7
|
||||
Accept: 9,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S8
|
||||
Accept: 10,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S9
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S10
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S11
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S12
|
||||
Accept: 3,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S13
|
||||
Accept: 11,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S14
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S15
|
||||
Accept: 12,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S16
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S17
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S18
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S19
|
||||
Accept: 0,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S20
|
||||
Accept: 6,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S21
|
||||
Accept: 7,
|
||||
Ignore: "",
|
||||
},
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue