├── .dockerignore ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── _tools ├── credits ├── release └── upload_artifacts ├── go.mod ├── go.sum ├── gokc.go ├── log └── log.go ├── parser ├── lexer.go ├── lexer_test.go ├── parser.go ├── parser.go.y ├── parser.output └── testing.go ├── testdata ├── globaldef_1_3.conf ├── unicast_mcast.conf ├── vrrp_garp_master.conf ├── vrrp_mcast_group.conf └── vrrp_script.conf └── version.go /.dockerignore: -------------------------------------------------------------------------------- 1 | snapshot 2 | .git 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | /gokc 27 | 28 | /snapshot 29 | /dist 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "keepalived"] 2 | path = keepalived 3 | url = https://github.com/acassen/keepalived 4 | [submodule "vendor/github.com/mitchellh/colorstring"] 5 | path = vendor/github.com/mitchellh/colorstring 6 | url = https://github.com/mitchellh/colorstring 7 | branch = master 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | 4 | go: 5 | - 1.12 6 | 7 | script: 8 | - make test 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [v0.4.3](https://github.com/yuuki/gokc/compare/v0.4.1...v0.4.3) (2019-09-20) 4 | 5 | * Add garp_master settings [#19](https://github.com/yuuki/gokc/pull/19) ([nashiox](https://github.com/nashiox)) 6 | * Improve release [#17](https://github.com/yuuki/gokc/pull/17) ([yuuki](https://github.com/yuuki)) 7 | * add enable_script_security option to parser [#16](https://github.com/yuuki/gokc/pull/16) ([nabeo](https://github.com/nabeo)) 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.12 2 | 3 | RUN mkdir -p /src 4 | WORKDIR /src 5 | COPY go.mod . 6 | COPY go.sum . 7 | 8 | RUN go mod download 9 | COPY . . 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 y_uuki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export GO111MODULE=on 2 | 3 | PKG = github.com/yuuki/gokc 4 | COMMIT = $$(git describe --tags --always) 5 | DATE = $$(date --utc '+%Y-%m-%d_%H:%M:%S') 6 | BUILD_LDFLAGS = -X $(PKG).commit=$(COMMIT) -X $(PKG).date=$(DATE) 7 | RELEASE_BUILD_LDFLAGS = -s -w $(BUILD_LDFLAGS) 8 | 9 | all: build 10 | 11 | yacc: deps 12 | goyacc -o parser/parser.go -v parser/parser.output parser/parser.go.y 13 | 14 | build: yacc 15 | go build -ldflags="$(BUILD_LDFLAGS)" $(PKG) 16 | 17 | test: yacc 18 | go test -v $$(go list ./... | grep -v vendor) 19 | 20 | testfiles: build 21 | find ./testdata -type f | xargs -I{} ./$(BIN) -f {} 22 | find ./keepalived/doc/samples/keepalived.conf.* -type f | xargs -I{} ./$(BIN) -f {} 23 | 24 | .PHONY: devel-deps 25 | devel-deps: 26 | GO111MODULE=off go get -v \ 27 | golang.org/x/tools/cmd/cover \ 28 | github.com/mattn/goveralls \ 29 | github.com/motemen/gobump/cmd/gobump \ 30 | github.com/Songmu/ghch/cmd/ghch \ 31 | github.com/Songmu/goxz/cmd/goxz \ 32 | github.com/tcnksm/ghr \ 33 | github.com/Songmu/gocredits/cmd/gocredits 34 | 35 | deps: 36 | go get golang.org/x/tools/cmd/goyacc 37 | go get -d -v ./... 38 | 39 | .PHONY: crossbuild 40 | crossbuild: devel-deps 41 | $(eval ver = $(shell gobump show -r)) 42 | goxz -pv=v$(ver) -os=linux,darwin -arch=386,amd64 -build-ldflags="$(RELEASE_BUILD_LDFLAGS)" \ 43 | -d=./dist/v$(ver) 44 | 45 | .PHONY: release 46 | release: devel-deps 47 | _tools/release 48 | _tools/upload_artifacts 49 | 50 | clean: 51 | go clean 52 | 53 | .PHONY: yacc build clean deps test buildlinux patch minor gobump 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gokc 2 | ==== 3 | [![Build Status](https://travis-ci.org/yuuki/diamondb.svg?branch=master)](https://travis-ci.org/yuuki/diamondb) 4 | [![Latest Version](http://img.shields.io/github/release/yuuki/gokc.svg?style=flat-square)](https://github.com/yuuki/gokc/releases) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/yuuki/gokc)](https://goreportcard.com/report/github.com/yuuki/gokc) 6 | 7 | Yet Another [Keepalived](http://keepalived.org/) syntax checker in golang. 8 | 9 | ## Usage 10 | 11 | ```bash 12 | gokc -f /etc/keepalived/keepalived.conf 13 | gokc: the configuration file /etc/keepalived/keepalived.conf syntax is ok 14 | ``` 15 | 16 | ## Installation 17 | 18 | ### Homebrew 19 | ```bash 20 | $ brew tap yuuki/gokc 21 | $ brew install gokc 22 | ``` 23 | 24 | ### Download binary from GitHub Releases 25 | [Releases・yuuki/gokc - GitHub](https://github.com/yuuki/gokc/releases) 26 | 27 | ### Build from source 28 | ```bash 29 | $ go get github.com/yuuki/gokc 30 | $ go install github.com/yuuki/gokc 31 | ``` 32 | 33 | ## Contribution 34 | 35 | 1. Fork ([https://github.com/yuuki/gokc/fork](https://github.com/yuuki/gokc/fork)) 36 | 1. Create a feature branch 37 | 1. Commit your changes 38 | 1. Rebase your local changes against the master branch 39 | 1. Run test suite with the `go test ./...` command and confirm that it passes 40 | 1. Run `gofmt -s` 41 | 1. Create new Pull Request 42 | 43 | ## License 44 | 45 | [The MIT License](./LICENSE). 46 | 47 | ## Author 48 | 49 | [y_uuki](https://github.com/yuuki) 50 | -------------------------------------------------------------------------------- /_tools/credits: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e -o pipefail 3 | 4 | ROOT=$(dirname "${BASH_SOURCE}")/.. 5 | cd "${ROOT}" 6 | 7 | echo '==========================================================================================' 8 | echo "= lstf licensed under: =" 9 | echo "https://github.com/yuuki/lstf/" 10 | echo 11 | cat "${ROOT}"/LICENSE 12 | echo 13 | echo "= LICENSE $(cat ${ROOT}/LICENSE | md5sum | awk '{print $1}')" 14 | echo '==========================================================================================' 15 | echo 16 | 17 | echo "= Go (the standard library) licensed under: =" 18 | echo "https://golang.org/" 19 | echo 20 | curl -sS https://raw.githubusercontent.com/golang/go/release-branch.go1.9/LICENSE 2>/dev/null 21 | echo 22 | echo '==========================================================================================' 23 | echo 24 | 25 | find_names=(-iname 'licen[sc]e*') 26 | for repo in $(dep status -json | jq -rM '.[].ProjectRoot'); do 27 | echo 28 | echo '==========================================================================================' 29 | echo "= vendor/${repo} licensed under: =" 30 | echo "https://${repo}/" 31 | for lic in $(find vendor/${repo} -xdev -follow -maxdepth 1 -type f "${find_names[@]}"); do 32 | echo 33 | cat "${lic}" 34 | echo 35 | echo "= ${lic} $(cat ${lic} | md5sum | awk '{print $1}')" 36 | done 37 | echo '==========================================================================================' 38 | echo 39 | done 40 | -------------------------------------------------------------------------------- /_tools/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ $(git status -s) != "" ]]; then 5 | echo 2>&1 "git is currently in a dirty state" 6 | exit 1 7 | fi 8 | 9 | current_version=$(gobump show -r) 10 | 11 | echo "current version: $current_version" 12 | read -p "input next version: " next_version 13 | 14 | echo "--> Bumping version $next_version" 15 | gobump set "$next_version" -w 16 | echo "--> Generating CHANGELOG" 17 | ghch -w -N "v$next_version" 18 | 19 | git commit -am "Bump version $next_version" 20 | git tag "v$next_version" 21 | git push && git push --tags -------------------------------------------------------------------------------- /_tools/upload_artifacts: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ver=v$(gobump show -r) 5 | make crossbuild 6 | ghr -username yuuki -replace ${ver} dist/${ver} -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/yuuki/gokc 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db 7 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= 2 | github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= 3 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 4 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 5 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 6 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 7 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 8 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88= 9 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 10 | -------------------------------------------------------------------------------- /gokc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | 9 | "github.com/mitchellh/colorstring" 10 | 11 | "github.com/yuuki/gokc/log" 12 | "github.com/yuuki/gokc/parser" 13 | ) 14 | 15 | func setDebugOutputLevel() { 16 | for _, f := range os.Args { 17 | if f == "-D" || f == "--debug" || f == "-debug" { 18 | log.IsDebug = true 19 | } 20 | } 21 | 22 | debugEnv := os.Getenv("GOKC_DEBUG") 23 | if debugEnv != "" { 24 | showDebug, err := strconv.ParseBool(debugEnv) 25 | if err != nil { 26 | fmt.Fprintf(os.Stderr, "Error parsing boolean value from GRABENI_DEBUG: %s\n", err) 27 | os.Exit(1) 28 | } 29 | log.IsDebug = showDebug 30 | } 31 | } 32 | 33 | func init() { 34 | setDebugOutputLevel() 35 | } 36 | 37 | func main() { 38 | var filepath string 39 | var isVersion bool 40 | flag.StringVar(&filepath, "f", "/etc/keepalived/keepalived.conf", "keepalived.conf file path") 41 | flag.BoolVar(&isVersion, "v", false, "print the version") 42 | flag.BoolVar(&log.IsVerbose, "V", false, "verbose log mode") 43 | flag.Parse() 44 | 45 | if isVersion { 46 | log.Infof("gokc version %s", version) 47 | os.Exit(0) 48 | } 49 | 50 | if filepath == "" { 51 | log.Error("filepath required") 52 | } 53 | 54 | file, err := os.Open(filepath) 55 | if err != nil { 56 | log.Error(err) 57 | } 58 | defer file.Close() 59 | 60 | if err := parser.Parse(file, filepath); err != nil { 61 | if e, ok := err.(*parser.Error); ok { 62 | msg := colorstring.Color(fmt.Sprintf("[white]%s:%d:%d: [red]%s[reset]", e.Filename, e.Line, e.Column, e.Message)) 63 | log.Error(msg) 64 | } else { 65 | log.Error(err) 66 | } 67 | } 68 | 69 | log.Infof("gokc: the configuration file %s syntax is ok", filepath) 70 | } 71 | -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "log" 5 | ) 6 | 7 | var IsDebug = false 8 | var IsVerbose = false 9 | 10 | func init() { 11 | log.SetFlags(0) 12 | } 13 | 14 | func Debug(v ...interface{}) { 15 | if IsDebug == true { 16 | log.Println(v...) 17 | } 18 | } 19 | 20 | func Debugf(format string, v ...interface{}) { 21 | if IsDebug == true { 22 | log.Printf(format, v...) 23 | } 24 | } 25 | 26 | func Verbose(v ...interface{}) { 27 | if IsVerbose == true { 28 | log.Println(v...) 29 | } 30 | } 31 | 32 | func Verbosef(format string, v ...interface{}) { 33 | if IsVerbose == true { 34 | log.Printf(format, v...) 35 | } 36 | } 37 | 38 | func Info(v ...interface{}) { 39 | log.Println(v...) 40 | } 41 | 42 | func Infof(format string, v ...interface{}) { 43 | log.Printf(format, v...) 44 | } 45 | 46 | func Error(v ...interface{}) { 47 | log.Fatal(v...) 48 | } 49 | 50 | func Errorf(format string, v ...interface{}) { 51 | log.Fatalf(format, v...) 52 | } 53 | -------------------------------------------------------------------------------- /parser/lexer.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net" 7 | "net/mail" 8 | "os" 9 | "path/filepath" 10 | "regexp" 11 | "strconv" 12 | "strings" 13 | "text/scanner" 14 | "unicode" 15 | 16 | "github.com/yuuki/gokc/log" 17 | ) 18 | 19 | const ( 20 | EOF = 0 21 | ) 22 | 23 | var symbolTables = map[string]int{ 24 | "{": LB, 25 | "}": RB, 26 | 27 | "global_defs": GLOBALDEFS, 28 | "notification_email": NOTIFICATION_EMAIL, 29 | "notification_email_from": NOTIFICATION_EMAIL_FROM, 30 | "smtp_server": SMTP_SERVER, 31 | "smtp_connect_timeout": SMTP_CONNECT_TIMEOUT, 32 | "router_id": ROUTER_ID, 33 | "lvs_id": LVS_ID, 34 | "vrrp_mcast_group4": VRRP_MCAST_GROUP4, 35 | "vrrp_mcast_group6": VRRP_MCAST_GROUP6, 36 | "vrrp_garp_master_delay": VRRP_GARP_MASTER_DELAY, 37 | "vrrp_garp_master_repeat": VRRP_GARP_MASTER_REPEAT, 38 | "vrrp_garp_master_refresh": VRRP_GARP_MASTER_REFRESH, 39 | "vrrp_garp_master_refresh_repeat": VRRP_GARP_MASTER_REFRESH_REPEAT, 40 | "vrrp_version": VRRP_VERSION, 41 | "enable_script_security": ENABLE_SCRIPT_SECURITY, 42 | 43 | "static_ipaddress": STATIC_IPADDRESS, 44 | "static_routes": STATIC_ROUTES, 45 | "static_rules": STATIC_RULES, 46 | 47 | "vrrp_sync_group": VRRP_SYNC_GROUP, 48 | "group": GROUP, 49 | 50 | "vrrp_instance": VRRP_INSTANCE, 51 | "use_vmac": USE_VMAC, 52 | "version": VERSION, 53 | "vmac_xmit_base": VMAC_XMIT_BASE, 54 | "native_ipv6": NATIVE_IPV6, 55 | "interface": INTERFACE, 56 | "mcast_src_ip": MCAST_SRC_IP, 57 | "unicast_src_ip": UNICAST_SRC_IP, 58 | "unicast_peer": UNICAST_PEER, 59 | "lvs_sync_daemon_interface": LVS_SYNC_DAEMON_INTERFACE, 60 | "virtual_router_id": VIRTUAL_ROUTER_ID, 61 | "nopreempt": NOPREEMPT, 62 | "preempt_delay": PREEMPT_DELAY, 63 | "priority": PRIORITY, 64 | "advert_int": ADVERT_INT, 65 | "virtual_ipaddress": VIRTUAL_IPADDRESS, 66 | "virtual_ipaddress_excluded": VIRTUAL_IPADDRESS_EXCLUDED, 67 | "virtual_routes": VIRTUAL_ROUTES, 68 | "state": STATE, 69 | "MASTER": MASTER, 70 | "BACKUP": BACKUP, 71 | "garp_master_delay": GARP_MASTER_DELAY, 72 | "garp_master_repeat": GARP_MASTER_REPEAT, 73 | "garp_master_refresh": GARP_MASTER_REFRESH, 74 | "garp_master_refresh_repeat": GARP_MASTER_REFRESH_REPEAT, 75 | "smtp_alert": SMTP_ALERT, 76 | "authentication": AUTHENTICATION, 77 | "auth_type": AUTH_TYPE, 78 | "auth_pass": AUTH_PASS, 79 | "PASS": PASS, 80 | "AH": AH, 81 | "label": LABEL, 82 | "dev": DEV, 83 | "scope": SCOPE, 84 | "site": SITE, 85 | "link": LINK, 86 | "host": HOST, 87 | "nowhere": NOWHERE, 88 | "global": GLOBAL, 89 | "brd": BRD, 90 | "src": SRC, 91 | "from": FROM, 92 | "to": TO, 93 | "via": VIA, 94 | "gw": GW, 95 | "or": OR, 96 | "table": TABLE, 97 | "metric": METRIC, 98 | "blackhole": BLACKHOLE, 99 | "track_interface": TRACK_INTERFACE, 100 | "track_script": TRACK_SCRIPT, 101 | "dont_track_primary": DONT_TRACK_PRIMARY, 102 | "notify_master": NOTIFY_MASTER, 103 | "notify_backup": NOTIFY_BACKUP, 104 | "notify_fault": NOTIFY_FAULT, 105 | "notify_stop": NOTIFY_STOP, 106 | "notify": NOTIFY, 107 | 108 | "vrrp_script": VRRP_SCRIPT, 109 | "script": SCRIPT, 110 | "interval": INTERVAL, 111 | "timeout": TIMEOUT, 112 | "fall": FALL, 113 | "rise": RISE, 114 | 115 | "virtual_server_group": VIRTUAL_SERVER_GROUP, 116 | "fwmark": FWMARK, 117 | 118 | "virtual_server": VIRTUAL_SERVER, 119 | "delay_loop": DELAY_LOOP, 120 | "lb_algo": LB_ALGO, 121 | "lb_kind": LB_KIND, 122 | "lvs_sched": LVS_SCHED, 123 | "lvs_method": LVS_METHOD, 124 | "rr": RR, 125 | "wrr": WRR, 126 | "lc": LC, 127 | "wlc": WLC, 128 | "fo": FO, 129 | "ovf": OVF, 130 | "lblc": LBLC, 131 | "lblcr": LBLCR, 132 | "sh": SH, 133 | "dh": DH, 134 | "sed": SED, 135 | "nq": NQ, 136 | "NAT": NAT, 137 | "DR": DR, 138 | "TUN": TUN, 139 | "persistence_timeout": PERSISTENCE_TIMEOUT, 140 | "protocol": PROTOCOL, 141 | "TCP": TCP, 142 | "UDP": UDP, 143 | "sorry_server": SORRY_SERVER, 144 | "real_server": REAL_SERVER, 145 | "weight": WEIGHT, 146 | "inhibit_on_failure": INHIBIT_ON_FAILURE, 147 | "TCP_CHECK": TCP_CHECK, 148 | "HTTP_GET": HTTP_GET, 149 | "SSL_GET": SSL_GET, 150 | "SMTP_CHECK": SMTP_CHECK, 151 | "DNS_CHECK": DNS_CHECK, 152 | "MISC_CHECK": MISC_CHECK, 153 | "url": URL, 154 | "path": PATH, 155 | "digest": DIGEST, 156 | "status_code": STATUS_CODE, 157 | "connect_timeout": CONNECT_TIMEOUT, 158 | "connect_port": CONNECT_PORT, 159 | "connect_ip": CONNECT_IP, 160 | "bindto": BINDTO, 161 | "bind_port": BIND_PORT, 162 | "retry": RETRY, 163 | "helo_name": HELO_NAME, 164 | "delay_before_retry": DELAY_BEFORE_RETRY, 165 | "type": TYPE, 166 | "name": NAME, 167 | "misc_path": MISC_PATH, 168 | "misc_timeout": MISC_TIMEOUT, 169 | "warmup": WARMUP, 170 | "misc_dynamic": MISC_DYNAMIC, 171 | "nb_get_retry": NB_GET_RETRY, 172 | "virtualhost": VIRTUALHOST, 173 | "alpha": ALPHA, 174 | "omega": OMEGA, 175 | "quorum": QUORUM, 176 | "hysteresis": HYSTERESIS, 177 | "quorum_up": QUORUM_UP, 178 | "quorum_down": QUORUM_DOWN, 179 | } 180 | 181 | type Tokenizer struct { 182 | scanner scanner.Scanner 183 | filename string 184 | } 185 | 186 | func NewTokenizer(src io.Reader, filename string) *Tokenizer { 187 | var t Tokenizer 188 | t.scanner.Init(src) 189 | t.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats | scanner.ScanChars | scanner.ScanRawStrings | scanner.ScanComments | scanner.SkipComments 190 | t.scanner.IsIdentRune = isIdentRune 191 | t.filename = filename 192 | return &t 193 | } 194 | 195 | func (t *Tokenizer) NextAll() ([]*Token, error) { 196 | var result []*Token 197 | 198 | for { 199 | token, s := t.scanNextToken() 200 | 201 | for s == "include" { 202 | token, s = t.scanNextToken() 203 | 204 | tokens, err := t.scanInclude(s) 205 | if err != nil { 206 | return nil, err 207 | } 208 | result = append(result, tokens...) 209 | 210 | token, s = t.scanNextToken() 211 | } 212 | 213 | if token == scanner.EOF { 214 | break 215 | } 216 | 217 | if token == scanner.Ident || token == scanner.String { 218 | token = STRING 219 | } 220 | 221 | if _, err := strconv.Atoi(s); err == nil { 222 | token = NUMBER 223 | } 224 | 225 | if ip := net.ParseIP(s); ip != nil { 226 | if ip.To4() != nil { 227 | token = IPV4 228 | } else if ip.To16() != nil { 229 | token = IPV6 230 | } else { 231 | log.Infof("warning: %s may be IP address?", s) 232 | } 233 | } 234 | 235 | if _, _, err := net.ParseCIDR(s); err == nil { 236 | token = IP_CIDR 237 | } 238 | 239 | // IPADDR_RANGE(XXX.YYY.ZZZ.WWW-VVV) 240 | if ss := strings.Split(s, "-"); len(ss) == 2 { 241 | if net.ParseIP(ss[0]) != nil { 242 | if ok, _ := regexp.MatchString(`^[\d]{1,3}$`, ss[1]); ok { 243 | token = IPADDR_RANGE 244 | } 245 | } 246 | } 247 | 248 | if ok, _ := regexp.MatchString(`^[[:xdigit:]]{32}$`, s); ok { 249 | token = HEX32 250 | } 251 | 252 | if ok, _ := regexp.MatchString(`/^([[:alnum:]./-_])*`, s); ok { 253 | token = PATHSTR 254 | } 255 | 256 | if _, err := mail.ParseAddress(s); err == nil { 257 | token = EMAIL 258 | } 259 | 260 | if _, ok := symbolTables[s]; ok { 261 | token = symbolTables[s] 262 | } 263 | 264 | result = append(result, &Token{ 265 | value: token, 266 | filename: t.filename, 267 | line: t.scanner.Line, 268 | column: t.scanner.Column, 269 | }) 270 | } 271 | 272 | return result, nil 273 | } 274 | 275 | func skipComments(scanner *scanner.Scanner) { 276 | ch := scanner.Next() 277 | for ch != '\n' && ch >= 0 { 278 | ch = scanner.Next() 279 | } 280 | } 281 | 282 | func (t *Tokenizer) scanNextToken() (int, string) { 283 | token := int(t.scanner.Scan()) 284 | s := t.scanner.TokenText() 285 | 286 | for s == "!" || s == "#" { 287 | skipComments(&t.scanner) 288 | 289 | token = int(t.scanner.Scan()) 290 | s = t.scanner.TokenText() 291 | } 292 | 293 | log.Debugf("token text: %s\n", s) 294 | 295 | return token, s 296 | } 297 | 298 | func (t *Tokenizer) scanInclude(rawfilename string) ([]*Token, error) { 299 | curDir, err := filepath.Abs(".") 300 | if err != nil { 301 | return nil, err 302 | } 303 | 304 | baseDir := filepath.Dir(t.filename) 305 | os.Chdir(baseDir) 306 | defer os.Chdir(curDir) 307 | 308 | rawpaths, err := filepath.Glob(rawfilename) 309 | if err != nil { 310 | return nil, err 311 | } 312 | 313 | if len(rawpaths) < 1 { 314 | return nil, fmt.Errorf("warning: %s: No such file or directory", rawfilename) 315 | } 316 | 317 | var result []*Token 318 | for _, rawpath := range rawpaths { 319 | log.Verbosef("--> Parsing ... %s\n", rawpath) 320 | 321 | f, err := os.Open(rawpath) 322 | if err != nil { 323 | return nil, err 324 | } 325 | 326 | child := NewTokenizer(f, rawpath) 327 | tokens, err := child.NextAll() 328 | if err != nil { 329 | return nil, err 330 | } 331 | result = append(result, tokens...) 332 | 333 | f.Close() 334 | } 335 | 336 | return result, nil 337 | } 338 | 339 | type Token struct { 340 | value int 341 | filename string 342 | line int 343 | column int 344 | } 345 | 346 | type Lexer struct { 347 | tokens []*Token 348 | pos int 349 | e error 350 | } 351 | 352 | type Error struct { 353 | Message string 354 | Filename string 355 | Line int 356 | Column int 357 | } 358 | 359 | func (e *Error) Error() string { 360 | return e.Message 361 | } 362 | 363 | func NewLexer(tokens []*Token) *Lexer { 364 | return &Lexer{tokens: tokens, pos: -1} 365 | } 366 | 367 | func isIdentRune(ch rune, i int) bool { 368 | return ch == '_' || ch == '.' || ch == '/' || ch == ':' || ch == '-' || ch == '+' || ch == '*' || ch == '?' || ch == '=' || ch == '&' || ch == '@' || unicode.IsLetter(ch) || unicode.IsDigit(ch) 369 | } 370 | 371 | func (l *Lexer) curToken() *Token { 372 | return l.tokens[l.pos] 373 | } 374 | 375 | func (l *Lexer) nextToken() *Token { 376 | l.pos++ 377 | return l.tokens[l.pos] 378 | } 379 | 380 | func (l *Lexer) Lex(lval *yySymType) int { 381 | if (len(l.tokens) - 1) == l.pos { 382 | return EOF 383 | } 384 | token := l.nextToken() 385 | return token.value 386 | } 387 | 388 | func (l *Lexer) Error(msg string) { 389 | token := l.curToken() 390 | l.e = &Error{ 391 | Filename: token.filename, 392 | Line: token.line, 393 | Column: token.column, 394 | Message: msg, 395 | } 396 | } 397 | 398 | func Parse(src io.Reader, filename string) error { 399 | yyErrorVerbose = true 400 | t := NewTokenizer(src, filename) 401 | tokens, err := t.NextAll() 402 | if err != nil { 403 | return err 404 | } 405 | l := NewLexer(tokens) 406 | if ret := yyParse(l); ret != 0 { 407 | return l.e 408 | } 409 | return l.e 410 | } 411 | -------------------------------------------------------------------------------- /parser/lexer_test.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | const ( 12 | testdataDir = "../testdata/" 13 | ) 14 | 15 | func TestNewTokenizer(t *testing.T) { 16 | buf := bytes.NewReader([]byte("hello world")) 17 | tokenizer := NewTokenizer(buf, "buffer") 18 | if tokenizer.scanner.Pos().Offset != 0 { 19 | t.Errorf("scanner pos got %v, want %v", tokenizer.scanner.Pos().Offset, 0) 20 | } 21 | if tokenizer.filename != "buffer" { 22 | t.Errorf("filename got %v, want %v", tokenizer.filename, "buffer") 23 | } 24 | } 25 | 26 | var ( 27 | tokenMap = map[string][]int{ 28 | "unicast_mcast": { 29 | VRRP_INSTANCE, STRING, LB, MCAST_SRC_IP, IPV4, 30 | UNICAST_SRC_IP, IPV4, UNICAST_PEER, LB, 31 | IPV4, IPV4, IPV4, RB, RB, 32 | }, 33 | } 34 | ) 35 | 36 | func TestTokenizer_NextAll(t *testing.T) { 37 | tests := []struct { 38 | filename string 39 | toks []int 40 | }{ 41 | { 42 | "unicast_mcast.conf", tokenMap["unicast_mcast"], 43 | }, 44 | } 45 | 46 | for _, tt := range tests { 47 | path := testdataDir + tt.filename 48 | f, err := os.Open(path) 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | tokenizer := NewTokenizer(f, path) 54 | tokens, err := tokenizer.NextAll() 55 | if err != nil { 56 | t.Errorf("shoud not raise error: %v", err) 57 | } 58 | fmt.Printf("%+v", len(tokens)) 59 | for i, token := range tokens { 60 | got, want := token.value, tt.toks[i] 61 | if got != want { 62 | t.Errorf("token got %v, want %v (%v)", got, want, i) 63 | } 64 | } 65 | } 66 | } 67 | 68 | func TestNewLexer(t *testing.T) { 69 | tokens := []*Token{ 70 | {VRRP_INSTANCE, "dummy.conf", 2, 10}, 71 | } 72 | l := NewLexer(tokens) 73 | if !reflect.DeepEqual(l.tokens, tokens) { 74 | t.Errorf("NewLexer got %v, want %v", l.tokens, tokens) 75 | } 76 | if l.pos != -1 { 77 | t.Errorf("pos got %v, want %v", l.pos, -1) 78 | } 79 | if l.e != nil { 80 | t.Errorf("lexer error: %v", l.e) 81 | } 82 | } 83 | 84 | func TestLexer_Lex(t *testing.T) { 85 | tests := []struct { 86 | desc string 87 | tokens []*Token 88 | }{ 89 | {"unicast_mcast", generateTestTokens(tokenMap["unicast_mcast"])}, 90 | } 91 | for _, tt := range tests { 92 | l := NewLexer(tt.tokens) 93 | ret := yyParse(l) 94 | if ret != 0 { 95 | t.Errorf("yyParse got %v, want %v", ret, 0) 96 | } 97 | if l.e != nil { 98 | t.Errorf("yyParse error shoud be nil: %v", l.e) 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /parser/parser.go: -------------------------------------------------------------------------------- 1 | // Code generated by goyacc -o parser/parser.go -v parser/parser.output parser/parser.go.y. DO NOT EDIT. 2 | 3 | //line parser/parser.go.y:2 4 | package parser 5 | 6 | import __yyfmt__ "fmt" 7 | 8 | //line parser/parser.go.y:2 9 | 10 | //line parser/parser.go.y:5 11 | type yySymType struct { 12 | yys int 13 | integer int 14 | symbol string 15 | } 16 | 17 | const NUMBER = 57346 18 | const ID = 57347 19 | const STRING = 57348 20 | const EMAIL = 57349 21 | const IPV4 = 57350 22 | const IPV6 = 57351 23 | const IP_CIDR = 57352 24 | const IPADDR_RANGE = 57353 25 | const HEX32 = 57354 26 | const PATHSTR = 57355 27 | const LB = 57356 28 | const RB = 57357 29 | const GLOBALDEFS = 57358 30 | const NOTIFICATION_EMAIL = 57359 31 | const NOTIFICATION_EMAIL_FROM = 57360 32 | const SMTP_SERVER = 57361 33 | const SMTP_CONNECT_TIMEOUT = 57362 34 | const ROUTER_ID = 57363 35 | const LVS_ID = 57364 36 | const VRRP_MCAST_GROUP4 = 57365 37 | const VRRP_MCAST_GROUP6 = 57366 38 | const VRRP_GARP_MASTER_DELAY = 57367 39 | const VRRP_GARP_MASTER_REPEAT = 57368 40 | const VRRP_GARP_MASTER_REFRESH = 57369 41 | const VRRP_GARP_MASTER_REFRESH_REPEAT = 57370 42 | const VRRP_VERSION = 57371 43 | const ENABLE_SCRIPT_SECURITY = 57372 44 | const STATIC_IPADDRESS = 57373 45 | const STATIC_ROUTES = 57374 46 | const STATIC_RULES = 57375 47 | const VRRP_SYNC_GROUP = 57376 48 | const GROUP = 57377 49 | const VRRP_INSTANCE = 57378 50 | const USE_VMAC = 57379 51 | const VERSION = 57380 52 | const VMAC_XMIT_BASE = 57381 53 | const NATIVE_IPV6 = 57382 54 | const INTERFACE = 57383 55 | const MCAST_SRC_IP = 57384 56 | const UNICAST_SRC_IP = 57385 57 | const UNICAST_PEER = 57386 58 | const LVS_SYNC_DAEMON_INTERFACE = 57387 59 | const VIRTUAL_ROUTER_ID = 57388 60 | const NOPREEMPT = 57389 61 | const PREEMPT_DELAY = 57390 62 | const PRIORITY = 57391 63 | const ADVERT_INT = 57392 64 | const VIRTUAL_IPADDRESS = 57393 65 | const VIRTUAL_IPADDRESS_EXCLUDED = 57394 66 | const VIRTUAL_ROUTES = 57395 67 | const STATE = 57396 68 | const MASTER = 57397 69 | const BACKUP = 57398 70 | const GARP_MASTER_DELAY = 57399 71 | const GARP_MASTER_REPEAT = 57400 72 | const GARP_MASTER_REFRESH = 57401 73 | const GARP_MASTER_REFRESH_REPEAT = 57402 74 | const SMTP_ALERT = 57403 75 | const AUTHENTICATION = 57404 76 | const AUTH_TYPE = 57405 77 | const AUTH_PASS = 57406 78 | const PASS = 57407 79 | const AH = 57408 80 | const LABEL = 57409 81 | const DEV = 57410 82 | const SCOPE = 57411 83 | const SITE = 57412 84 | const LINK = 57413 85 | const HOST = 57414 86 | const NOWHERE = 57415 87 | const GLOBAL = 57416 88 | const BRD = 57417 89 | const SRC = 57418 90 | const FROM = 57419 91 | const TO = 57420 92 | const VIA = 57421 93 | const GW = 57422 94 | const OR = 57423 95 | const TABLE = 57424 96 | const METRIC = 57425 97 | const TRACK_INTERFACE = 57426 98 | const TRACK_SCRIPT = 57427 99 | const DONT_TRACK_PRIMARY = 57428 100 | const NOTIFY_MASTER = 57429 101 | const NOTIFY_BACKUP = 57430 102 | const NOTIFY_FAULT = 57431 103 | const NOTIFY_STOP = 57432 104 | const NOTIFY = 57433 105 | const BLACKHOLE = 57434 106 | const VRRP_SCRIPT = 57435 107 | const SCRIPT = 57436 108 | const INTERVAL = 57437 109 | const TIMEOUT = 57438 110 | const WEIGHT = 57439 111 | const FALL = 57440 112 | const RISE = 57441 113 | const VIRTUAL_SERVER_GROUP = 57442 114 | const VIRTUAL_SERVER = 57443 115 | const DELAY_LOOP = 57444 116 | const LB_ALGO = 57445 117 | const LB_KIND = 57446 118 | const LVS_SCHED = 57447 119 | const LVS_METHOD = 57448 120 | const RR = 57449 121 | const WRR = 57450 122 | const LC = 57451 123 | const WLC = 57452 124 | const FO = 57453 125 | const OVF = 57454 126 | const LBLC = 57455 127 | const LBLCR = 57456 128 | const SH = 57457 129 | const DH = 57458 130 | const SED = 57459 131 | const NQ = 57460 132 | const NAT = 57461 133 | const DR = 57462 134 | const TUN = 57463 135 | const PERSISTENCE_TIMEOUT = 57464 136 | const PROTOCOL = 57465 137 | const TCP = 57466 138 | const UDP = 57467 139 | const SORRY_SERVER = 57468 140 | const REAL_SERVER = 57469 141 | const FWMARK = 57470 142 | const INHIBIT_ON_FAILURE = 57471 143 | const TCP_CHECK = 57472 144 | const HTTP_GET = 57473 145 | const SSL_GET = 57474 146 | const SMTP_CHECK = 57475 147 | const DNS_CHECK = 57476 148 | const MISC_CHECK = 57477 149 | const URL = 57478 150 | const PATH = 57479 151 | const DIGEST = 57480 152 | const STATUS_CODE = 57481 153 | const CONNECT_TIMEOUT = 57482 154 | const CONNECT_PORT = 57483 155 | const CONNECT_IP = 57484 156 | const BINDTO = 57485 157 | const BIND_PORT = 57486 158 | const RETRY = 57487 159 | const HELO_NAME = 57488 160 | const TYPE = 57489 161 | const NAME = 57490 162 | const MISC_PATH = 57491 163 | const MISC_TIMEOUT = 57492 164 | const WARMUP = 57493 165 | const MISC_DYNAMIC = 57494 166 | const NB_GET_RETRY = 57495 167 | const DELAY_BEFORE_RETRY = 57496 168 | const VIRTUALHOST = 57497 169 | const ALPHA = 57498 170 | const OMEGA = 57499 171 | const QUORUM = 57500 172 | const HYSTERESIS = 57501 173 | const QUORUM_UP = 57502 174 | const QUORUM_DOWN = 57503 175 | 176 | var yyToknames = [...]string{ 177 | "$end", 178 | "error", 179 | "$unk", 180 | "NUMBER", 181 | "ID", 182 | "STRING", 183 | "EMAIL", 184 | "IPV4", 185 | "IPV6", 186 | "IP_CIDR", 187 | "IPADDR_RANGE", 188 | "HEX32", 189 | "PATHSTR", 190 | "LB", 191 | "RB", 192 | "GLOBALDEFS", 193 | "NOTIFICATION_EMAIL", 194 | "NOTIFICATION_EMAIL_FROM", 195 | "SMTP_SERVER", 196 | "SMTP_CONNECT_TIMEOUT", 197 | "ROUTER_ID", 198 | "LVS_ID", 199 | "VRRP_MCAST_GROUP4", 200 | "VRRP_MCAST_GROUP6", 201 | "VRRP_GARP_MASTER_DELAY", 202 | "VRRP_GARP_MASTER_REPEAT", 203 | "VRRP_GARP_MASTER_REFRESH", 204 | "VRRP_GARP_MASTER_REFRESH_REPEAT", 205 | "VRRP_VERSION", 206 | "ENABLE_SCRIPT_SECURITY", 207 | "STATIC_IPADDRESS", 208 | "STATIC_ROUTES", 209 | "STATIC_RULES", 210 | "VRRP_SYNC_GROUP", 211 | "GROUP", 212 | "VRRP_INSTANCE", 213 | "USE_VMAC", 214 | "VERSION", 215 | "VMAC_XMIT_BASE", 216 | "NATIVE_IPV6", 217 | "INTERFACE", 218 | "MCAST_SRC_IP", 219 | "UNICAST_SRC_IP", 220 | "UNICAST_PEER", 221 | "LVS_SYNC_DAEMON_INTERFACE", 222 | "VIRTUAL_ROUTER_ID", 223 | "NOPREEMPT", 224 | "PREEMPT_DELAY", 225 | "PRIORITY", 226 | "ADVERT_INT", 227 | "VIRTUAL_IPADDRESS", 228 | "VIRTUAL_IPADDRESS_EXCLUDED", 229 | "VIRTUAL_ROUTES", 230 | "STATE", 231 | "MASTER", 232 | "BACKUP", 233 | "GARP_MASTER_DELAY", 234 | "GARP_MASTER_REPEAT", 235 | "GARP_MASTER_REFRESH", 236 | "GARP_MASTER_REFRESH_REPEAT", 237 | "SMTP_ALERT", 238 | "AUTHENTICATION", 239 | "AUTH_TYPE", 240 | "AUTH_PASS", 241 | "PASS", 242 | "AH", 243 | "LABEL", 244 | "DEV", 245 | "SCOPE", 246 | "SITE", 247 | "LINK", 248 | "HOST", 249 | "NOWHERE", 250 | "GLOBAL", 251 | "BRD", 252 | "SRC", 253 | "FROM", 254 | "TO", 255 | "VIA", 256 | "GW", 257 | "OR", 258 | "TABLE", 259 | "METRIC", 260 | "TRACK_INTERFACE", 261 | "TRACK_SCRIPT", 262 | "DONT_TRACK_PRIMARY", 263 | "NOTIFY_MASTER", 264 | "NOTIFY_BACKUP", 265 | "NOTIFY_FAULT", 266 | "NOTIFY_STOP", 267 | "NOTIFY", 268 | "BLACKHOLE", 269 | "VRRP_SCRIPT", 270 | "SCRIPT", 271 | "INTERVAL", 272 | "TIMEOUT", 273 | "WEIGHT", 274 | "FALL", 275 | "RISE", 276 | "VIRTUAL_SERVER_GROUP", 277 | "VIRTUAL_SERVER", 278 | "DELAY_LOOP", 279 | "LB_ALGO", 280 | "LB_KIND", 281 | "LVS_SCHED", 282 | "LVS_METHOD", 283 | "RR", 284 | "WRR", 285 | "LC", 286 | "WLC", 287 | "FO", 288 | "OVF", 289 | "LBLC", 290 | "LBLCR", 291 | "SH", 292 | "DH", 293 | "SED", 294 | "NQ", 295 | "NAT", 296 | "DR", 297 | "TUN", 298 | "PERSISTENCE_TIMEOUT", 299 | "PROTOCOL", 300 | "TCP", 301 | "UDP", 302 | "SORRY_SERVER", 303 | "REAL_SERVER", 304 | "FWMARK", 305 | "INHIBIT_ON_FAILURE", 306 | "TCP_CHECK", 307 | "HTTP_GET", 308 | "SSL_GET", 309 | "SMTP_CHECK", 310 | "DNS_CHECK", 311 | "MISC_CHECK", 312 | "URL", 313 | "PATH", 314 | "DIGEST", 315 | "STATUS_CODE", 316 | "CONNECT_TIMEOUT", 317 | "CONNECT_PORT", 318 | "CONNECT_IP", 319 | "BINDTO", 320 | "BIND_PORT", 321 | "RETRY", 322 | "HELO_NAME", 323 | "TYPE", 324 | "NAME", 325 | "MISC_PATH", 326 | "MISC_TIMEOUT", 327 | "WARMUP", 328 | "MISC_DYNAMIC", 329 | "NB_GET_RETRY", 330 | "DELAY_BEFORE_RETRY", 331 | "VIRTUALHOST", 332 | "ALPHA", 333 | "OMEGA", 334 | "QUORUM", 335 | "HYSTERESIS", 336 | "QUORUM_UP", 337 | "QUORUM_DOWN", 338 | } 339 | var yyStatenames = [...]string{} 340 | 341 | const yyEofCode = 1 342 | const yyErrCode = 2 343 | const yyInitialStackSize = 16 344 | 345 | //line parser/parser.go.y:385 346 | 347 | //line yacctab:1 348 | var yyExca = [...]int{ 349 | -1, 1, 350 | 1, -1, 351 | -2, 0, 352 | -1, 19, 353 | 14, 131, 354 | -2, 301, 355 | -1, 206, 356 | 15, 123, 357 | -2, 124, 358 | } 359 | 360 | const yyPrivate = 57344 361 | 362 | const yyLast = 565 363 | 364 | var yyAct = [...]int{ 365 | 366 | 416, 496, 491, 64, 439, 428, 414, 405, 398, 377, 367 | 342, 338, 212, 334, 186, 321, 327, 319, 317, 30, 368 | 314, 187, 210, 33, 205, 286, 178, 55, 273, 188, 369 | 441, 442, 443, 444, 144, 34, 35, 65, 60, 401, 370 | 400, 136, 407, 417, 402, 373, 408, 409, 222, 96, 371 | 403, 294, 295, 404, 61, 221, 340, 412, 55, 410, 372 | 411, 106, 493, 494, 495, 220, 116, 117, 219, 504, 373 | 119, 120, 121, 427, 34, 35, 498, 208, 128, 77, 374 | 78, 132, 134, 108, 485, 426, 423, 422, 424, 425, 375 | 207, 61, 474, 217, 70, 69, 73, 34, 35, 427, 376 | 115, 75, 37, 62, 463, 63, 66, 67, 68, 71, 377 | 72, 426, 423, 422, 424, 425, 419, 421, 461, 74, 378 | 365, 366, 418, 435, 32, 420, 379, 336, 337, 189, 379 | 190, 191, 192, 193, 53, 434, 431, 430, 432, 433, 380 | 436, 88, 437, 438, 287, 288, 289, 341, 460, 194, 381 | 195, 246, 247, 196, 197, 234, 235, 127, 380, 381, 382 | 382, 383, 384, 385, 386, 274, 275, 276, 277, 278, 383 | 279, 280, 281, 282, 283, 284, 285, 452, 131, 224, 384 | 231, 445, 198, 199, 200, 201, 202, 203, 204, 105, 385 | 397, 34, 35, 65, 209, 454, 12, 388, 502, 371, 386 | 296, 297, 270, 138, 368, 363, 262, 361, 357, 352, 387 | 207, 13, 14, 15, 16, 217, 17, 31, 61, 291, 388 | 350, 290, 348, 34, 35, 326, 308, 271, 303, 269, 389 | 253, 304, 139, 261, 309, 34, 35, 56, 254, 396, 390 | 318, 180, 181, 182, 183, 184, 185, 325, 325, 230, 391 | 70, 69, 73, 34, 35, 326, 223, 130, 114, 62, 392 | 329, 63, 66, 67, 68, 71, 72, 333, 109, 110, 393 | 111, 112, 113, 18, 104, 74, 87, 395, 394, 90, 394 | 20, 19, 322, 323, 140, 141, 142, 89, 143, 393, 395 | 324, 500, 487, 392, 391, 58, 59, 375, 501, 488, 396 | 102, 33, 57, 213, 374, 214, 215, 34, 35, 218, 397 | 255, 216, 252, 330, 245, 244, 243, 346, 236, 225, 398 | 331, 86, 318, 82, 325, 81, 80, 79, 356, 25, 399 | 24, 23, 325, 22, 101, 360, 349, 351, 353, 91, 400 | 97, 217, 34, 35, 329, 358, 484, 483, 362, 364, 401 | 367, 369, 34, 35, 372, 39, 40, 45, 46, 47, 402 | 48, 49, 50, 41, 42, 43, 44, 51, 52, 34, 403 | 35, 135, 34, 35, 133, 34, 35, 129, 34, 35, 404 | 118, 239, 347, 238, 503, 387, 34, 35, 389, 124, 405 | 467, 125, 344, 359, 355, 354, 316, 302, 301, 298, 406 | 263, 413, 260, 259, 258, 257, 256, 237, 446, 233, 407 | 229, 228, 227, 226, 453, 123, 122, 107, 100, 99, 408 | 84, 36, 462, 28, 27, 26, 468, 490, 470, 489, 409 | 482, 481, 54, 480, 476, 475, 478, 479, 477, 473, 410 | 472, 471, 469, 466, 465, 486, 464, 459, 458, 457, 411 | 456, 455, 451, 450, 449, 448, 447, 390, 376, 370, 412 | 345, 313, 312, 311, 497, 146, 147, 148, 149, 150, 413 | 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 414 | 161, 162, 163, 310, 307, 164, 165, 166, 167, 168, 415 | 169, 306, 305, 300, 299, 499, 292, 272, 497, 505, 416 | 268, 267, 266, 265, 264, 251, 250, 249, 248, 242, 417 | 241, 240, 170, 171, 172, 173, 174, 175, 176, 177, 418 | 232, 126, 103, 98, 95, 94, 93, 92, 85, 83, 419 | 1, 211, 328, 21, 320, 440, 429, 415, 492, 406, 420 | 399, 378, 293, 29, 206, 179, 343, 339, 335, 332, 421 | 145, 315, 137, 76, 38, 11, 10, 9, 8, 7, 422 | 6, 5, 4, 3, 2, 423 | } 424 | var yyPact = [...]int{ 425 | 426 | 180, -1000, 180, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 427 | -1000, -1000, 319, 317, 316, 315, 419, 418, 417, 89, 428 | 415, -1000, 338, 227, 183, 2, 313, 312, 311, 309, 429 | -1000, 525, 414, 524, -1000, -1000, 307, 261, 338, 273, 430 | 332, 523, 522, 521, 520, 334, 519, 413, 412, 326, 431 | 291, 518, -1000, 259, 227, -1000, -1000, 344, 411, 198, 432 | 243, 183, 344, 370, -1000, -1000, 344, 344, 344, 410, 433 | 409, 385, 517, 198, 367, 242, 2, 364, 361, 197, 434 | 428, 147, 27, -1000, -1000, -1000, 66, -1000, -1000, 299, 435 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 436 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 437 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 438 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 439 | -1000, -1000, -14, -17, -27, -34, 241, 197, -1000, 305, 440 | 407, 406, 405, 404, 234, 428, -1000, 516, -1000, -1000, 441 | 403, 344, 344, 304, 401, 377, -1000, 507, 506, 505, 442 | 302, 301, 300, 96, 504, 503, 502, 501, -1000, 298, 443 | 224, 296, -1000, 400, 399, 398, 397, 396, 218, 147, 444 | 394, 500, 499, 498, 497, 496, 214, 27, 183, 493, 445 | 58, 25, 58, 25, 492, -73, 344, 344, 393, -1000, 446 | -1000, 490, 489, 392, 391, 213, 66, 488, 487, 480, 447 | 211, 299, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 479, 448 | 459, 458, 457, -1000, -1000, 390, -1000, -1000, -1000, -1000, 449 | -1000, -1000, -1000, -1000, -1000, -1000, 344, -1000, -1000, -1000, 450 | -1000, -1000, -1000, 215, 245, 27, -1000, -1000, -1000, -1000, 451 | -1000, -1000, 64, -1000, 50, 386, -1000, -1000, -1000, -1000, 452 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 453 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 454 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 455 | -1000, -1000, -1000, -1000, -1000, -1000, 456, 378, -1000, -1000, 456 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 457 | -1000, -1000, -1000, -1000, 207, 390, -1000, 205, 344, 194, 458 | 215, -1000, 389, 388, 344, -1000, -1000, 193, 245, -1000, 459 | 387, 344, 192, 27, 190, 64, 55, 299, 189, 50, 460 | -1000, 455, 184, 386, -52, -1000, 290, 283, -1000, -1000, 461 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 462 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 463 | -1000, -1000, -1000, 454, 29, 29, -1000, 182, 29, 453, 464 | -1000, 280, 279, 275, 264, 263, 225, 175, -1000, -1000, 465 | -1000, -101, -94, -94, -29, -5, -119, -1000, 166, -101, 466 | 452, 451, 450, 449, 448, 162, -94, 181, 447, 446, 467 | 445, 444, 443, 133, 103, -29, -1000, 90, 442, 440, 468 | 439, 384, 344, 438, 344, 437, 436, 435, 77, -5, 469 | 344, 434, 344, 433, 429, 427, 426, 341, 340, 69, 470 | -119, 286, 425, 423, -1000, -1000, -1000, -1000, -1000, -1000, 471 | -1000, -1000, -1000, -1000, -75, -1000, -1000, -1000, -1000, -1000, 472 | -1000, -1000, -1000, -55, -1000, -1000, -1000, -1000, -1000, -1000, 473 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 474 | -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 475 | -1000, 61, -75, 285, 186, 380, 54, -55, -1000, -1000, 476 | -1000, -1000, -1000, -1000, -1000, -1000, 477 | } 478 | var yyPgo = [...]int{ 479 | 480 | 0, 530, 564, 563, 562, 561, 560, 559, 558, 557, 481 | 556, 555, 102, 554, 22, 3, 134, 38, 101, 553, 482 | 41, 552, 20, 551, 34, 550, 18, 17, 16, 549, 483 | 13, 11, 10, 548, 12, 547, 546, 26, 545, 21, 484 | 14, 29, 24, 544, 543, 19, 28, 25, 542, 9, 485 | 541, 8, 7, 6, 5, 4, 540, 539, 2, 538, 486 | 537, 0, 1, 536, 535, 534, 532, 15, 531, 432, 487 | 83, 488 | } 489 | var yyR1 = [...]int{ 490 | 491 | 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 492 | 2, 2, 2, 3, 12, 12, 13, 13, 13, 13, 493 | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 494 | 13, 13, 13, 4, 5, 6, 18, 18, 7, 20, 495 | 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 496 | 23, 8, 24, 24, 25, 25, 25, 25, 25, 25, 497 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 498 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 499 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 500 | 30, 30, 33, 33, 33, 33, 31, 31, 35, 35, 501 | 26, 26, 32, 32, 36, 36, 36, 9, 37, 37, 502 | 38, 38, 38, 38, 38, 38, 38, 29, 29, 39, 503 | 39, 11, 42, 42, 43, 43, 43, 43, 10, 40, 504 | 40, 44, 44, 44, 44, 39, 39, 39, 39, 39, 505 | 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 506 | 39, 39, 39, 49, 49, 50, 50, 50, 50, 50, 507 | 50, 50, 50, 50, 51, 51, 56, 56, 56, 56, 508 | 56, 56, 52, 52, 57, 57, 57, 57, 57, 57, 509 | 57, 58, 58, 59, 59, 59, 59, 59, 53, 53, 510 | 60, 60, 60, 60, 60, 60, 60, 62, 62, 61, 511 | 61, 61, 61, 61, 61, 61, 54, 54, 63, 63, 512 | 63, 63, 63, 63, 63, 63, 63, 63, 55, 55, 513 | 64, 64, 64, 64, 64, 64, 46, 46, 46, 46, 514 | 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 515 | 47, 47, 47, 48, 48, 48, 27, 27, 28, 28, 516 | 65, 65, 65, 65, 66, 66, 66, 14, 14, 68, 517 | 16, 16, 69, 69, 69, 69, 69, 69, 17, 17, 518 | 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 519 | 41, 41, 41, 41, 41, 41, 41, 19, 19, 19, 520 | 19, 19, 70, 70, 70, 70, 70, 70, 67, 67, 521 | 67, 15, 15, 15, 45, 45, 45, 34, 34, 34, 522 | 34, 34, 34, 34, 523 | } 524 | var yyR2 = [...]int{ 525 | 526 | 0, 2, 1, 0, 1, 1, 1, 1, 1, 1, 527 | 1, 1, 1, 4, 2, 1, 0, 4, 2, 2, 528 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 529 | 2, 2, 1, 4, 4, 4, 2, 1, 5, 2, 530 | 1, 0, 1, 4, 2, 2, 2, 2, 2, 1, 531 | 1, 5, 2, 1, 0, 1, 2, 1, 1, 2, 532 | 2, 2, 4, 2, 2, 2, 1, 2, 2, 2, 533 | 4, 4, 4, 2, 2, 2, 2, 2, 2, 1, 534 | 4, 2, 4, 4, 1, 2, 2, 2, 2, 2, 535 | 2, 1, 0, 2, 2, 2, 2, 1, 1, 2, 536 | 2, 1, 2, 1, 0, 1, 3, 5, 2, 1, 537 | 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 538 | 1, 5, 2, 1, 0, 2, 2, 2, 5, 2, 539 | 1, 0, 1, 2, 2, 0, 2, 2, 2, 2, 540 | 2, 2, 2, 3, 6, 6, 2, 1, 1, 2, 541 | 2, 2, 2, 2, 1, 0, 2, 1, 4, 4, 542 | 4, 4, 4, 4, 2, 1, 0, 2, 2, 2, 543 | 2, 2, 2, 1, 0, 4, 2, 2, 2, 2, 544 | 2, 2, 1, 0, 2, 2, 2, 2, 2, 1, 545 | 0, 1, 4, 2, 2, 2, 2, 2, 1, 0, 546 | 2, 2, 2, 2, 2, 2, 2, 1, 0, 2, 547 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 548 | 0, 2, 2, 2, 2, 1, 0, 1, 1, 1, 549 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 550 | 1, 1, 1, 0, 1, 1, 2, 1, 2, 1, 551 | 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 552 | 2, 1, 0, 1, 1, 2, 2, 2, 2, 1, 553 | 0, 2, 2, 2, 1, 1, 2, 2, 2, 2, 554 | 2, 2, 2, 2, 2, 2, 2, 0, 4, 4, 555 | 4, 4, 0, 1, 1, 1, 1, 1, 0, 1, 556 | 1, 0, 1, 1, 0, 1, 2, 0, 1, 1, 557 | 1, 1, 1, 1, 558 | } 559 | var yyChk = [...]int{ 560 | 561 | -1000, -1, -2, -3, -4, -5, -6, -7, -8, -9, 562 | -10, -11, 16, 31, 32, 33, 34, 36, 93, 101, 563 | 100, -1, 14, 14, 14, 14, 6, 6, 6, -44, 564 | -45, 128, 35, -15, 8, 9, 6, -12, -13, 17, 565 | 18, 25, 26, 27, 28, 19, 20, 21, 22, 23, 566 | 24, 29, 30, -16, -69, -15, 10, 75, 68, 69, 567 | -17, -41, 76, 78, -15, 10, 79, 80, 81, 68, 568 | 67, 82, 83, 69, 92, -18, -19, 77, 78, 14, 569 | 14, 14, 14, 4, 6, 4, 14, 15, -12, 14, 570 | 6, 7, 4, 4, 4, 4, -15, 6, 4, 6, 571 | 6, 8, 9, 4, 15, -16, -15, 6, -70, 70, 572 | 71, 72, 73, 74, 15, -17, -15, -15, 10, -15, 573 | -15, -15, 6, 6, 4, 6, 4, -70, -15, 10, 574 | 15, -18, -15, 10, -15, 10, -20, -21, 6, 35, 575 | 87, 88, 89, 91, -24, -25, 37, 38, 39, 40, 576 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 577 | 51, 52, 53, 54, 57, 58, 59, 60, 61, 62, 578 | 84, 85, 86, 87, 88, 89, 90, 91, -37, -38, 579 | 94, 95, 96, 97, 98, 99, -40, -39, -41, 102, 580 | 103, 104, 105, 106, 122, 123, 126, 127, 155, 156, 581 | 157, 158, 159, 160, 161, -42, -43, -15, 11, 128, 582 | -14, -68, -34, 4, 6, 7, 12, -15, 10, 82, 583 | 82, 82, 82, 15, -20, 14, 6, 6, 6, 6, 584 | 15, -24, 4, 6, -15, -15, 14, 6, 6, 4, 585 | 4, 4, 4, 14, 14, 14, 55, 56, 4, 4, 586 | 4, 4, 14, 6, 14, 14, 6, 6, 6, 6, 587 | 6, 15, -37, 6, 4, 4, 4, 4, 4, 15, 588 | -40, -17, 4, -46, 107, 108, 109, 110, 111, 112, 589 | 113, 114, 115, 116, 117, 118, -47, 119, 120, 121, 590 | -46, -47, 4, -48, 124, 125, -15, -15, 6, 4, 591 | 4, 6, 6, 15, -42, 4, 4, 4, 15, -14, 592 | 4, 4, 4, 4, -22, -23, 6, -26, -15, -27, 593 | -65, -67, 67, 68, 75, -15, 10, -28, -66, -67, 594 | 68, 75, -29, -39, -30, -33, 63, 64, -31, -35, 595 | 6, 97, -32, -36, 6, 4, -45, 4, 15, -22, 596 | 15, -26, 15, -27, 6, 6, -15, 15, -28, 6, 597 | -15, 15, -40, 15, -30, 65, 66, -34, 15, -31, 598 | 4, 15, -32, 97, 14, 14, 4, -49, -50, 97, 599 | 129, 130, 131, 132, 133, 134, 135, -49, 15, -49, 600 | 4, 14, 14, 14, 14, 14, 14, 15, -51, -56, 601 | 141, 140, 145, 151, 154, -52, -57, 136, 140, 141, 602 | 153, 154, 151, -52, -53, -60, -61, 72, 151, 145, 603 | 154, 146, 142, 141, 143, 144, 140, 128, -54, -63, 604 | 142, 141, 143, 144, 140, 128, 145, 147, 148, -55, 605 | -64, 149, 150, 151, 152, 15, -51, 4, 4, 4, 606 | 4, 4, 15, -52, 14, 4, 4, 4, 4, 4, 607 | 15, 15, -53, 14, 4, 4, 4, 6, -15, 4, 608 | -15, 4, 4, 4, 15, -54, -15, 4, -15, 4, 609 | 4, 4, 4, 6, 6, 15, -55, 6, 13, 4, 610 | 4, -58, -59, 137, 138, 139, -62, -61, 15, -58, 611 | 6, 13, 12, 4, 15, -62, 612 | } 613 | var yyDef = [...]int{ 614 | 615 | 3, -2, 2, 4, 5, 6, 7, 8, 9, 10, 616 | 11, 12, 0, 0, 0, 0, 0, 0, 0, -2, 617 | 0, 1, 16, 262, 270, 287, 0, 0, 0, 0, 618 | 132, 0, 0, 305, 302, 303, 0, 0, 15, 0, 619 | 0, 0, 0, 0, 0, 301, 0, 0, 0, 0, 620 | 0, 0, 32, 0, 261, 263, 264, 301, 0, 292, 621 | 0, 269, 301, 301, 274, 275, 301, 301, 301, 0, 622 | 0, 0, 0, 292, 301, 0, 37, 301, 301, 41, 623 | 54, 110, 135, 133, 134, 306, 124, 13, 14, 301, 624 | 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 625 | 28, 29, 30, 31, 33, 260, 265, 266, 267, 293, 626 | 294, 295, 296, 297, 34, 268, 271, 272, 273, 276, 627 | 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 628 | 35, 36, 0, 0, 0, 0, 0, 40, 42, 0, 629 | 0, 0, 0, 0, 0, 53, 55, 0, 57, 58, 630 | 0, 301, 301, 0, 0, 0, 66, 0, 0, 0, 631 | 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 632 | 0, 0, 84, 0, 0, 0, 0, 0, 0, 109, 633 | 0, 0, 0, 0, 0, 0, 0, 130, 120, 0, 634 | 226, 239, 226, 239, 0, 243, 301, 301, 0, 147, 635 | 148, 0, 0, 0, 0, 0, -2, 0, 0, 0, 636 | 0, 258, 259, 308, 309, 310, 311, 312, 313, 0, 637 | 0, 0, 0, 38, 39, 0, 44, 45, 46, 47, 638 | 51, 52, 56, 59, 60, 61, 301, 63, 64, 65, 639 | 67, 68, 69, 298, 298, 135, 73, 74, 75, 76, 640 | 77, 78, 92, 81, 0, 104, 85, 86, 87, 88, 641 | 89, 107, 108, 111, 112, 113, 114, 115, 116, 128, 642 | 129, 119, 136, 137, 227, 228, 229, 230, 231, 232, 643 | 233, 234, 235, 236, 237, 238, 138, 240, 241, 242, 644 | 139, 140, 141, 142, 244, 245, 0, 301, 146, 149, 645 | 150, 151, 152, 121, 122, 125, 126, 127, 17, 257, 646 | 288, 290, 289, 291, 0, 49, 50, 0, 101, 0, 647 | 247, 250, 0, 0, 301, 299, 300, 0, 249, 254, 648 | 0, 301, 0, 118, 0, 91, 0, 301, 0, 97, 649 | 98, 0, 0, 103, 105, 143, 0, 0, 43, 48, 650 | 62, 100, 70, 246, 251, 252, 253, 71, 248, 255, 651 | 256, 72, 117, 80, 90, 93, 94, 95, 82, 96, 652 | 99, 83, 102, 0, 155, 155, 106, 0, 154, 0, 653 | 157, 0, 0, 0, 0, 0, 0, 0, 144, 153, 654 | 156, 166, 174, 174, 190, 208, 220, 145, 0, 165, 655 | 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 656 | 0, 0, 0, 0, 0, 189, 191, 0, 0, 0, 657 | 0, 0, 301, 0, 301, 0, 0, 0, 0, 207, 658 | 301, 0, 301, 0, 0, 0, 0, 0, 0, 0, 659 | 219, 0, 0, 0, 225, 158, 164, 167, 168, 169, 660 | 170, 171, 159, 172, 183, 176, 177, 178, 179, 180, 661 | 160, 161, 188, 199, 193, 194, 195, 196, 200, 201, 662 | 202, 203, 204, 205, 162, 206, 209, 210, 211, 212, 663 | 213, 214, 215, 216, 217, 163, 218, 221, 222, 223, 664 | 224, 0, 182, 0, 0, 0, 0, 198, 175, 181, 665 | 184, 185, 186, 187, 192, 197, 666 | } 667 | var yyTok1 = [...]int{ 668 | 669 | 1, 670 | } 671 | var yyTok2 = [...]int{ 672 | 673 | 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 674 | 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 675 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 676 | 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 677 | 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 678 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 679 | 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 680 | 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 681 | 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 682 | 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 683 | 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 684 | 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 685 | 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 686 | 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 687 | 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 688 | 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 689 | } 690 | var yyTok3 = [...]int{ 691 | 0, 692 | } 693 | 694 | var yyErrorMessages = [...]struct { 695 | state int 696 | token int 697 | msg string 698 | }{} 699 | 700 | //line yaccpar:1 701 | 702 | /* parser for yacc output */ 703 | 704 | var ( 705 | yyDebug = 0 706 | yyErrorVerbose = false 707 | ) 708 | 709 | type yyLexer interface { 710 | Lex(lval *yySymType) int 711 | Error(s string) 712 | } 713 | 714 | type yyParser interface { 715 | Parse(yyLexer) int 716 | Lookahead() int 717 | } 718 | 719 | type yyParserImpl struct { 720 | lval yySymType 721 | stack [yyInitialStackSize]yySymType 722 | char int 723 | } 724 | 725 | func (p *yyParserImpl) Lookahead() int { 726 | return p.char 727 | } 728 | 729 | func yyNewParser() yyParser { 730 | return &yyParserImpl{} 731 | } 732 | 733 | const yyFlag = -1000 734 | 735 | func yyTokname(c int) string { 736 | if c >= 1 && c-1 < len(yyToknames) { 737 | if yyToknames[c-1] != "" { 738 | return yyToknames[c-1] 739 | } 740 | } 741 | return __yyfmt__.Sprintf("tok-%v", c) 742 | } 743 | 744 | func yyStatname(s int) string { 745 | if s >= 0 && s < len(yyStatenames) { 746 | if yyStatenames[s] != "" { 747 | return yyStatenames[s] 748 | } 749 | } 750 | return __yyfmt__.Sprintf("state-%v", s) 751 | } 752 | 753 | func yyErrorMessage(state, lookAhead int) string { 754 | const TOKSTART = 4 755 | 756 | if !yyErrorVerbose { 757 | return "syntax error" 758 | } 759 | 760 | for _, e := range yyErrorMessages { 761 | if e.state == state && e.token == lookAhead { 762 | return "syntax error: " + e.msg 763 | } 764 | } 765 | 766 | res := "syntax error: unexpected " + yyTokname(lookAhead) 767 | 768 | // To match Bison, suggest at most four expected tokens. 769 | expected := make([]int, 0, 4) 770 | 771 | // Look for shiftable tokens. 772 | base := yyPact[state] 773 | for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { 774 | if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok { 775 | if len(expected) == cap(expected) { 776 | return res 777 | } 778 | expected = append(expected, tok) 779 | } 780 | } 781 | 782 | if yyDef[state] == -2 { 783 | i := 0 784 | for yyExca[i] != -1 || yyExca[i+1] != state { 785 | i += 2 786 | } 787 | 788 | // Look for tokens that we accept or reduce. 789 | for i += 2; yyExca[i] >= 0; i += 2 { 790 | tok := yyExca[i] 791 | if tok < TOKSTART || yyExca[i+1] == 0 { 792 | continue 793 | } 794 | if len(expected) == cap(expected) { 795 | return res 796 | } 797 | expected = append(expected, tok) 798 | } 799 | 800 | // If the default action is to accept or reduce, give up. 801 | if yyExca[i+1] != 0 { 802 | return res 803 | } 804 | } 805 | 806 | for i, tok := range expected { 807 | if i == 0 { 808 | res += ", expecting " 809 | } else { 810 | res += " or " 811 | } 812 | res += yyTokname(tok) 813 | } 814 | return res 815 | } 816 | 817 | func yylex1(lex yyLexer, lval *yySymType) (char, token int) { 818 | token = 0 819 | char = lex.Lex(lval) 820 | if char <= 0 { 821 | token = yyTok1[0] 822 | goto out 823 | } 824 | if char < len(yyTok1) { 825 | token = yyTok1[char] 826 | goto out 827 | } 828 | if char >= yyPrivate { 829 | if char < yyPrivate+len(yyTok2) { 830 | token = yyTok2[char-yyPrivate] 831 | goto out 832 | } 833 | } 834 | for i := 0; i < len(yyTok3); i += 2 { 835 | token = yyTok3[i+0] 836 | if token == char { 837 | token = yyTok3[i+1] 838 | goto out 839 | } 840 | } 841 | 842 | out: 843 | if token == 0 { 844 | token = yyTok2[1] /* unknown char */ 845 | } 846 | if yyDebug >= 3 { 847 | __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) 848 | } 849 | return char, token 850 | } 851 | 852 | func yyParse(yylex yyLexer) int { 853 | return yyNewParser().Parse(yylex) 854 | } 855 | 856 | func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int { 857 | var yyn int 858 | var yyVAL yySymType 859 | var yyDollar []yySymType 860 | _ = yyDollar // silence set and not used 861 | yyS := yyrcvr.stack[:] 862 | 863 | Nerrs := 0 /* number of errors */ 864 | Errflag := 0 /* error recovery flag */ 865 | yystate := 0 866 | yyrcvr.char = -1 867 | yytoken := -1 // yyrcvr.char translated into internal numbering 868 | defer func() { 869 | // Make sure we report no lookahead when not parsing. 870 | yystate = -1 871 | yyrcvr.char = -1 872 | yytoken = -1 873 | }() 874 | yyp := -1 875 | goto yystack 876 | 877 | ret0: 878 | return 0 879 | 880 | ret1: 881 | return 1 882 | 883 | yystack: 884 | /* put a state and value onto the stack */ 885 | if yyDebug >= 4 { 886 | __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) 887 | } 888 | 889 | yyp++ 890 | if yyp >= len(yyS) { 891 | nyys := make([]yySymType, len(yyS)*2) 892 | copy(nyys, yyS) 893 | yyS = nyys 894 | } 895 | yyS[yyp] = yyVAL 896 | yyS[yyp].yys = yystate 897 | 898 | yynewstate: 899 | yyn = yyPact[yystate] 900 | if yyn <= yyFlag { 901 | goto yydefault /* simple state */ 902 | } 903 | if yyrcvr.char < 0 { 904 | yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) 905 | } 906 | yyn += yytoken 907 | if yyn < 0 || yyn >= yyLast { 908 | goto yydefault 909 | } 910 | yyn = yyAct[yyn] 911 | if yyChk[yyn] == yytoken { /* valid shift */ 912 | yyrcvr.char = -1 913 | yytoken = -1 914 | yyVAL = yyrcvr.lval 915 | yystate = yyn 916 | if Errflag > 0 { 917 | Errflag-- 918 | } 919 | goto yystack 920 | } 921 | 922 | yydefault: 923 | /* default state action */ 924 | yyn = yyDef[yystate] 925 | if yyn == -2 { 926 | if yyrcvr.char < 0 { 927 | yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) 928 | } 929 | 930 | /* look through exception table */ 931 | xi := 0 932 | for { 933 | if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { 934 | break 935 | } 936 | xi += 2 937 | } 938 | for xi += 2; ; xi += 2 { 939 | yyn = yyExca[xi+0] 940 | if yyn < 0 || yyn == yytoken { 941 | break 942 | } 943 | } 944 | yyn = yyExca[xi+1] 945 | if yyn < 0 { 946 | goto ret0 947 | } 948 | } 949 | if yyn == 0 { 950 | /* error ... attempt to resume parsing */ 951 | switch Errflag { 952 | case 0: /* brand new error */ 953 | yylex.Error(yyErrorMessage(yystate, yytoken)) 954 | Nerrs++ 955 | if yyDebug >= 1 { 956 | __yyfmt__.Printf("%s", yyStatname(yystate)) 957 | __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) 958 | } 959 | fallthrough 960 | 961 | case 1, 2: /* incompletely recovered error ... try again */ 962 | Errflag = 3 963 | 964 | /* find a state where "error" is a legal shift action */ 965 | for yyp >= 0 { 966 | yyn = yyPact[yyS[yyp].yys] + yyErrCode 967 | if yyn >= 0 && yyn < yyLast { 968 | yystate = yyAct[yyn] /* simulate a shift of "error" */ 969 | if yyChk[yystate] == yyErrCode { 970 | goto yystack 971 | } 972 | } 973 | 974 | /* the current p has no shift on "error", pop stack */ 975 | if yyDebug >= 2 { 976 | __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) 977 | } 978 | yyp-- 979 | } 980 | /* there is no state on the stack with an error shift ... abort */ 981 | goto ret1 982 | 983 | case 3: /* no shift yet; clobber input char */ 984 | if yyDebug >= 2 { 985 | __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) 986 | } 987 | if yytoken == yyEofCode { 988 | goto ret1 989 | } 990 | yyrcvr.char = -1 991 | yytoken = -1 992 | goto yynewstate /* try again in the same state */ 993 | } 994 | } 995 | 996 | /* reduction by production yyn */ 997 | if yyDebug >= 2 { 998 | __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) 999 | } 1000 | 1001 | yynt := yyn 1002 | yypt := yyp 1003 | _ = yypt // guard against "declared and not used" 1004 | 1005 | yyp -= yyR2[yyn] 1006 | // yyp is now the index of $0. Perform the default action. Iff the 1007 | // reduced production is ε, $1 is possibly out of range. 1008 | if yyp+1 >= len(yyS) { 1009 | nyys := make([]yySymType, len(yyS)*2) 1010 | copy(nyys, yyS) 1011 | yyS = nyys 1012 | } 1013 | yyVAL = yyS[yyp+1] 1014 | 1015 | /* consult goto table to find next state */ 1016 | yyn = yyR1[yyn] 1017 | yyg := yyPgo[yyn] 1018 | yyj := yyg + yyS[yyp].yys + 1 1019 | 1020 | if yyj >= yyLast { 1021 | yystate = yyAct[yyg] 1022 | } else { 1023 | yystate = yyAct[yyj] 1024 | if yyChk[yystate] != -yyn { 1025 | yystate = yyAct[yyg] 1026 | } 1027 | } 1028 | // dummy call; replaced with literal code 1029 | switch yynt { 1030 | 1031 | case 2: 1032 | yyDollar = yyS[yypt-1 : yypt+1] 1033 | //line parser/parser.go.y:29 1034 | { 1035 | } 1036 | case 3: 1037 | yyDollar = yyS[yypt-0 : yypt+1] 1038 | //line parser/parser.go.y:31 1039 | { 1040 | } 1041 | case 4: 1042 | yyDollar = yyS[yypt-1 : yypt+1] 1043 | //line parser/parser.go.y:32 1044 | { 1045 | } 1046 | case 5: 1047 | yyDollar = yyS[yypt-1 : yypt+1] 1048 | //line parser/parser.go.y:33 1049 | { 1050 | } 1051 | case 6: 1052 | yyDollar = yyS[yypt-1 : yypt+1] 1053 | //line parser/parser.go.y:34 1054 | { 1055 | } 1056 | case 7: 1057 | yyDollar = yyS[yypt-1 : yypt+1] 1058 | //line parser/parser.go.y:35 1059 | { 1060 | } 1061 | case 8: 1062 | yyDollar = yyS[yypt-1 : yypt+1] 1063 | //line parser/parser.go.y:36 1064 | { 1065 | } 1066 | case 9: 1067 | yyDollar = yyS[yypt-1 : yypt+1] 1068 | //line parser/parser.go.y:37 1069 | { 1070 | } 1071 | case 10: 1072 | yyDollar = yyS[yypt-1 : yypt+1] 1073 | //line parser/parser.go.y:38 1074 | { 1075 | } 1076 | case 11: 1077 | yyDollar = yyS[yypt-1 : yypt+1] 1078 | //line parser/parser.go.y:39 1079 | { 1080 | } 1081 | case 12: 1082 | yyDollar = yyS[yypt-1 : yypt+1] 1083 | //line parser/parser.go.y:40 1084 | { 1085 | } 1086 | case 17: 1087 | yyDollar = yyS[yypt-4 : yypt+1] 1088 | //line parser/parser.go.y:47 1089 | { 1090 | } 1091 | case 18: 1092 | yyDollar = yyS[yypt-2 : yypt+1] 1093 | //line parser/parser.go.y:48 1094 | { 1095 | } 1096 | case 19: 1097 | yyDollar = yyS[yypt-2 : yypt+1] 1098 | //line parser/parser.go.y:49 1099 | { 1100 | } 1101 | case 20: 1102 | yyDollar = yyS[yypt-2 : yypt+1] 1103 | //line parser/parser.go.y:50 1104 | { 1105 | } 1106 | case 21: 1107 | yyDollar = yyS[yypt-2 : yypt+1] 1108 | //line parser/parser.go.y:51 1109 | { 1110 | } 1111 | case 22: 1112 | yyDollar = yyS[yypt-2 : yypt+1] 1113 | //line parser/parser.go.y:52 1114 | { 1115 | } 1116 | case 23: 1117 | yyDollar = yyS[yypt-2 : yypt+1] 1118 | //line parser/parser.go.y:53 1119 | { 1120 | } 1121 | case 24: 1122 | yyDollar = yyS[yypt-2 : yypt+1] 1123 | //line parser/parser.go.y:54 1124 | { 1125 | } 1126 | case 25: 1127 | yyDollar = yyS[yypt-2 : yypt+1] 1128 | //line parser/parser.go.y:55 1129 | { 1130 | } 1131 | case 26: 1132 | yyDollar = yyS[yypt-2 : yypt+1] 1133 | //line parser/parser.go.y:56 1134 | { 1135 | } 1136 | case 27: 1137 | yyDollar = yyS[yypt-2 : yypt+1] 1138 | //line parser/parser.go.y:57 1139 | { 1140 | } 1141 | case 28: 1142 | yyDollar = yyS[yypt-2 : yypt+1] 1143 | //line parser/parser.go.y:58 1144 | { 1145 | } 1146 | case 29: 1147 | yyDollar = yyS[yypt-2 : yypt+1] 1148 | //line parser/parser.go.y:59 1149 | { 1150 | } 1151 | case 30: 1152 | yyDollar = yyS[yypt-2 : yypt+1] 1153 | //line parser/parser.go.y:60 1154 | { 1155 | } 1156 | case 31: 1157 | yyDollar = yyS[yypt-2 : yypt+1] 1158 | //line parser/parser.go.y:61 1159 | { 1160 | } 1161 | case 41: 1162 | yyDollar = yyS[yypt-0 : yypt+1] 1163 | //line parser/parser.go.y:76 1164 | { 1165 | } 1166 | case 42: 1167 | yyDollar = yyS[yypt-1 : yypt+1] 1168 | //line parser/parser.go.y:77 1169 | { 1170 | } 1171 | case 43: 1172 | yyDollar = yyS[yypt-4 : yypt+1] 1173 | //line parser/parser.go.y:78 1174 | { 1175 | } 1176 | case 44: 1177 | yyDollar = yyS[yypt-2 : yypt+1] 1178 | //line parser/parser.go.y:79 1179 | { 1180 | } 1181 | case 45: 1182 | yyDollar = yyS[yypt-2 : yypt+1] 1183 | //line parser/parser.go.y:80 1184 | { 1185 | } 1186 | case 46: 1187 | yyDollar = yyS[yypt-2 : yypt+1] 1188 | //line parser/parser.go.y:81 1189 | { 1190 | } 1191 | case 47: 1192 | yyDollar = yyS[yypt-2 : yypt+1] 1193 | //line parser/parser.go.y:82 1194 | { 1195 | } 1196 | case 49: 1197 | yyDollar = yyS[yypt-1 : yypt+1] 1198 | //line parser/parser.go.y:84 1199 | { 1200 | } 1201 | case 54: 1202 | yyDollar = yyS[yypt-0 : yypt+1] 1203 | //line parser/parser.go.y:92 1204 | { 1205 | } 1206 | case 55: 1207 | yyDollar = yyS[yypt-1 : yypt+1] 1208 | //line parser/parser.go.y:93 1209 | { 1210 | } 1211 | case 56: 1212 | yyDollar = yyS[yypt-2 : yypt+1] 1213 | //line parser/parser.go.y:94 1214 | { 1215 | } 1216 | case 57: 1217 | yyDollar = yyS[yypt-1 : yypt+1] 1218 | //line parser/parser.go.y:95 1219 | { 1220 | } 1221 | case 58: 1222 | yyDollar = yyS[yypt-1 : yypt+1] 1223 | //line parser/parser.go.y:96 1224 | { 1225 | } 1226 | case 59: 1227 | yyDollar = yyS[yypt-2 : yypt+1] 1228 | //line parser/parser.go.y:97 1229 | { 1230 | } 1231 | case 60: 1232 | yyDollar = yyS[yypt-2 : yypt+1] 1233 | //line parser/parser.go.y:98 1234 | { 1235 | } 1236 | case 61: 1237 | yyDollar = yyS[yypt-2 : yypt+1] 1238 | //line parser/parser.go.y:99 1239 | { 1240 | } 1241 | case 62: 1242 | yyDollar = yyS[yypt-4 : yypt+1] 1243 | //line parser/parser.go.y:100 1244 | { 1245 | } 1246 | case 63: 1247 | yyDollar = yyS[yypt-2 : yypt+1] 1248 | //line parser/parser.go.y:101 1249 | { 1250 | } 1251 | case 64: 1252 | yyDollar = yyS[yypt-2 : yypt+1] 1253 | //line parser/parser.go.y:102 1254 | { 1255 | } 1256 | case 65: 1257 | yyDollar = yyS[yypt-2 : yypt+1] 1258 | //line parser/parser.go.y:103 1259 | { 1260 | } 1261 | case 67: 1262 | yyDollar = yyS[yypt-2 : yypt+1] 1263 | //line parser/parser.go.y:105 1264 | { 1265 | } 1266 | case 68: 1267 | yyDollar = yyS[yypt-2 : yypt+1] 1268 | //line parser/parser.go.y:106 1269 | { 1270 | } 1271 | case 69: 1272 | yyDollar = yyS[yypt-2 : yypt+1] 1273 | //line parser/parser.go.y:107 1274 | { 1275 | } 1276 | case 73: 1277 | yyDollar = yyS[yypt-2 : yypt+1] 1278 | //line parser/parser.go.y:111 1279 | { 1280 | } 1281 | case 74: 1282 | yyDollar = yyS[yypt-2 : yypt+1] 1283 | //line parser/parser.go.y:112 1284 | { 1285 | } 1286 | case 75: 1287 | yyDollar = yyS[yypt-2 : yypt+1] 1288 | //line parser/parser.go.y:113 1289 | { 1290 | } 1291 | case 76: 1292 | yyDollar = yyS[yypt-2 : yypt+1] 1293 | //line parser/parser.go.y:114 1294 | { 1295 | } 1296 | case 77: 1297 | yyDollar = yyS[yypt-2 : yypt+1] 1298 | //line parser/parser.go.y:115 1299 | { 1300 | } 1301 | case 78: 1302 | yyDollar = yyS[yypt-2 : yypt+1] 1303 | //line parser/parser.go.y:116 1304 | { 1305 | } 1306 | case 79: 1307 | yyDollar = yyS[yypt-1 : yypt+1] 1308 | //line parser/parser.go.y:117 1309 | { 1310 | } 1311 | case 80: 1312 | yyDollar = yyS[yypt-4 : yypt+1] 1313 | //line parser/parser.go.y:118 1314 | { 1315 | } 1316 | case 81: 1317 | yyDollar = yyS[yypt-2 : yypt+1] 1318 | //line parser/parser.go.y:119 1319 | { 1320 | } 1321 | case 82: 1322 | yyDollar = yyS[yypt-4 : yypt+1] 1323 | //line parser/parser.go.y:120 1324 | { 1325 | } 1326 | case 83: 1327 | yyDollar = yyS[yypt-4 : yypt+1] 1328 | //line parser/parser.go.y:121 1329 | { 1330 | } 1331 | case 84: 1332 | yyDollar = yyS[yypt-1 : yypt+1] 1333 | //line parser/parser.go.y:122 1334 | { 1335 | } 1336 | case 85: 1337 | yyDollar = yyS[yypt-2 : yypt+1] 1338 | //line parser/parser.go.y:123 1339 | { 1340 | } 1341 | case 86: 1342 | yyDollar = yyS[yypt-2 : yypt+1] 1343 | //line parser/parser.go.y:124 1344 | { 1345 | } 1346 | case 87: 1347 | yyDollar = yyS[yypt-2 : yypt+1] 1348 | //line parser/parser.go.y:125 1349 | { 1350 | } 1351 | case 88: 1352 | yyDollar = yyS[yypt-2 : yypt+1] 1353 | //line parser/parser.go.y:126 1354 | { 1355 | } 1356 | case 89: 1357 | yyDollar = yyS[yypt-2 : yypt+1] 1358 | //line parser/parser.go.y:127 1359 | { 1360 | } 1361 | case 92: 1362 | yyDollar = yyS[yypt-0 : yypt+1] 1363 | //line parser/parser.go.y:131 1364 | { 1365 | } 1366 | case 93: 1367 | yyDollar = yyS[yypt-2 : yypt+1] 1368 | //line parser/parser.go.y:132 1369 | { 1370 | } 1371 | case 94: 1372 | yyDollar = yyS[yypt-2 : yypt+1] 1373 | //line parser/parser.go.y:133 1374 | { 1375 | } 1376 | case 95: 1377 | yyDollar = yyS[yypt-2 : yypt+1] 1378 | //line parser/parser.go.y:134 1379 | { 1380 | } 1381 | case 99: 1382 | yyDollar = yyS[yypt-2 : yypt+1] 1383 | //line parser/parser.go.y:139 1384 | { 1385 | } 1386 | case 104: 1387 | yyDollar = yyS[yypt-0 : yypt+1] 1388 | //line parser/parser.go.y:145 1389 | { 1390 | } 1391 | case 105: 1392 | yyDollar = yyS[yypt-1 : yypt+1] 1393 | //line parser/parser.go.y:146 1394 | { 1395 | } 1396 | case 106: 1397 | yyDollar = yyS[yypt-3 : yypt+1] 1398 | //line parser/parser.go.y:147 1399 | { 1400 | } 1401 | case 110: 1402 | yyDollar = yyS[yypt-0 : yypt+1] 1403 | //line parser/parser.go.y:153 1404 | { 1405 | } 1406 | case 111: 1407 | yyDollar = yyS[yypt-2 : yypt+1] 1408 | //line parser/parser.go.y:154 1409 | { 1410 | } 1411 | case 112: 1412 | yyDollar = yyS[yypt-2 : yypt+1] 1413 | //line parser/parser.go.y:155 1414 | { 1415 | } 1416 | case 113: 1417 | yyDollar = yyS[yypt-2 : yypt+1] 1418 | //line parser/parser.go.y:156 1419 | { 1420 | } 1421 | case 114: 1422 | yyDollar = yyS[yypt-2 : yypt+1] 1423 | //line parser/parser.go.y:157 1424 | { 1425 | } 1426 | case 115: 1427 | yyDollar = yyS[yypt-2 : yypt+1] 1428 | //line parser/parser.go.y:158 1429 | { 1430 | } 1431 | case 116: 1432 | yyDollar = yyS[yypt-2 : yypt+1] 1433 | //line parser/parser.go.y:159 1434 | { 1435 | } 1436 | case 124: 1437 | yyDollar = yyS[yypt-0 : yypt+1] 1438 | //line parser/parser.go.y:169 1439 | { 1440 | } 1441 | case 125: 1442 | yyDollar = yyS[yypt-2 : yypt+1] 1443 | //line parser/parser.go.y:170 1444 | { 1445 | } 1446 | case 126: 1447 | yyDollar = yyS[yypt-2 : yypt+1] 1448 | //line parser/parser.go.y:171 1449 | { 1450 | } 1451 | case 127: 1452 | yyDollar = yyS[yypt-2 : yypt+1] 1453 | //line parser/parser.go.y:172 1454 | { 1455 | } 1456 | case 133: 1457 | yyDollar = yyS[yypt-2 : yypt+1] 1458 | //line parser/parser.go.y:180 1459 | { 1460 | } 1461 | case 134: 1462 | yyDollar = yyS[yypt-2 : yypt+1] 1463 | //line parser/parser.go.y:181 1464 | { 1465 | } 1466 | case 135: 1467 | yyDollar = yyS[yypt-0 : yypt+1] 1468 | //line parser/parser.go.y:183 1469 | { 1470 | } 1471 | case 136: 1472 | yyDollar = yyS[yypt-2 : yypt+1] 1473 | //line parser/parser.go.y:184 1474 | { 1475 | } 1476 | case 137: 1477 | yyDollar = yyS[yypt-2 : yypt+1] 1478 | //line parser/parser.go.y:185 1479 | { 1480 | } 1481 | case 138: 1482 | yyDollar = yyS[yypt-2 : yypt+1] 1483 | //line parser/parser.go.y:186 1484 | { 1485 | } 1486 | case 139: 1487 | yyDollar = yyS[yypt-2 : yypt+1] 1488 | //line parser/parser.go.y:187 1489 | { 1490 | } 1491 | case 140: 1492 | yyDollar = yyS[yypt-2 : yypt+1] 1493 | //line parser/parser.go.y:188 1494 | { 1495 | } 1496 | case 141: 1497 | yyDollar = yyS[yypt-2 : yypt+1] 1498 | //line parser/parser.go.y:189 1499 | { 1500 | } 1501 | case 142: 1502 | yyDollar = yyS[yypt-2 : yypt+1] 1503 | //line parser/parser.go.y:190 1504 | { 1505 | } 1506 | case 143: 1507 | yyDollar = yyS[yypt-3 : yypt+1] 1508 | //line parser/parser.go.y:191 1509 | { 1510 | } 1511 | case 146: 1512 | yyDollar = yyS[yypt-2 : yypt+1] 1513 | //line parser/parser.go.y:194 1514 | { 1515 | } 1516 | case 149: 1517 | yyDollar = yyS[yypt-2 : yypt+1] 1518 | //line parser/parser.go.y:197 1519 | { 1520 | } 1521 | case 150: 1522 | yyDollar = yyS[yypt-2 : yypt+1] 1523 | //line parser/parser.go.y:198 1524 | { 1525 | } 1526 | case 151: 1527 | yyDollar = yyS[yypt-2 : yypt+1] 1528 | //line parser/parser.go.y:199 1529 | { 1530 | } 1531 | case 152: 1532 | yyDollar = yyS[yypt-2 : yypt+1] 1533 | //line parser/parser.go.y:200 1534 | { 1535 | } 1536 | case 154: 1537 | yyDollar = yyS[yypt-1 : yypt+1] 1538 | //line parser/parser.go.y:202 1539 | { 1540 | } 1541 | case 155: 1542 | yyDollar = yyS[yypt-0 : yypt+1] 1543 | //line parser/parser.go.y:204 1544 | { 1545 | } 1546 | case 156: 1547 | yyDollar = yyS[yypt-2 : yypt+1] 1548 | //line parser/parser.go.y:205 1549 | { 1550 | } 1551 | case 157: 1552 | yyDollar = yyS[yypt-1 : yypt+1] 1553 | //line parser/parser.go.y:206 1554 | { 1555 | } 1556 | case 158: 1557 | yyDollar = yyS[yypt-4 : yypt+1] 1558 | //line parser/parser.go.y:207 1559 | { 1560 | } 1561 | case 159: 1562 | yyDollar = yyS[yypt-4 : yypt+1] 1563 | //line parser/parser.go.y:208 1564 | { 1565 | } 1566 | case 160: 1567 | yyDollar = yyS[yypt-4 : yypt+1] 1568 | //line parser/parser.go.y:209 1569 | { 1570 | } 1571 | case 161: 1572 | yyDollar = yyS[yypt-4 : yypt+1] 1573 | //line parser/parser.go.y:210 1574 | { 1575 | } 1576 | case 162: 1577 | yyDollar = yyS[yypt-4 : yypt+1] 1578 | //line parser/parser.go.y:211 1579 | { 1580 | } 1581 | case 163: 1582 | yyDollar = yyS[yypt-4 : yypt+1] 1583 | //line parser/parser.go.y:212 1584 | { 1585 | } 1586 | case 165: 1587 | yyDollar = yyS[yypt-1 : yypt+1] 1588 | //line parser/parser.go.y:214 1589 | { 1590 | } 1591 | case 166: 1592 | yyDollar = yyS[yypt-0 : yypt+1] 1593 | //line parser/parser.go.y:216 1594 | { 1595 | } 1596 | case 167: 1597 | yyDollar = yyS[yypt-2 : yypt+1] 1598 | //line parser/parser.go.y:217 1599 | { 1600 | } 1601 | case 168: 1602 | yyDollar = yyS[yypt-2 : yypt+1] 1603 | //line parser/parser.go.y:218 1604 | { 1605 | } 1606 | case 169: 1607 | yyDollar = yyS[yypt-2 : yypt+1] 1608 | //line parser/parser.go.y:219 1609 | { 1610 | } 1611 | case 170: 1612 | yyDollar = yyS[yypt-2 : yypt+1] 1613 | //line parser/parser.go.y:220 1614 | { 1615 | } 1616 | case 171: 1617 | yyDollar = yyS[yypt-2 : yypt+1] 1618 | //line parser/parser.go.y:221 1619 | { 1620 | } 1621 | case 173: 1622 | yyDollar = yyS[yypt-1 : yypt+1] 1623 | //line parser/parser.go.y:223 1624 | { 1625 | } 1626 | case 174: 1627 | yyDollar = yyS[yypt-0 : yypt+1] 1628 | //line parser/parser.go.y:225 1629 | { 1630 | } 1631 | case 175: 1632 | yyDollar = yyS[yypt-4 : yypt+1] 1633 | //line parser/parser.go.y:226 1634 | { 1635 | } 1636 | case 176: 1637 | yyDollar = yyS[yypt-2 : yypt+1] 1638 | //line parser/parser.go.y:227 1639 | { 1640 | } 1641 | case 177: 1642 | yyDollar = yyS[yypt-2 : yypt+1] 1643 | //line parser/parser.go.y:228 1644 | { 1645 | } 1646 | case 178: 1647 | yyDollar = yyS[yypt-2 : yypt+1] 1648 | //line parser/parser.go.y:229 1649 | { 1650 | } 1651 | case 179: 1652 | yyDollar = yyS[yypt-2 : yypt+1] 1653 | //line parser/parser.go.y:230 1654 | { 1655 | } 1656 | case 180: 1657 | yyDollar = yyS[yypt-2 : yypt+1] 1658 | //line parser/parser.go.y:231 1659 | { 1660 | } 1661 | case 182: 1662 | yyDollar = yyS[yypt-1 : yypt+1] 1663 | //line parser/parser.go.y:233 1664 | { 1665 | } 1666 | case 183: 1667 | yyDollar = yyS[yypt-0 : yypt+1] 1668 | //line parser/parser.go.y:235 1669 | { 1670 | } 1671 | case 184: 1672 | yyDollar = yyS[yypt-2 : yypt+1] 1673 | //line parser/parser.go.y:236 1674 | { 1675 | } 1676 | case 185: 1677 | yyDollar = yyS[yypt-2 : yypt+1] 1678 | //line parser/parser.go.y:237 1679 | { 1680 | } 1681 | case 186: 1682 | yyDollar = yyS[yypt-2 : yypt+1] 1683 | //line parser/parser.go.y:238 1684 | { 1685 | } 1686 | case 187: 1687 | yyDollar = yyS[yypt-2 : yypt+1] 1688 | //line parser/parser.go.y:239 1689 | { 1690 | } 1691 | case 189: 1692 | yyDollar = yyS[yypt-1 : yypt+1] 1693 | //line parser/parser.go.y:241 1694 | { 1695 | } 1696 | case 190: 1697 | yyDollar = yyS[yypt-0 : yypt+1] 1698 | //line parser/parser.go.y:243 1699 | { 1700 | } 1701 | case 191: 1702 | yyDollar = yyS[yypt-1 : yypt+1] 1703 | //line parser/parser.go.y:244 1704 | { 1705 | } 1706 | case 198: 1707 | yyDollar = yyS[yypt-1 : yypt+1] 1708 | //line parser/parser.go.y:251 1709 | { 1710 | } 1711 | case 199: 1712 | yyDollar = yyS[yypt-0 : yypt+1] 1713 | //line parser/parser.go.y:253 1714 | { 1715 | } 1716 | case 200: 1717 | yyDollar = yyS[yypt-2 : yypt+1] 1718 | //line parser/parser.go.y:254 1719 | { 1720 | } 1721 | case 201: 1722 | yyDollar = yyS[yypt-2 : yypt+1] 1723 | //line parser/parser.go.y:255 1724 | { 1725 | } 1726 | case 202: 1727 | yyDollar = yyS[yypt-2 : yypt+1] 1728 | //line parser/parser.go.y:256 1729 | { 1730 | } 1731 | case 203: 1732 | yyDollar = yyS[yypt-2 : yypt+1] 1733 | //line parser/parser.go.y:257 1734 | { 1735 | } 1736 | case 204: 1737 | yyDollar = yyS[yypt-2 : yypt+1] 1738 | //line parser/parser.go.y:258 1739 | { 1740 | } 1741 | case 205: 1742 | yyDollar = yyS[yypt-2 : yypt+1] 1743 | //line parser/parser.go.y:259 1744 | { 1745 | } 1746 | case 207: 1747 | yyDollar = yyS[yypt-1 : yypt+1] 1748 | //line parser/parser.go.y:261 1749 | { 1750 | } 1751 | case 208: 1752 | yyDollar = yyS[yypt-0 : yypt+1] 1753 | //line parser/parser.go.y:263 1754 | { 1755 | } 1756 | case 209: 1757 | yyDollar = yyS[yypt-2 : yypt+1] 1758 | //line parser/parser.go.y:264 1759 | { 1760 | } 1761 | case 210: 1762 | yyDollar = yyS[yypt-2 : yypt+1] 1763 | //line parser/parser.go.y:265 1764 | { 1765 | } 1766 | case 211: 1767 | yyDollar = yyS[yypt-2 : yypt+1] 1768 | //line parser/parser.go.y:266 1769 | { 1770 | } 1771 | case 212: 1772 | yyDollar = yyS[yypt-2 : yypt+1] 1773 | //line parser/parser.go.y:267 1774 | { 1775 | } 1776 | case 213: 1777 | yyDollar = yyS[yypt-2 : yypt+1] 1778 | //line parser/parser.go.y:268 1779 | { 1780 | } 1781 | case 214: 1782 | yyDollar = yyS[yypt-2 : yypt+1] 1783 | //line parser/parser.go.y:269 1784 | { 1785 | } 1786 | case 215: 1787 | yyDollar = yyS[yypt-2 : yypt+1] 1788 | //line parser/parser.go.y:270 1789 | { 1790 | } 1791 | case 216: 1792 | yyDollar = yyS[yypt-2 : yypt+1] 1793 | //line parser/parser.go.y:271 1794 | { 1795 | } 1796 | case 217: 1797 | yyDollar = yyS[yypt-2 : yypt+1] 1798 | //line parser/parser.go.y:272 1799 | { 1800 | } 1801 | case 219: 1802 | yyDollar = yyS[yypt-1 : yypt+1] 1803 | //line parser/parser.go.y:274 1804 | { 1805 | } 1806 | case 220: 1807 | yyDollar = yyS[yypt-0 : yypt+1] 1808 | //line parser/parser.go.y:276 1809 | { 1810 | } 1811 | case 221: 1812 | yyDollar = yyS[yypt-2 : yypt+1] 1813 | //line parser/parser.go.y:277 1814 | { 1815 | } 1816 | case 222: 1817 | yyDollar = yyS[yypt-2 : yypt+1] 1818 | //line parser/parser.go.y:278 1819 | { 1820 | } 1821 | case 223: 1822 | yyDollar = yyS[yypt-2 : yypt+1] 1823 | //line parser/parser.go.y:279 1824 | { 1825 | } 1826 | case 224: 1827 | yyDollar = yyS[yypt-2 : yypt+1] 1828 | //line parser/parser.go.y:280 1829 | { 1830 | } 1831 | case 225: 1832 | yyDollar = yyS[yypt-1 : yypt+1] 1833 | //line parser/parser.go.y:281 1834 | { 1835 | } 1836 | case 226: 1837 | yyDollar = yyS[yypt-0 : yypt+1] 1838 | //line parser/parser.go.y:283 1839 | { 1840 | } 1841 | case 227: 1842 | yyDollar = yyS[yypt-1 : yypt+1] 1843 | //line parser/parser.go.y:284 1844 | { 1845 | } 1846 | case 228: 1847 | yyDollar = yyS[yypt-1 : yypt+1] 1848 | //line parser/parser.go.y:285 1849 | { 1850 | } 1851 | case 229: 1852 | yyDollar = yyS[yypt-1 : yypt+1] 1853 | //line parser/parser.go.y:286 1854 | { 1855 | } 1856 | case 230: 1857 | yyDollar = yyS[yypt-1 : yypt+1] 1858 | //line parser/parser.go.y:287 1859 | { 1860 | } 1861 | case 231: 1862 | yyDollar = yyS[yypt-1 : yypt+1] 1863 | //line parser/parser.go.y:288 1864 | { 1865 | } 1866 | case 232: 1867 | yyDollar = yyS[yypt-1 : yypt+1] 1868 | //line parser/parser.go.y:289 1869 | { 1870 | } 1871 | case 233: 1872 | yyDollar = yyS[yypt-1 : yypt+1] 1873 | //line parser/parser.go.y:290 1874 | { 1875 | } 1876 | case 234: 1877 | yyDollar = yyS[yypt-1 : yypt+1] 1878 | //line parser/parser.go.y:291 1879 | { 1880 | } 1881 | case 235: 1882 | yyDollar = yyS[yypt-1 : yypt+1] 1883 | //line parser/parser.go.y:292 1884 | { 1885 | } 1886 | case 236: 1887 | yyDollar = yyS[yypt-1 : yypt+1] 1888 | //line parser/parser.go.y:293 1889 | { 1890 | } 1891 | case 237: 1892 | yyDollar = yyS[yypt-1 : yypt+1] 1893 | //line parser/parser.go.y:294 1894 | { 1895 | } 1896 | case 238: 1897 | yyDollar = yyS[yypt-1 : yypt+1] 1898 | //line parser/parser.go.y:295 1899 | { 1900 | } 1901 | case 239: 1902 | yyDollar = yyS[yypt-0 : yypt+1] 1903 | //line parser/parser.go.y:297 1904 | { 1905 | } 1906 | case 240: 1907 | yyDollar = yyS[yypt-1 : yypt+1] 1908 | //line parser/parser.go.y:298 1909 | { 1910 | } 1911 | case 241: 1912 | yyDollar = yyS[yypt-1 : yypt+1] 1913 | //line parser/parser.go.y:299 1914 | { 1915 | } 1916 | case 242: 1917 | yyDollar = yyS[yypt-1 : yypt+1] 1918 | //line parser/parser.go.y:300 1919 | { 1920 | } 1921 | case 243: 1922 | yyDollar = yyS[yypt-0 : yypt+1] 1923 | //line parser/parser.go.y:302 1924 | { 1925 | } 1926 | case 244: 1927 | yyDollar = yyS[yypt-1 : yypt+1] 1928 | //line parser/parser.go.y:303 1929 | { 1930 | } 1931 | case 245: 1932 | yyDollar = yyS[yypt-1 : yypt+1] 1933 | //line parser/parser.go.y:304 1934 | { 1935 | } 1936 | case 247: 1937 | yyDollar = yyS[yypt-1 : yypt+1] 1938 | //line parser/parser.go.y:306 1939 | { 1940 | } 1941 | case 249: 1942 | yyDollar = yyS[yypt-1 : yypt+1] 1943 | //line parser/parser.go.y:308 1944 | { 1945 | } 1946 | case 250: 1947 | yyDollar = yyS[yypt-1 : yypt+1] 1948 | //line parser/parser.go.y:310 1949 | { 1950 | } 1951 | case 251: 1952 | yyDollar = yyS[yypt-2 : yypt+1] 1953 | //line parser/parser.go.y:311 1954 | { 1955 | } 1956 | case 252: 1957 | yyDollar = yyS[yypt-2 : yypt+1] 1958 | //line parser/parser.go.y:312 1959 | { 1960 | } 1961 | case 253: 1962 | yyDollar = yyS[yypt-2 : yypt+1] 1963 | //line parser/parser.go.y:313 1964 | { 1965 | } 1966 | case 254: 1967 | yyDollar = yyS[yypt-1 : yypt+1] 1968 | //line parser/parser.go.y:315 1969 | { 1970 | } 1971 | case 255: 1972 | yyDollar = yyS[yypt-2 : yypt+1] 1973 | //line parser/parser.go.y:316 1974 | { 1975 | } 1976 | case 256: 1977 | yyDollar = yyS[yypt-2 : yypt+1] 1978 | //line parser/parser.go.y:317 1979 | { 1980 | } 1981 | case 258: 1982 | yyDollar = yyS[yypt-1 : yypt+1] 1983 | //line parser/parser.go.y:319 1984 | { 1985 | } 1986 | case 259: 1987 | yyDollar = yyS[yypt-1 : yypt+1] 1988 | //line parser/parser.go.y:321 1989 | { 1990 | } 1991 | case 262: 1992 | yyDollar = yyS[yypt-0 : yypt+1] 1993 | //line parser/parser.go.y:325 1994 | { 1995 | } 1996 | case 270: 1997 | yyDollar = yyS[yypt-0 : yypt+1] 1998 | //line parser/parser.go.y:334 1999 | { 2000 | } 2001 | case 287: 2002 | yyDollar = yyS[yypt-0 : yypt+1] 2003 | //line parser/parser.go.y:352 2004 | { 2005 | } 2006 | case 292: 2007 | yyDollar = yyS[yypt-0 : yypt+1] 2008 | //line parser/parser.go.y:358 2009 | { 2010 | } 2011 | case 298: 2012 | yyDollar = yyS[yypt-0 : yypt+1] 2013 | //line parser/parser.go.y:365 2014 | { 2015 | } 2016 | case 301: 2017 | yyDollar = yyS[yypt-0 : yypt+1] 2018 | //line parser/parser.go.y:369 2019 | { 2020 | } 2021 | case 304: 2022 | yyDollar = yyS[yypt-0 : yypt+1] 2023 | //line parser/parser.go.y:373 2024 | { 2025 | } 2026 | case 307: 2027 | yyDollar = yyS[yypt-0 : yypt+1] 2028 | //line parser/parser.go.y:377 2029 | { 2030 | } 2031 | } 2032 | goto yystack /* stack new state and value */ 2033 | } 2034 | -------------------------------------------------------------------------------- /parser/parser.go.y: -------------------------------------------------------------------------------- 1 | %{ 2 | package parser 3 | %} 4 | 5 | %union { 6 | integer int 7 | symbol string 8 | }; 9 | 10 | %token NUMBER 11 | %token ID STRING EMAIL IPV4 IPV6 IP_CIDR IPADDR_RANGE HEX32 PATHSTR 12 | %token LB RB 13 | %token GLOBALDEFS 14 | %token NOTIFICATION_EMAIL NOTIFICATION_EMAIL_FROM SMTP_SERVER SMTP_CONNECT_TIMEOUT ROUTER_ID LVS_ID VRRP_MCAST_GROUP4 VRRP_MCAST_GROUP6 VRRP_GARP_MASTER_DELAY VRRP_GARP_MASTER_REPEAT VRRP_GARP_MASTER_REFRESH VRRP_GARP_MASTER_REFRESH_REPEAT VRRP_VERSION ENABLE_SCRIPT_SECURITY 15 | %token STATIC_IPADDRESS 16 | %token STATIC_ROUTES 17 | %token STATIC_RULES 18 | %token VRRP_SYNC_GROUP GROUP 19 | %token VRRP_INSTANCE 20 | %token USE_VMAC VERSION VMAC_XMIT_BASE NATIVE_IPV6 INTERFACE MCAST_SRC_IP UNICAST_SRC_IP UNICAST_PEER LVS_SYNC_DAEMON_INTERFACE VIRTUAL_ROUTER_ID NOPREEMPT PREEMPT_DELAY PRIORITY ADVERT_INT VIRTUAL_IPADDRESS VIRTUAL_IPADDRESS_EXCLUDED VIRTUAL_ROUTES STATE MASTER BACKUP GARP_MASTER_DELAY GARP_MASTER_REPEAT GARP_MASTER_REFRESH GARP_MASTER_REFRESH_REPEAT SMTP_ALERT AUTHENTICATION AUTH_TYPE AUTH_PASS PASS AH LABEL DEV SCOPE SITE LINK HOST NOWHERE GLOBAL BRD SRC FROM TO VIA GW OR TABLE METRIC TRACK_INTERFACE TRACK_SCRIPT DONT_TRACK_PRIMARY NOTIFY_MASTER NOTIFY_BACKUP NOTIFY_FAULT NOTIFY_STOP NOTIFY BLACKHOLE 21 | %token VRRP_SCRIPT 22 | %token SCRIPT INTERVAL TIMEOUT WEIGHT FALL RISE 23 | %token VIRTUAL_SERVER_GROUP 24 | %token VIRTUAL_SERVER 25 | %token DELAY_LOOP LB_ALGO LB_KIND LVS_SCHED LVS_METHOD RR WRR LC WLC FO OVF LBLC LBLCR SH DH SED NQ NAT DR TUN PERSISTENCE_TIMEOUT PROTOCOL TCP UDP SORRY_SERVER REAL_SERVER FWMARK INHIBIT_ON_FAILURE TCP_CHECK HTTP_GET SSL_GET SMTP_CHECK DNS_CHECK MISC_CHECK URL PATH DIGEST STATUS_CODE CONNECT_TIMEOUT CONNECT_PORT CONNECT_IP BINDTO BIND_PORT RETRY HELO_NAME TYPE NAME MISC_PATH MISC_TIMEOUT WARMUP MISC_DYNAMIC NB_GET_RETRY DELAY_BEFORE_RETRY VIRTUALHOST ALPHA OMEGA QUORUM HYSTERESIS QUORUM_UP QUORUM_DOWN, 26 | 27 | 28 | %% 29 | configuration: main_statements configuration | main_statements { } 30 | 31 | main_statements: { } 32 | | global { } 33 | | static_ipaddress_block { } 34 | | static_routes_block { } 35 | | static_rules_block { } 36 | | vrrp_sync_group_block { } 37 | | vrrp_instance_block { } 38 | | vrrp_script_block { } 39 | | virtual_server_block { } 40 | | virtual_server_group_block { } 41 | 42 | global: GLOBALDEFS LB global_statements RB 43 | 44 | global_statements: global_statement global_statements | global_statement 45 | 46 | global_statement: 47 | | NOTIFICATION_EMAIL LB mail_statements RB { } 48 | | NOTIFICATION_EMAIL STRING { } 49 | | NOTIFICATION_EMAIL_FROM EMAIL { } 50 | | VRRP_GARP_MASTER_DELAY NUMBER { } 51 | | VRRP_GARP_MASTER_REPEAT NUMBER { } 52 | | VRRP_GARP_MASTER_REFRESH NUMBER { } 53 | | VRRP_GARP_MASTER_REFRESH_REPEAT NUMBER { } 54 | | SMTP_SERVER ip46 { } 55 | | SMTP_SERVER STRING { } 56 | | SMTP_CONNECT_TIMEOUT NUMBER { } 57 | | ROUTER_ID STRING { } 58 | | LVS_ID STRING { } 59 | | VRRP_MCAST_GROUP4 IPV4 { } 60 | | VRRP_MCAST_GROUP6 IPV6 { } 61 | | VRRP_VERSION NUMBER { } 62 | | ENABLE_SCRIPT_SECURITY 63 | 64 | static_ipaddress_block: STATIC_IPADDRESS LB address_options RB 65 | 66 | static_routes_block: STATIC_ROUTES LB route_options RB 67 | 68 | static_rules_block: STATIC_RULES LB rule_options RB 69 | 70 | rule_options: rule_option rule_options | rule_option 71 | 72 | vrrp_sync_group_block: VRRP_SYNC_GROUP STRING LB vrrp_sync_group_statements RB 73 | 74 | vrrp_sync_group_statements: vrrp_sync_group_statement vrrp_sync_group_statements | vrrp_sync_group_statement 75 | 76 | vrrp_sync_group_statement: { } 77 | | STRING { } 78 | | GROUP LB vrrp_group_ids RB { } 79 | | NOTIFY_MASTER STRING { } 80 | | NOTIFY_BACKUP STRING { } 81 | | NOTIFY_FAULT STRING { } 82 | | NOTIFY STRING { } 83 | 84 | vrrp_group_ids: vrrp_group_id vrrp_group_ids | vrrp_group_id { } 85 | 86 | vrrp_group_id: STRING 87 | 88 | vrrp_instance_block: VRRP_INSTANCE STRING LB vrrp_instance_statements RB 89 | 90 | vrrp_instance_statements: vrrp_instance_statement vrrp_instance_statements | vrrp_instance_statement 91 | 92 | vrrp_instance_statement: { } 93 | | USE_VMAC { } 94 | | VERSION NUMBER { } 95 | | VMAC_XMIT_BASE { } 96 | | NATIVE_IPV6 { } 97 | | INTERFACE STRING { } 98 | | MCAST_SRC_IP ip46 { } 99 | | UNICAST_SRC_IP ip46 { } 100 | | UNICAST_PEER LB ipaddr_list RB { } 101 | | LVS_SYNC_DAEMON_INTERFACE STRING { } 102 | | VIRTUAL_ROUTER_ID STRING { } 103 | | VIRTUAL_ROUTER_ID NUMBER { } 104 | | NOPREEMPT 105 | | PREEMPT_DELAY NUMBER { } 106 | | PRIORITY NUMBER { } 107 | | ADVERT_INT NUMBER { } 108 | | VIRTUAL_IPADDRESS LB vips RB 109 | | VIRTUAL_IPADDRESS_EXCLUDED LB vips_ex RB 110 | | VIRTUAL_ROUTES LB virtual_routes_statements RB 111 | | STATE MASTER { } 112 | | STATE BACKUP { } 113 | | GARP_MASTER_DELAY NUMBER { } 114 | | GARP_MASTER_REPEAT NUMBER { } 115 | | GARP_MASTER_REFRESH NUMBER { } 116 | | GARP_MASTER_REFRESH_REPEAT NUMBER { } 117 | | SMTP_ALERT { } 118 | | AUTHENTICATION LB authentication_statements RB { } 119 | | TRACK_INTERFACE STRING { } 120 | | TRACK_INTERFACE LB interfaces RB { } 121 | | TRACK_SCRIPT LB track_script_statements RB { } 122 | | DONT_TRACK_PRIMARY { } 123 | | NOTIFY_MASTER STRING { } 124 | | NOTIFY_BACKUP STRING { } 125 | | NOTIFY_FAULT STRING { } 126 | | NOTIFY_STOP STRING { } 127 | | NOTIFY STRING { } 128 | 129 | authentication_statements: authentication_statement authentication_statements | authentication_statement 130 | 131 | authentication_statement: { } 132 | | AUTH_TYPE PASS { } 133 | | AUTH_TYPE AH { } 134 | | AUTH_PASS any_literal { } 135 | 136 | interfaces: interface interfaces | interface 137 | 138 | interface: STRING 139 | | WEIGHT NUMBER { } 140 | 141 | ipaddr_list: ip46 ipaddr_list | ip46 142 | 143 | track_script_statements: track_script_statement track_script_statements | track_script_statement 144 | 145 | track_script_statement: { } 146 | | STRING { } 147 | | STRING WEIGHT NUMBER { } 148 | 149 | vrrp_script_block: VRRP_SCRIPT STRING LB vrrp_script_statements RB 150 | 151 | vrrp_script_statements: vrrp_script_statement vrrp_script_statements | vrrp_script_statement 152 | 153 | vrrp_script_statement: { } 154 | | SCRIPT STRING { } 155 | | INTERVAL NUMBER { } 156 | | TIMEOUT NUMBER { } 157 | | WEIGHT NUMBER { } 158 | | FALL NUMBER { } 159 | | RISE NUMBER { } 160 | 161 | virtual_routes_statements: virtual_server_statement virtual_server_statements | virtual_server_statement 162 | 163 | virtual_server_statement: route_option route_options | route_option 164 | 165 | virtual_server_group_block: VIRTUAL_SERVER_GROUP STRING LB virtual_server_group_statements RB 166 | 167 | virtual_server_group_statements: virtual_server_group_statement virtual_server_group_statements | virtual_server_group_statement 168 | 169 | virtual_server_group_statement: { } 170 | | ip46 NUMBER { } 171 | | IPADDR_RANGE NUMBER { } 172 | | FWMARK NUMBER { } 173 | 174 | virtual_server_block: VIRTUAL_SERVER virtual_server_arg LB virtual_server_statements RB 175 | 176 | virtual_server_statements: virtual_server_statement virtual_server_statements | virtual_server_statement 177 | 178 | virtual_server_arg: 179 | | ipport 180 | | FWMARK NUMBER { } 181 | | GROUP STRING { } 182 | 183 | virtual_server_statement: { } 184 | | DELAY_LOOP NUMBER { } 185 | | LB_ALGO lb_algo { } 186 | | LB_KIND lb_kind { } 187 | | LVS_SCHED lb_algo { } 188 | | LVS_METHOD lb_kind { } 189 | | PERSISTENCE_TIMEOUT NUMBER { } 190 | | PROTOCOL protocol { } 191 | | SORRY_SERVER ip46 NUMBER { } 192 | | REAL_SERVER ip46 ipport LB real_server_statements RB 193 | | REAL_SERVER ip46 NUMBER LB real_server_statements RB 194 | | VIRTUALHOST STRING { } 195 | | ALPHA 196 | | OMEGA 197 | | QUORUM NUMBER { } 198 | | HYSTERESIS NUMBER { } 199 | | QUORUM_UP STRING { } 200 | | QUORUM_DOWN STRING { } 201 | 202 | real_server_statements: real_server_statement real_server_statements | real_server_statement { } 203 | 204 | real_server_statement: { } 205 | | WEIGHT NUMBER { } 206 | | INHIBIT_ON_FAILURE { } 207 | | TCP_CHECK LB tcp_check_statements RB { } 208 | | HTTP_GET LB http_get_statements RB { } 209 | | SSL_GET LB http_get_statements RB { } 210 | | SMTP_CHECK LB smtp_check_statements RB { } 211 | | DNS_CHECK LB dns_check_statements RB { } 212 | | MISC_CHECK LB misc_check_statements RB { } 213 | 214 | tcp_check_statements: tcp_check_statement tcp_check_statements | tcp_check_statement { } 215 | 216 | tcp_check_statement: { } 217 | | CONNECT_PORT NUMBER { } 218 | | CONNECT_TIMEOUT NUMBER { } 219 | | RETRY NUMBER { } 220 | | WARMUP NUMBER { } 221 | | DELAY_BEFORE_RETRY NUMBER { } 222 | 223 | http_get_statements: http_get_statement http_get_statements | http_get_statement { } 224 | 225 | http_get_statement: { } 226 | | URL LB url_statements RB { } 227 | | CONNECT_TIMEOUT NUMBER { } 228 | | CONNECT_PORT NUMBER { } 229 | | NB_GET_RETRY NUMBER { } 230 | | DELAY_BEFORE_RETRY NUMBER { } 231 | | WARMUP NUMBER { } 232 | 233 | url_statements: url_statement url_statements | url_statement { } 234 | 235 | url_statement: { } 236 | | PATH STRING { } 237 | | PATH PATHSTR { } 238 | | DIGEST HEX32 { } 239 | | STATUS_CODE NUMBER { } 240 | 241 | smtp_check_statements: smtp_check_statement smtp_check_statements | smtp_check_statement { } 242 | 243 | smtp_check_statement: { } 244 | | host_statement { } 245 | | HOST LB host_statements RB 246 | | WARMUP NUMBER 247 | | RETRY NUMBER 248 | | DELAY_BEFORE_RETRY NUMBER 249 | | HELO_NAME STRING 250 | 251 | host_statements: host_statement host_statements | host_statement { } 252 | 253 | host_statement: { } 254 | | CONNECT_IP ip46 { } 255 | | CONNECT_PORT NUMBER { } 256 | | BINDTO ip46 { } 257 | | BIND_PORT NUMBER { } 258 | | CONNECT_TIMEOUT NUMBER { } 259 | | FWMARK NUMBER { } 260 | 261 | dns_check_statements: dns_check_statement dns_check_statements | dns_check_statement { } 262 | 263 | dns_check_statement: { } 264 | | CONNECT_IP ip46 { } 265 | | CONNECT_PORT NUMBER { } 266 | | BINDTO ip46 { } 267 | | BIND_PORT NUMBER { } 268 | | CONNECT_TIMEOUT NUMBER { } 269 | | FWMARK NUMBER { } 270 | | RETRY NUMBER { } 271 | | TYPE STRING { } 272 | | NAME STRING { } 273 | 274 | misc_check_statements: misc_check_statement misc_check_statements | misc_check_statement { } 275 | 276 | misc_check_statement: { } 277 | | MISC_PATH STRING { } 278 | | MISC_PATH PATHSTR { } 279 | | MISC_TIMEOUT NUMBER { } 280 | | WARMUP NUMBER { } 281 | | MISC_DYNAMIC { } 282 | 283 | lb_algo: { } 284 | | RR { } 285 | | WRR { } 286 | | LC { } 287 | | WLC { } 288 | | FO { } 289 | | OVF { } 290 | | LBLC { } 291 | | LBLCR { } 292 | | SH { } 293 | | DH { } 294 | | SED { } 295 | | NQ { } 296 | 297 | lb_kind: { } 298 | | NAT { } 299 | | DR { } 300 | | TUN { } 301 | 302 | protocol: { } 303 | | TCP { } 304 | | UDP { } 305 | 306 | vips: vip vips | vip { } 307 | 308 | vips_ex: vip_ex vips_ex | vip_ex { } 309 | 310 | vip: ipaddr_literal { } 311 | | LABEL STRING { } 312 | | DEV STRING { } 313 | | BRD ip46 { } 314 | 315 | vip_ex: ipaddr_literal { } 316 | | DEV STRING { } 317 | | BRD ip46 { } 318 | 319 | mail_statements: mail_statement mail_statements | mail_statement { } 320 | 321 | mail_statement: any_literal { } 322 | 323 | address_options: address_option address_options | address_option 324 | 325 | address_option: { } 326 | | ip46 327 | | IP_CIDR 328 | | BRD ip46 329 | | DEV STRING 330 | | SCOPE scope_val 331 | 332 | route_options: route_option route_options | route_option 333 | 334 | route_option: { } 335 | | SRC ip46 336 | | TO ip46 337 | | TO IP_CIDR 338 | | ip46 339 | | IP_CIDR 340 | | VIA ip46 341 | | GW ip46 342 | | OR ip46 343 | | DEV STRING 344 | | LABEL STRING 345 | | TABLE NUMBER 346 | | TABLE STRING 347 | | METRIC NUMBER 348 | | SCOPE scope_val 349 | | BLACKHOLE ip46 350 | | BLACKHOLE IP_CIDR 351 | 352 | rule_option: { } 353 | | FROM ip46 TABLE NUMBER 354 | | TO ip46 TABLE NUMBER 355 | | FROM IP_CIDR TABLE NUMBER 356 | | TO IP_CIDR TABLE NUMBER 357 | 358 | scope_val: { } 359 | | SITE 360 | | LINK 361 | | HOST 362 | | NOWHERE 363 | | GLOBAL 364 | 365 | ipaddr_literal: { } 366 | | ip46 367 | | IP_CIDR 368 | 369 | ip46: { } 370 | | IPV4 371 | | IPV6 372 | 373 | ipport: { } 374 | | ip46 375 | | ip46 NUMBER 376 | 377 | any_literal: { } 378 | | NUMBER 379 | | STRING 380 | | EMAIL 381 | | HEX32 382 | | ip46 383 | | IP_CIDR 384 | 385 | %% 386 | -------------------------------------------------------------------------------- /parser/testing.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | func generateTestTokens(toks []int) []*Token { 4 | tokens := make([]*Token, 0, len(toks)) 5 | for _, tok := range toks { 6 | tokens = append(tokens, &Token{ 7 | value: tok, 8 | filename: "dummy.conf", // Whatever is fine 9 | line: 10, // Whatever is fine 10 | column: 2, // Whatever is fine 11 | }) 12 | } 13 | return tokens 14 | } 15 | -------------------------------------------------------------------------------- /testdata/globaldef_1_3.conf: -------------------------------------------------------------------------------- 1 | global_defs { 2 | notification_email { 3 | notification@example.com 4 | } 5 | notification_email_from keepalived@example.com 6 | smtp_server 172.0.0.1 7 | smtp_connect_timeout 30 8 | enable_script_security 9 | } 10 | -------------------------------------------------------------------------------- /testdata/unicast_mcast.conf: -------------------------------------------------------------------------------- 1 | vrrp_instance L1 { 2 | mcast_src_ip 10.10.10.10 3 | unicast_src_ip 10.10.10.100 4 | unicast_peer { 5 | 10.10.10.15 6 | 10.10.10.16 7 | 10.10.10.17 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /testdata/vrrp_garp_master.conf: -------------------------------------------------------------------------------- 1 | global_defs { 2 | notification_email_from y_uuki@example.com 3 | router_id EXAMPLE1 4 | vrrp_garp_master_delay 5 5 | vrrp_garp_master_repeat 5 6 | vrrp_garp_master_refresh 0 7 | vrrp_garp_master_refresh_repeat 1 8 | } 9 | -------------------------------------------------------------------------------- /testdata/vrrp_mcast_group.conf: -------------------------------------------------------------------------------- 1 | global_defs { 2 | notification_email_from y_uuki@example.com 3 | router_id EXAMPLE1 4 | vrrp_mcast_group4 224.0.0.18 5 | vrrp_mcast_group6 ff02::12 6 | vrrp_version 2 7 | } 8 | -------------------------------------------------------------------------------- /testdata/vrrp_script.conf: -------------------------------------------------------------------------------- 1 | vrrp_script check_redis { 2 | script /usr/bin/check_redis 3 | interval 5 4 | timeout 10 5 | weight 100 6 | fall 5 7 | rise 2 8 | } 9 | -------------------------------------------------------------------------------- /version.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // name is application name. 4 | const name = "gokc" 5 | 6 | // version is application version. 7 | const version = "0.4.3" 8 | 9 | // commit describes latest git commit hash. 10 | // This is automatically extracted by git describe --always. 11 | var commit string 12 | 13 | var date string 14 | --------------------------------------------------------------------------------