diff --git a/README.md b/README.md index 604adcf..9a39ef8 100644 --- a/README.md +++ b/README.md @@ -26,18 +26,32 @@ resource: description: (( "This document describes a " name " located at " url )) ``` -spiff is a command line tool and declarative YAML templating system, specially designed for generating deployment -manifests (for example BOSH or [kubernetes](https://github.com/kubernetes) manifests). +Instead of using only external value sources *spiff* provides a merging mechanism +to merge a template with any number of merging stubs to produce a final document. + +It is a command line tool and declarative YAML templating system, specially designed for generating deployment +manifests (for example BOSH, [Kubernetes](https://github.com/kubernetes) or +[Landscaper](https://github.com/gardener/landscaper) manifests). + +Besides the CLI there is a golang library enabling the usage of the spiff +template processing in any GO program (for example [Landscaper](https://github.com/gardener/landscaper)). + +The templating engine offers enabling access to the filesystem based on a +configurable [virtual filesystem](https://github.com/mandelsoft/vfs) +or the process system to execute commands and incorporate the output into the +template processing. Contents: - [Installation](#installation) - [Usage](#usage) +- [Feature Flags](#feature-flags) - [Libraries](#libraries) - [dynaml Templating Language](#dynaml-templating-language) - [(( foo ))](#-foo-) - [(( foo.bar.[1].baz ))](#-foobar1baz-) - [(( foo.[bar].baz ))](#-foobarbaz-) - [(( list.[1..3] ))](#-list13-) + - [(( tag::foo ))](#-tagfoo-) - [(( 1.2e4 ))](#-12e4-) - [(( "foo" ))](#-foo-) - [(( [ 1, 2, 3 ] ))](#--1-2-3--) @@ -132,6 +146,17 @@ Contents: - [(( mkdir("dir", 0755) ))](#-mkdirdir-0755-) - [(( list_files(".") ))](#-list_files-) - [(( archive(files, "tar") ))](#-archivefiles-tar-) + - [Semantic Versioning Functions](#semantic-versioning-functions) + - [(( semver("v1.2-beta.1") ))](#-semverv12-beta1-) + - [(( semverrelease("v1.2.3-beta.1") ))](#-semverreleasev123-beta1-) + - [(( semvermajor("1.2.3-beta.1") ))](#-semvermajor123-beta1-) + - [(( semverminor("1.2.3-beta.1") ))](#-semverminor123-beta1-) + - [(( semverpatch("1.2.3-beta.1") ))](#-semverpatch123-beta1-) + - [(( semverprerelease("1.2.3-beta.1") ))](#-semverprerelease123-beta1-) + - [(( semvermetadata("1.2.3+demo") ))](#-semvermetadata123demo-) + - [(( semvercmp("1.2.3", "1.2.3-beta.1") ))](#-semvercmp123-123-beta1-) + - [(( semvermatch("1.2.3", "~1.2") ))](#-semvermatch123-12-) + - [(( semversort("1.2.3", "1.2.1") ))](#-semversort123-121-) - [X509 Functions](#x509-functions) - [(( x509genkey(spec) ))](#-x509genkeyspec-) - [(( x509publickey(key) ))](#-x509publickeykey-) @@ -166,14 +191,16 @@ Contents: - [Markers](#markers) - [(( &temporary ))](#-temporary-) - [(( &local ))](#-local-) + - [(( &dynamic ))](#-dynamic-) - [(( &inject ))](#-inject-) - [(( &default ))](#-default-) - [(( &state ))](#-state-) - [(( &tag:name ))](#-tagname-) - [Tags](#tags) - [(( &tag:name(value) ))](#-tagnamevalue-) - - [(( name::path ))](#-namepath-) - - [(( name::. ))](#-name-) + - [(( tag::foo ))](#-tagfoo-) + - [(( tag::. ))](#-tag-) + - [(( foo.bar::alice ))](#-foobaralice-) - [Path Resolution for Tags](#path-resolution-for-tags) - [Tags in Multi-Document Streams](#tags-in-multi-document-streams) - [Templates](#templates) @@ -188,6 +215,16 @@ Contents: - [Access to evaluation context](#access-to-evaluation-context) - [Operation Priorities](#operation-priorities) - [String Interpolation](#string-interpolation) + - [YAML-based Control Structures](#yaml-based-control-structures) + - [in Maps](#control-structures-in-maps) + - [in Lists](#control-structures-in-lists) + - [`<` will enable this given features. New + features that are incompatible with the old behaviour must be explicitly + enabled. Typically those feature do not break the common behavior but introduce + a dedicated interpretation for yaml values that were used as regular values + before. + The folder [libraries](libraries/README.md) offers some useful utility libraries. They can also be used as an example for the power of this templating engine. @@ -340,6 +383,33 @@ stdin. If the option `-d` is given, the data is decrypted, otherwise the data is read as yaml document and the encrypted result is printed. +# Feature Flags + +New features that are incompatible with the old behaviour must be explicitly +enabled. Typically those features do not break the common behavior but introduce +a dedicated interpretation for yaml values that were used as regular values +before and can therefore break existing use cases. + +The following feature flags are currently supported: + +| Feature | Since | State | Meaning | +|---------|-------|-------|---------| +| `interpolation` | 1.7.0-beta-1 | alpha | [dynaml as part of yaml strings](#string-interpolation) | +| `control` | 1.7.0-beta-4 | alpha | [yaml based control structures](#yaml-based-control-structures) | + +Active feature flags can be queried using the *dynaml* function +`features()` as list of strings. If this function is called with a string +argument, it returns whether the given feature is currenty enabled. + +Features can be enabled by command line using the `--features` option, +by the go library using the `WithFeatures` function or generally +by setting the environment variable `SPIFF_FEATURES` to a feature list. +This setting is alwas used as default. By using the `Plain()` spiff +settings from the go library all environment variables are ignored. + +A feature can be specified by name or by name prepended with the prefix `no` +to disable it. + # Libraries The [libraries](libraries/README.md) folder contains some useful _spiff_ template @@ -1226,7 +1296,7 @@ The result is the string `3 times 2 yields 6`. ## `(( "10.10.10.10" - 11 ))` -Besides arithmetic on integers it is also possible to use addition and subtraction on ip addresses. +Besides arithmetic on integers it is also possible to use addition and subtraction on ip addresses and cidrs. e.g.: @@ -1242,7 +1312,7 @@ ip: 10.10.10.10 range: 10.10.10.10-10.11.11.1 ``` -Subtraction also works on two IP addresses to calculate the number of +Subtraction also works on two IP addresses or cidrs to calculate the number of IP addresses between two IP addresses. e.g.: @@ -2061,6 +2131,7 @@ template: types: - int: (( type(1) )) + - float: (( type(1.0) )) - bool: (( type(true) )) - string: (( type("foobar") )) - list: (( type([]) )) @@ -2076,6 +2147,7 @@ evaluates types to ```yaml types: - int: int +- float: float - bool: bool - string: string - list: list @@ -2836,6 +2908,7 @@ The following validators are available: | `privatekey` | none | private key in pem format | | `certificate` | none | certificate in pem format | | `ca`| none | certificate for CA | +| `semver` | optional list of constraints | validate semver version against constraints | | `type`| list of accepted type keys | at least one [type key](#-typefoobar-) must match | | `valueset` | list argument with values | possible values | | `value` or `=` | value | check dedicated value | @@ -3282,10 +3355,299 @@ yaml: bob: 27 ``` +### Semantic Versioning Functions + +*Spiff* supports handling of semantic version names. It supports all functionality +from the [Masterminds Semver Package](https://github.com/Masterminds/semver/blob/v3.1.1/README.md) +accepting versions with or without a leading `v`. + +#### `(( semver("v1.2-beta.1") ))` + +Check whether a given string is a semantic version and return +its normalized form (without leading `v` and complete release part with major, +minor and and patch version number). + +e.g.: + +```yaml +normalized: (( semver("v1.2-beta.1") )) +``` + +resolves to + +```yaml +normalized: 1.2.0-beta.1 +``` + +#### `(( semverrelease("v1.2.3-beta.1") ))` + +Return the release part of a semantic version omitting metadata and prerelease +information. + +e.g.: + +```yaml +release: (( semverrelease("v1.2.3-beta.1") )) +``` + +resolves to + +```yaml +release: v1.2.3 +``` + +If an additional string argument is given this function replaces +the release by the release of the given semantic version preserving +metadata and prerelease information. + +e.g.: + +```yaml +new: (( semverrelease("1.2.3-beta.1", "1.2.1) )) +``` + +resolves to + +```yaml +new: 1.2.1-beta.1 +``` + +#### `(( semvermajor("1.2.3-beta.1") ))` + +Determine the major version number of the given semantic version. +The result is an integer. + +e.g.: + +```yaml +major: (( semvermajor("1.2.3-beta.1") )) +``` + +resolves to + +```yaml +major: 1 +``` + +The function `semverincmajor` can be used to increment the +major version number and reset the minor version, patch version +and release suffixes. + +e.g.: + +```yaml +new: (( semverincmajor("1.2.3-beta.1") )) +``` + +resolves to + +```yaml +new: 2.0.0 +``` + +#### `(( semverminor("1.2.3-beta.1") ))` + +Determine the minor version number of the given semantic version. +The result is an integer. + +e.g.: + +```yaml +minor: (( semverminor("1.2.3-beta.1") )) +``` + +resolves to + +```yaml +minor: 2 +``` + +The function `semverincminor` can be used to increment the +minor version number and reset the patch version +and release suffixes. + +e.g.: + +```yaml +new: (( semverincmajor("v1.2.3-beta.1") )) +``` + +resolves to + +```yaml +new: v1.3.0 +``` + +#### `(( semverpatch("1.2.3-beta.1") ))` + +Determine the patch version number of the given semantic version. +The result is an integer. + +e.g.: + +```yaml +patch: (( semverpatch("1.2.3-beta.1") )) +``` + +resolves to + +```yaml +patch: 3 +``` + +The function `semverincpatch` can be used to increment the +patch version number or reset the release suffixes. +If there are rlease suffixes, they are removed and the release +info is kept unchanged, otherwise the patch version number +is increased. + +e.g.: + +```yaml +final: (( semverincpatch("1.2.3-beta.1") )) +new: (( semverincpatch(final) )) +``` + +resolves to + +```yaml +final: 1.2.3 +new: 1.2.4 +``` + +#### `(( semverprerelease("1.2.3-beta.1") ))` + +Determine the prerelease of the given semantic version. +The result is a string. + +e.g.: + +```yaml +prerelease: (( semverprerelease("1.2.3-beta.1") )) +``` + +resolves to + +```yaml +prerelease: beta.1 +``` + +If an additional string argument is given this function sets, replaces or clears +(if set to empty string) the prerelease + +e.g.: + +```yaml +new: (( semverprerelease("1.2.3-beta.1", "beta.2) )) +``` + +resolves to + +```yaml +new: 1.2.3-beta.2 +``` + +#### `(( semvermetadata("1.2.3+demo") ))` + +Determine the metadata of the given semantic version. +The result is a string. + +e.g.: + +```yaml +metadata: (( semvermetadata("1.2.3+demo") )) +``` + +resolves to + +```yaml +metadata: demo +``` + +If an additional string argument is given this function sets, replaces or clears +(if set to empty string) the metadata. + +e.g.: + +```yaml +new: (( semvermetadata("1.2.3-test", "demo) )) +``` + +resolves to + +```yaml +new: 1.2.3+demo +``` + +#### `(( semvercmp("1.2.3", 1.2.3-beta.1") ))` + +Compare two semantic versions. A prerelease is always *smaller* than +the final release. The result is an integer with the following values: + +| result | meaning | +|--------|---------| +| -1 | first version is before the second version | +| 0 | both versions are equal | +| 1 | first versuon is after the second one | + +e.g.: + +```yaml +compare: (( semvercmp("1.2.3", "1.2.3-beta.1") )) +``` + +resolves to + +```yaml +compare: 1 +``` + +#### `(( semvermatch("1.2.3", "~1.2") ))` + +Match the given semantic version against a list of contraints. +The result is a boolean. It is possible to specify any number of version +constraints. If no constraint is given, the function just checks whether +the given string is a semantic version. + +e.g.: + +```yaml +match: (( semvermatch("1.2.3", "~1.2") )) +``` + +resolves to + +```yaml +match: true +``` + +The complete list of possible constraints specification can be found +[here](https://github.com/Masterminds/semver/blob/v3.1.1/README.md#checking-version-constraints). + +#### `(( semversort("1.2.3", "1.2.1") ))` + +Sort a list of versions in ascending order. A leading `v` is preserved. + +e.g.: + +```yaml +sorted: (( semversort("1.2.3", "1.2.1") )) +``` + +resolves to + +```yaml +sorted: + - 1.2.1 + - 1.2.3 +``` + +The list of versions to be sorted may also be specified with a single list +argument. ### X509 Functions -spiff supports some useful functions to work with _X509_ certificates and keys. +*Spiff* supports some useful functions to work with _X509_ certificates and keys. Please refer also to the [Useful to Know](#useful-to-know) section to find some tips for providing state. @@ -4530,7 +4892,7 @@ Please note, that the list expansion might span multiple arguments (including th Nodes of the yaml document can be marked to enable dedicated behaviours for this node. Such markers are part of the _dynaml_ syntax and may be prepended to any dynaml expression. They are denoted by the `&` character directly followed -by a marker name. If the expression is combination of markers and regular +by a marker name. If the expression is a combination of markers and regular expressions, the expression follows the marker list enclosed in brackets (for example `(( &temporary( a + b ) ))`). @@ -4588,6 +4950,40 @@ removed from a stub directly after resolving dynaml expressions. Such nodes are therefore not available for merging and they are not used for further merging of stubs and finally the template. +### `(( &dynamic ))` + +This marker can be used to mark a template expression (direct or referenced) +to enforce the re-evaluation of the template in the usage context whenever the +node is used to override or inject a node value along the processing chain. +It can also be used together with +[`&inject`](#-inject-) or [`&default`](#-default-). + +e.g.: + +**template.yaml** +```yaml +data: 1 +``` + +merged with + +**stub.yaml** +```yaml +id: (( &dynamic &inject &template(__ctx.FILE) )) +``` + +will resolve to + +```yaml +id: template.yaml +data: 1 +``` + +The original template is kept along the merge chain and is evaluated +separately in the context of the very stub or template it is used. + +Using this marker for nodes not evaluationg to a template value is +not possible. ### `(( &inject ))` @@ -4773,7 +5169,9 @@ value as a whole or sub structure. ### `(( &tag:name(value) ))` This syntax is used to tag a node whose value is defined by a dynaml expression. -It can also be used to denote tagged simple value nodes. +It can also be used to denote tagged simple value nodes. (As usual the value +part is optional for adding markers to structured values +(see [Markers](#markers)).) e.g.: @@ -4785,12 +5183,15 @@ data: ``` If the name is prefixed with a star (`*`), the tag is defined globally. -Gobal tags surive stub processing and their value is visible in sub sequent +Gobal tags surive stub processing and their value is visible in subsequent stub (and template) processings. A tag name may consist of multiple components separated by a colon (`:`). -### `(( name::path ))` +Tags can also be defined dynamically by the dynaml +function [tagdef](#-tagdeftag-valiue-). + +### `(( tag::foo ))` Reference a sub path of the value of a tagged node. @@ -4807,9 +5208,9 @@ tagref: (( persons::alice )) resolves `tagref` to `25` -### `(( name::. ))` +### `(( tag::. ))` -Reference the value of tagged node. +Reference the whole (structured) value of tagged node. e.g.: @@ -4823,11 +5224,18 @@ tagref: (( alice::. )) resolves `tagref` to `25` +### `(( foo.bar::alice ))` + +Tag names may be structured. A tag name consists of a non-empty list of +tag components separated by a dot or colon (`:`). A tag component may +contain ASCII letters or numbers, starting wit a letter. +Multi-component tags are subject to [Tag Resolution](#path-resolution-for-tags). + ### Path Resolution for Tags A tag reference always contains a tag name and a path separated by a double colon (`::`). -The standard usecase is to describe a dedicated sub node for a tagged +The standard use-case is to describe a dedicated sub node for a tagged node value. for example, if the tag `X` describes the value @@ -4838,14 +5246,19 @@ data: bob: 24 ``` -the tagged reference `tag::data.alice` describes the value `25`. +the tagged reference `X::data.alice` describes the value `25`. -For tagged reference with a path other the `.` (the whole tag value), +For tagged references with a path other than `.` (the whole tag value), structured tags feature a more sophisticated resolution mechanism. A structured tag consist of multiple tag components separated by a colon (`:`), for -example `lib:mylib`. +example `lib:mylib`. Therefore tags span a tree of namespaces or scopes +used to resolve path references. A tag-less reference just uses +the actual document or binding to resolve a path extression. + Evaluation of a path reference for a tag tries to resolve the path in the -first unique nested tag, if it cannot be resolved directly by the given tag. +first tag tree level where the path is available (breadth-first search). +If this level contains multiple tags that could resolve the given path, the +resolution fails because it cannot be unambigiously resolved. For example: @@ -4914,7 +5327,7 @@ Local tags are only avaialble on the processing level they are declared. Additionally to the tags explicitly set by tag markers, there are implicit document tags given by the document index during the processing of a (multi-document) template. The implicit document tags are qualified with the -prefix `doc:`. This prefix should not be used to own tags in the documents +prefix `doc.`. This prefix should not be used to own tags in the documents e.g.: @@ -4927,10 +5340,10 @@ data: bob: 24 --- alice: (( persons::alice )) -prev: (( doc:1::. )) +prev: (( doc.1::. )) --- bob: (( persons::bob )) -prev: (( doc:2::. )) +prev: (( doc.2::. )) ``` resolves to @@ -4953,8 +5366,8 @@ prev: ``` If the given document index is negative it denotes the document relative to the -one actually processed (so, the tag `doc:-1` denotes the previous document). -The index `doc:0` can be used to denote the actual document. Here always a path +one actually processed (so, the tag `doc.-1` denotes the previous document). +The index `doc.0` can be used to denote the actual document. Here always a path must be specified, it is not possible to refer to the complete document (with `.`). @@ -5243,6 +5656,7 @@ The following fields are supported: | Field Name | Type | Meaning | | ------------| ---- | ------- | +| `VERSION` | string |current version of *spiff* | | `FILE` | string | name of actually processed template file | | `DIR` | string | name of directory of actually processed template file | | `RESOLVED_FILE` | string | name of actually processed template file with resolved symbolic links | @@ -5300,8 +5714,11 @@ The complete grammar can be found in [dynaml.peg](dynaml/dynaml.peg). ## String Interpolation +Feature state: alpha + **Attention:** This is an alpha feature. It must be enabled on the command -line with the `--interpolation` option. Also for the spiff library it must +line with the `--interpolation` or `--features=interpolation` option. +Also for the spiff library it must explicitly be enabled. By adding the key `interpolation` to the feature list stored in the environment variable `SPIFF_FEATURES` this feature will be enabled by default. @@ -5354,7 +5771,549 @@ will resolve `interpolation` to `this is testtest`. The embedded dynaml expression must be concatenatable with strings. +## YAML-based Control Structures + +Feature state: alpha + +In addition to describe conditions and loops with *dynaml* expressions +it is also possible to use elements of the document structure to embed +control structures. + +Such a YAML-based control structure is always described as a map in YAML/JSON. +The syntactical elements are expressed as map fields starting with `<<`. +Additionally, depending on the control structure, regular fields are possible. +Control structures finally represent a value for the containing node. +They may contain marker expressions (`<<`), also. + +e.g.: + +```yaml +temp: + <<: (( &temporary )) + <v == 5 )) + value: bob + <`) + + Here the order in the list determine the traversal order. + +Traversal is done by recursively iterating follow up ranges for every entry +in the actual range. This means the last range is completely iterated +for the first values of the first ranges first. + +If no index variable is specified for a loop range there is an additional +implicit binding for every control variable describing the actual list index +or map key of the processed value for this dimension. It is denoted by +`index-` + +If multiple loop ranges are specified, the ranges may mix iterations over +maps and lists. +The iteration result value is determined by the value of the `< s sum[bob|[]|s,index_bob,bob|->s (alice "-" key "-" bob "-" index_bob)]] )) +``` + +A result list may omit entries if the value expression evaluates to the undefined +value (`~~`). The nil value (`~`) is kept. This way a `for` control can be used +to filter lists. + +e.g.: + +```yaml +bob: +- 1 +- 2 +- 3 +filtered: + < s sum[bob|{}|s,index_bob,bob|->s {(alice bob)=alice bob x}]] )) +``` + +An iteration value is ignored if the key or the value evaluate to the undefined +value `(( ~~ ))`. Additionally the key may evaluate to the nil value `(( ~ ))`, also. + +e.g.: + +```yaml +bob: + b1: 1 + b2: 2 + b3: 3 +filtered: + < 0 || len(templateYAMLs) > 1 { defstate := flow.NewDefaultState().SetInterpolation(interpolation) defstate.SetTags(tags...) @@ -243,6 +253,7 @@ func merge(stdin bool, templateFilePath string, opts flow.Options, json, split b } binding = binding.WithLocalScope(values) } + features = binding.GetFeatures() } prepared, err := flow.PrepareStubs(binding, processingOptions.Partial, stubs...) @@ -272,7 +283,7 @@ func merge(stdin bool, templateFilePath string, opts flow.Options, json, split b } if subpath != "" { comps := dynaml.PathComponents(subpath, false) - node, ok := yaml.FindR(true, flowed, comps...) + node, ok := yaml.FindR(true, flowed, features, comps...) if !ok { log.Fatalln(fmt.Sprintf("path %q not found%s", subpath, doc)) } @@ -330,7 +341,7 @@ func merge(stdin bool, templateFilePath string, opts flow.Options, json, split b new := map[string]yaml.Node{} for _, p := range selection { comps := dynaml.PathComponents(p, false) - node, ok := yaml.FindR(true, flowed, comps...) + node, ok := yaml.FindR(true, flowed, features, comps...) if !ok { log.Fatalln(fmt.Sprintf("path %q not found%s", subpath, doc)) } diff --git a/cmd/root.go b/cmd/root.go index b909315..2245954 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,6 +9,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/mandelsoft/spiff/flow" ) var cfgFile string @@ -17,7 +19,7 @@ var cfgFile string var rootCmd = &cobra.Command{ Use: "spiff", Short: "YAML in-domain templating processor", - Version: "v1.7.0-beta-2", + Version: flow.VERSION, } // Execute adds all child commands to the root command and sets flags appropriately. diff --git a/compare/compare.go b/compare/compare.go index a1831c1..93dc7ea 100644 --- a/compare/compare.go +++ b/compare/compare.go @@ -68,7 +68,7 @@ func listToMap(list []yaml.Node) map[string]yaml.Node { toMap := make(map[string]yaml.Node) for _, val := range list { - name, ok := yaml.FindString(val, "name") + name, ok := yaml.FindString(val, nil, "name") if !ok { return nil } @@ -155,7 +155,7 @@ func jobMap(jobs []yaml.Node) map[string]yaml.Node { attrs, ok := job.Value().(map[string]yaml.Node) attrs["index"] = yaml.NewNode(index, job.SourceName()) - name, ok := yaml.FindString(job, "name") + name, ok := yaml.FindString(job, nil, "name") if !ok { panic("job without string name") } @@ -167,7 +167,7 @@ func jobMap(jobs []yaml.Node) map[string]yaml.Node { } func findByNameOrIndex(node yaml.Node, others []yaml.Node, index int) (string, yaml.Node, bool) { - name, ok := yaml.FindString(node, "name") + name, ok := yaml.FindString(node, nil, "name") if !ok { return findByIndex(others, index) } @@ -182,7 +182,7 @@ func findByNameOrIndex(node yaml.Node, others []yaml.Node, index int) (string, y func findByName(name string, nodes []yaml.Node) (string, yaml.Node, bool) { for _, node := range nodes { - otherName, ok := yaml.FindString(node, "name") + otherName, ok := yaml.FindString(node, nil, "name") if !ok { continue } diff --git a/dynaml/addition.go b/dynaml/addition.go index 2d18af2..2e23f29 100644 --- a/dynaml/addition.go +++ b/dynaml/addition.go @@ -30,15 +30,28 @@ func (e AdditionExpr) Evaluate(binding Binding, locally bool) (interface{}, Eval str, ok := a.(string) if ok { + var cidr *net.IPNet + var err error ip := net.ParseIP(str) if ip == nil { - return info.Error("first argument for addition must be IP address or number") + ip, cidr, err = net.ParseCIDR(str) + if err != nil { + return info.Error("first argument for addition must be IP address, CIDR or number") + } } bint, ok := b.(int64) if !ok { return info.Error("addition argument for an IP address requires an integer argument") } - return IPAdd(ip, bint).String(), info, true + ip = IPAdd(ip, bint) + if cidr != nil { + if !cidr.Contains(ip) { + return info.Error("resulting ip address not in CIDR range") + } + cidr.IP = ip + return cidr.String(), info, true + } + return ip.String(), info, true } a, b, err := NumberOperands(a, b) if err != nil { diff --git a/dynaml/auto.go b/dynaml/auto.go index f939c5b..8a0f03f 100644 --- a/dynaml/auto.go +++ b/dynaml/auto.go @@ -22,7 +22,7 @@ func (e AutoExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati return nil, info, false } - if !isResolvedValue(jobs) { + if !isResolvedValue(jobs, binding) { return e, info, true } jobsList, ok := jobs.([]yaml.Node) @@ -33,7 +33,7 @@ func (e AutoExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati var size int64 for _, job := range jobsList { - poolName, ok := yaml.FindString(job, "resource_pool") + poolName, ok := yaml.FindString(job, binding.GetFeatures(), "resource_pool") if !ok { continue } @@ -42,7 +42,7 @@ func (e AutoExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati continue } - instances, ok := yaml.FindInt(job, "instances") + instances, ok := yaml.FindInt(job, binding.GetFeatures(), "instances") if !ok { return nil, info, false } diff --git a/dynaml/call.go b/dynaml/call.go index 7f2ecea..4a4b333 100644 --- a/dynaml/call.go +++ b/dynaml/call.go @@ -11,32 +11,37 @@ import ( type Function func(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) -type Registry interface { +type Functions interface { RegisterFunction(name string, f Function) LookupFunction(name string) Function } -type registry struct { + +type functionRegistry struct { functions map[string]Function } -func NewRegistry() Registry { - return ®istry{map[string]Function{}} +func NewFunctions() Functions { + return &functionRegistry{map[string]Function{}} } -func (r *registry) RegisterFunction(name string, f Function) { +func (r *functionRegistry) RegisterFunction(name string, f Function) { r.functions[name] = f } -func (r *registry) LookupFunction(name string) Function { - return r.functions[name] +func (r *functionRegistry) LookupFunction(name string) Function { + f := r.functions[name] + if f != nil || r == function_registry { + return f + } + return function_registry.(*functionRegistry).functions[name] } -var functions = NewRegistry() - func RegisterFunction(name string, f Function) { - functions.RegisterFunction(name, f) + function_registry.RegisterFunction(name, f) } +var function_registry = NewFunctions() + type NameArgument struct { Name string Expression @@ -324,14 +329,7 @@ func (e CallExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati } default: - var f Function - ext := binding.GetState().GetFunctions() - if ext != nil { - f = ext.LookupFunction(funcName) - } - if f == nil { - f = functions.LookupFunction(funcName) - } + f := binding.GetState().GetRegistry().LookupFunction(funcName) if f == nil { return info.Error("unknown function '%s'", funcName) } @@ -341,7 +339,7 @@ func (e CallExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati if cleaned { info.Cleanup() } - if ok && (!resolved || isExpression(result)) { + if ok && (!resolved || IsExpression(result)) { return e, sub.Join(info), true } return result, sub.Join(info), ok diff --git a/dynaml/control.go b/dynaml/control.go new file mode 100644 index 0000000..5b2a147 --- /dev/null +++ b/dynaml/control.go @@ -0,0 +1,290 @@ +package dynaml + +import ( + "fmt" + "strings" + + "github.com/mandelsoft/spiff/yaml" +) + +type ControlContext struct { + Binding + *Control + Value yaml.Node + Node yaml.Node + Fields map[string]yaml.Node + Options map[string]yaml.Node +} + +func (c *ControlContext) Option(name string) yaml.Node { + return c.Options[name] +} +func (c *ControlContext) Field(name string) yaml.Node { + return c.Fields[name] +} +func (c *ControlContext) HasFields() bool { + return len(c.Fields) != 0 +} +func (c *ControlContext) SortedFields() []string { + return yaml.GetSortedKeys(c.Fields) +} +func (c *ControlContext) DefinedFields() map[string]yaml.Node { + result := map[string]yaml.Node{} + for k, v := range c.Fields { + if !v.Undefined() { + result[k] = v + } + } + return result +} +func (c *ControlContext) Function() (yaml.Node, bool) { + return c.Control.Function(c) +} + +type ControlFunction func(*ControlContext) (yaml.Node, bool) + +type Control struct { + name string + options map[string]bool + function ControlFunction +} + +func (c *Control) Name() string { + return c.name +} + +func (c *Control) Options() []string { + l := []string{} + for n := range c.options { + l = append(l, n) + } + return l +} + +func (c *Control) HasOption(name string) bool { + _, ok := c.options[name] + return ok +} + +func (c *Control) IsTemplateOption(name string) bool { + return c.options[name] +} + +func (c *Control) Function(env *ControlContext) (yaml.Node, bool) { + env.Control = c + return c.function(env) +} + +type Controls interface { + RegisterControl(name string, f ControlFunction, opts ...string) error + LookupControl(name string) (*Control, bool) + IsTemplateControlOption(name string) bool +} + +type controlRegistry struct { + controls map[string]*Control + templateoptions map[string]struct{} +} + +func newControls() *controlRegistry { + return &controlRegistry{map[string]*Control{}, map[string]struct{}{}} +} + +func NewControls() Controls { + r := newControls() + + for n, c := range control_registry.controls { + r.controls[n] = c + } + for n := range control_registry.templateoptions { + r.templateoptions[n] = struct{}{} + } + return r +} + +func (r *controlRegistry) RegisterControl(name string, f ControlFunction, opts ...string) error { + m := map[string]bool{} + for _, o := range opts { + t := false + if strings.HasPrefix(o, "*") { + t = true + o = o[1:] + } + m[o] = t + + if _, ok := r.templateoptions[o]; ok && !t { + return fmt.Errorf("ambigious control option template setting for %q", o) + } + if t { + r.templateoptions[o] = struct{}{} + } + } + c := &Control{ + name: name, + options: m, + function: f, + } + if _, ok := r.controls[c.name]; ok { + return fmt.Errorf("control or option %q already defined", c.name) + } + r.controls[c.name] = c + for _, o := range opts { + if strings.HasPrefix(o, "*") { + o = o[1:] + } + if old, ok := r.controls[o]; ok { + if old != nil { + return fmt.Errorf("option %q for control %q already defined as control", o, c.name) + } + } + r.controls[o] = nil + } + return nil +} + +func (r *controlRegistry) LookupControl(name string) (*Control, bool) { + c, ok := r.controls[name] + return c, ok +} + +func (r *controlRegistry) IsTemplateControlOption(name string) bool { + _, ok := r.templateoptions[name] + return ok +} + +var control_registry = newControls() + +func RegisterControl(name string, f ControlFunction, opts ...string) { + err := control_registry.RegisterControl(name, f, opts...) + if err != nil { + panic(err.Error()) + } +} + +func ControlIssue(ctx *ControlContext, msg string, args ...interface{}) (yaml.Node, bool) { + var issue yaml.Issue + if len(args) == 0 { + issue = yaml.NewIssue("%s", msg) + } else { + issue = yaml.NewIssue(msg, args...) + } + return ControlIssueByIssue(ctx, issue, true) +} + +func ControlIssueByIssue(ctx *ControlContext, issue yaml.Issue, final bool) (yaml.Node, bool) { + control := "" + if ctx.Control != nil { + control = fmt.Sprintf("<%s control>", ctx.name) + } + if !final { + return yaml.IssueNode(ctx.Node, true, true, issue), false + } + return yaml.IssueNode(yaml.NewNode(control, ctx.Node.SourceName()), true, true, issue), false +} + +func IsControl(node yaml.Node, env Binding) (bool, error) { + c, err := GetControl(node, nil, env) + return c != nil, err +} + +func RequireTemplate(opt string, env Binding) bool { + registry := env.GetState().GetRegistry() + if strings.HasPrefix(opt, "<<") { + return registry.IsTemplateControlOption(opt[2:]) + } + return false +} + +func GetControl(node yaml.Node, undef map[string]yaml.Node, env Binding) (*ControlContext, error) { + if env.GetFeatures().ControlEnabled() { + if m, ok := node.Value().(map[string]yaml.Node); ok { + registry := env.GetState().GetRegistry() + var name string + var val yaml.Node + var control *Control + opts := map[string]yaml.Node{} + fields := map[string]yaml.Node{} + + f := func(k string, v yaml.Node) error { + if strings.HasPrefix(k, "<<") { + n := k[2:] + if n != "" && n != "<" && n[0] != '!' { + c, ok := registry.LookupControl(n) + if !ok { + return fmt.Errorf("unknown control or control option %q", k) + } + if c != nil { + if control != nil { + return fmt.Errorf("multiple controls %q and %q", name, k) + } + name = k + control = c + val = v + } else { + opts[n] = v + } + } + return nil + } + fields[k] = v + return nil + } + + for k, v := range m { + if err := f(k, v); err != nil { + return nil, err + } + } + for k, v := range undef { + if err := f(k, v); err != nil { + return nil, err + } + } + + if control != nil { + for k, v := range undef { + m[k] = v + } + if err := control.CheckOpts(opts); err != nil { + return nil, err + } + return &ControlContext{ + Binding: env, + Control: control, + Node: node, + Value: val, + Fields: fields, + Options: opts, + }, nil + } else { + if len(opts) > 0 { + return nil, fmt.Errorf("control options %v without control", yaml.GetSortedKeys(opts)) + } + } + } + } + return nil, nil +} + +func (c *Control) CheckOpts(opts map[string]yaml.Node) error { + for o := range opts { + if _, ok := c.options[o]; !ok { + return fmt.Errorf("invalid option %q for control %q", o, c.name) + } + } + return nil +} + +func ControlValue(ctx *ControlContext, val yaml.Node) (yaml.Node, bool) { + if val.Undefined() || IsResolvedNode(val, ctx) { + return val, true + } + return val, false +} + +func ControlReady(ctx *ControlContext, acceptFields bool) (yaml.Node, bool) { + if !acceptFields && ctx.HasFields() { + return ControlIssue(ctx, "no regular fields %v allowed", ctx.SortedFields()) + } + return ctx.Node, (ctx.Value.Undefined() || IsResolvedNode(ctx.Value, ctx)) && _isResolvedValue(ctx.Options, true, ctx) && _isResolvedValue(ctx.Fields, true, ctx) +} diff --git a/dynaml/control/for.go b/dynaml/control/for.go new file mode 100644 index 0000000..47d17b6 --- /dev/null +++ b/dynaml/control/for.go @@ -0,0 +1,358 @@ +package control + +import ( + "fmt" + "regexp" + "sort" + "strings" + + "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + dynaml.RegisterControl("for", flowFor, "*do", "*mapkey") +} + +type iterator interface { + Len() int + Index(int) interface{} + Value(int) yaml.Node +} + +type iteration struct { + name string + index string + current int + iterator +} + +type iterations []*iteration + +func (this iterations) Len() int { + return len(this) +} +func (this iterations) Less(i, j int) bool { + c := strings.Compare(this[i].name, this[j].name) + if c != 0 { + return c > 0 + } + return strings.Compare(this[i].index, this[j].index) > 0 +} + +func (this iterations) Swap(i, j int) { + this[i], this[j] = this[j], this[i] +} + +func newIteration(name, index string, it iterator) iteration { + if index == "" { + index = "index-" + name + } + return iteration{name, index, 0, it} +} + +func (this *iteration) IndexName() string { + return this.index +} + +func (this *iteration) Value() yaml.Node { + return this.iterator.Value(this.current) +} + +func (this *iteration) Index() interface{} { + return this.iterator.Index(this.current) +} + +/////////////////////////////// + +type listIterator struct { + values []yaml.Node +} + +func newListIterator(values []yaml.Node) iterator { + return &listIterator{values} +} + +func (this *listIterator) Len() int { + return len(this.values) +} + +func (this *listIterator) Index(i int) interface{} { + return int64(i) +} + +func (this *listIterator) Value(i int) yaml.Node { + return this.values[i] +} + +/////////////////////////////// + +type mapIterator struct { + values map[string]yaml.Node + keys []string +} + +func newMapIterator(values map[string]yaml.Node) iterator { + return &mapIterator{values, yaml.GetSortedKeys(values)} +} + +func (this *mapIterator) Len() int { + return len(this.values) +} + +func (this *mapIterator) Index(i int) interface{} { + return this.keys[i] +} + +func (this *mapIterator) Value(i int) yaml.Node { + return this.values[this.keys[i]] +} + +func flowFor(ctx *dynaml.ControlContext) (yaml.Node, bool) { + if node, ok := dynaml.ControlReady(ctx, false); !ok { + return node, ok + } + + body := ctx.Option("do") + if body == nil { + return dynaml.ControlIssue(ctx, "do field required") + } + + if ctx.Value.Undefined() { + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } + var mapkey *dynaml.SubstitutionExpr + if k := ctx.Option("mapkey"); k != nil { + if t, ok := k.Value().(dynaml.TemplateValue); ok { + mapkey = &dynaml.SubstitutionExpr{dynaml.ValueExpr{t}} + } else { + return dynaml.ControlIssue(ctx, "mapkey must be an expression") + } + } + + var subst *dynaml.SubstitutionExpr + if t, ok := body.Value().(dynaml.TemplateValue); ok { + subst = &dynaml.SubstitutionExpr{dynaml.ValueExpr{t}} + } + ranges := iterations{} + switch def := ctx.Value.Value().(type) { + case map[string]yaml.Node: + ranges = make(iterations, len(def)) + i := 0 + for v, values := range def { + i++ + name := "" + index := "" + parts := strings.Split(v, ",") + switch len(parts) { + case 2: + index = strings.TrimSpace(parts[0]) + name = strings.TrimSpace(parts[1]) + case 1: + name = strings.TrimSpace(parts[0]) + default: + return dynaml.ControlIssue(ctx, "invalid control variable spec %q", v) + } + it, err := controlIterator(name, values) + if err != nil { + return dynaml.ControlIssue(ctx, err.Error()) + } + ranges[len(ranges)-i], err = controlIteration(name, index, it) + if err != nil { + return dynaml.ControlIssue(ctx, err.Error()) + } + } + sort.Sort(ranges) + case []yaml.Node: + ranges = make(iterations, len(def)) + for i, v := range def { + spec, ok := v.Value().(map[string]yaml.Node) + if !ok { + return dynaml.ControlIssue(ctx, "control variable list entry requires may but got %s", dynaml.ExpressionType(v)) + } + n := spec["name"] + if n == nil { + return dynaml.ControlIssue(ctx, "control variable list entry requires name field") + } + name, ok := n.Value().(string) + index := "" + n = spec["index"] + if n != nil { + index, ok = n.Value().(string) + if !ok { + return dynaml.ControlIssue(ctx, "control index variable name must be of type string but got %s", dynaml.ExpressionType(n)) + } + } + l := spec["values"] + if l == nil { + return dynaml.ControlIssue(ctx, "control variable list entry requires values field") + } + it, err := controlIterator(name, l) + if err != nil { + return dynaml.ControlIssue(ctx, err.Error()) + } + + if len(spec) < 2 || len(spec) > 3 { + return dynaml.ControlIssue(ctx, "control variable list entry requires two or three fields: name, values and optionally index") + } + + if len(spec) == 3 && index == "" { + for _, k := range yaml.GetSortedKeys(spec) { + switch k { + case "name": + case "values": + case "index": + default: + return dynaml.ControlIssue(ctx, "invalid control variable list entry field %q", k) + } + } + } + + ranges[len(ranges)-i-1], err = controlIteration(name, index, it) + if err != nil { + return dynaml.ControlIssue(ctx, err.Error()) + } + } + default: + return dynaml.ControlIssue(ctx, "value field must be map but got %s", dynaml.ExpressionType(def)) + } + + var resultlist []yaml.Node + var resultmap map[string]yaml.Node + + if mapkey != nil { + resultmap = map[string]yaml.Node{} + } else { + resultlist = []yaml.Node{} + } + + done := true + issue := yaml.Issue{} +outer: + for { + // do + inp := map[string]yaml.Node{} + for i := 0; i < len(ranges); i++ { + inp[ranges[i].name] = ranges[i].Value() + inp[ranges[i].IndexName()] = yaml.NewNode(ranges[i].Index(), "for") + } + scope := ctx.WithLocalScope(inp) + skip := false + key := "" + if mapkey != nil { + k, info, ok := mapkey.Evaluate(scope, false) + if !ok { + done = false + issue.Nested = append(issue.Nested, controlVariablesIssue(ranges, info.Issue)) + } + if info.Undefined || k == nil { + skip = true + } else { + if key, ok = k.(string); !ok { + done = false + issue.Nested = append(issue.Nested, controlVariablesIssue(ranges, yaml.NewIssue("map key must be string, but found %s", dynaml.ExpressionType(k)))) + } + } + } + if subst != nil { + v, info, ok := subst.Evaluate(scope, false) + if !ok { + done = false + issue.Nested = append(issue.Nested, controlVariablesIssue(ranges, info.Issue)) + } else { + if dynaml.IsExpression(v) { + done = false + } else { + if !skip && !info.Undefined { + if mapkey != nil { + resultmap[key] = dynaml.NewNode(v, ctx) + } else { + resultlist = append(resultlist, dynaml.NewNode(v, ctx)) + } + } + } + } + } else { + if mapkey != nil { + resultmap[key] = body + } else { + resultlist = append(resultlist, body) + } + } + + for i := 0; i <= len(ranges); i++ { + if i == len(ranges) { + break outer + } + ranges[i].current++ + if ranges[i].current < ranges[i].Len() { + break + } + ranges[i].current = 0 + } + } + if !done { + if len(issue.Nested) > 0 { + issue.Issue = "error evaluating body" + return dynaml.ControlIssueByIssue(ctx, issue, false) + } + return ctx.Node, false + } + if resultlist != nil { + return dynaml.NewNode(resultlist, ctx), true + } + return dynaml.NewNode(resultmap, ctx), true +} + +var namesyntax = regexp.MustCompile("[a-zA-Z0-9_]+") + +func checkName(kind, n string) error { + if !namesyntax.Match([]byte(n)) { + return fmt.Errorf("invalid %s variable name %q (must be %s)", kind, n, namesyntax.String()) + } + return nil +} + +func controlIteration(name, index string, it iterator) (*iteration, error) { + if err := checkName("range", name); err != nil { + return nil, err + } + if index == "" { + index = "index-" + name + } else { + if err := checkName("index", index); err != nil { + return nil, err + } + } + return &iteration{name, index, 0, it}, nil +} + +func controlIterator(name string, val yaml.Node) (iterator, error) { + var it iterator + switch values := val.Value().(type) { + case []yaml.Node: + if len(values) == 0 { + return nil, nil + } + it = newListIterator(values) + case map[string]yaml.Node: + if len(values) == 0 { + return nil, nil + } + it = newMapIterator(values) + default: + return nil, fmt.Errorf("control variable %q requires list or map value, but got %s", name, dynaml.ExpressionType(val)) + } + return it, nil +} + +func controlVariablesIssue(iterations iterations, issue yaml.Issue) yaml.Issue { + desc := fmt.Sprintf("control variables: ") + sep := "" + for _, i := range iterations { + desc = fmt.Sprintf("%s%s %s[%v]=%s", desc, sep, i.name, i.Index(), dynaml.Shorten(dynaml.Short(i.Value().Value(), false))) + sep = ";" + } + issue.Issue = fmt.Sprintf("%s: %s", desc, issue.Issue) + return issue +} diff --git a/dynaml/control/if.go b/dynaml/control/if.go new file mode 100644 index 0000000..086b405 --- /dev/null +++ b/dynaml/control/if.go @@ -0,0 +1,38 @@ +package control + +import ( + "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + dynaml.RegisterControl("if", flowIf, "then", "else") +} + +func flowIf(ctx *dynaml.ControlContext) (yaml.Node, bool) { + if node, ok := dynaml.ControlReady(ctx, false); !ok { + return node, false + } + if ctx.Value.Value() == nil { + if e := ctx.Option("else"); e != nil { + return dynaml.ControlValue(ctx, e) + } + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } + switch v := ctx.Value.Value().(type) { + case bool: + if v { + if e := ctx.Option("then"); e != nil { + return dynaml.ControlValue(ctx, e) + } + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } else { + if e := ctx.Option("else"); e != nil { + return dynaml.ControlValue(ctx, e) + } + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } + default: + return dynaml.ControlIssue(ctx, "invalid condition value type: %s", dynaml.ExpressionType(v)) + } +} diff --git a/dynaml/control/merge.go b/dynaml/control/merge.go new file mode 100644 index 0000000..9de9c07 --- /dev/null +++ b/dynaml/control/merge.go @@ -0,0 +1,43 @@ +package control + +import ( + "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + dynaml.RegisterControl("merge", flowMerge) +} + +func flowMerge(ctx *dynaml.ControlContext) (yaml.Node, bool) { + if node, ok := dynaml.ControlReady(ctx, true); !ok { + return node, false + } + fields := ctx.DefinedFields() + if ctx.Value.Value() != nil { + switch v := ctx.Value.Value().(type) { + case map[string]yaml.Node: + for k, e := range v { + fields[k] = e + } + case []yaml.Node: + for i, l := range v { + if l.Value() != nil { + if m, ok := l.Value().(map[string]yaml.Node); ok { + for k, e := range m { + fields[k] = e + } + } else { + return dynaml.ControlIssue(ctx, "entry %d: invalid entry type: %s", i, dynaml.ExpressionType(v)) + } + } + } + + default: + if v != nil { + return dynaml.ControlIssue(ctx, "invalid value type: %s", dynaml.ExpressionType(v)) + } + } + } + return dynaml.NewNode(fields, ctx), true +} diff --git a/dynaml/control/switch.go b/dynaml/control/switch.go new file mode 100644 index 0000000..da8e50e --- /dev/null +++ b/dynaml/control/switch.go @@ -0,0 +1,99 @@ +package control + +import ( + "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + dynaml.RegisterControl("switch", flowSwitch, "default", "cases") +} + +func flowSwitch(ctx *dynaml.ControlContext) (yaml.Node, bool) { + if ctx.Value.Undefined() { + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } + cases := ctx.Option("cases") + if node, ok := dynaml.ControlReady(ctx, cases == nil); !ok { + return node, false + } + if cases != nil { + switch list := cases.Value().(type) { + case []yaml.Node: + for i, c := range list { + if m, ok := c.Value().(map[string]yaml.Node); ok { + var value yaml.Node + reject := false + found := false + for k, v := range m { + switch k { + case "case": + found = true + reject = reject || !v.EquivalentToNode(ctx.Value) + case "match": + found = true + if f, ok := v.Value().(dynaml.LambdaValue); ok { + resolved, r, _, ok := f.Evaluate(false, false, false, nil, []interface{}{ctx.Value.Value()}, ctx, false) + if !ok { + reject = true + } else { + if !resolved { + return ctx.Node, false + } + if b, ok := r.(bool); !ok { + return dynaml.ControlIssue(ctx, "case %d boolean match result required, but got %s", i, dynaml.ExpressionType(r)) + } else { + reject = reject || !b + } + } + } + case "value": + value = v + default: + return dynaml.ControlIssue(ctx, "case %d invalid field %q", i, k) + } + } + if !found { + return dynaml.ControlIssue(ctx, "case %d requires 'case' or `'match' field", i) + } + if !reject { + if value != nil { + return dynaml.ControlValue(ctx, value) + } else { + return yaml.UndefinedNode(dynaml.NewNode(nil, ctx)), true + } + } + } else { + return dynaml.ControlIssue(ctx, "case %d requires field 'case'", i) + } + } + result := ctx.Option("default") + if result != nil { + return dynaml.ControlValue(ctx, result) + } + return dynaml.ControlIssue(ctx, "invalid switch value: %s", dynaml.Shorten(dynaml.Short(ctx.Value.Value(), false))) + default: + return dynaml.ControlIssue(ctx, "cases must be a list") + } + } + return selected(ctx, ctx.Value.Value()) +} + +func selected(ctx *dynaml.ControlContext, key interface{}) (yaml.Node, bool) { + var result yaml.Node + if key != nil { + switch v := key.(type) { + case string: + result = ctx.Field(v) + default: + return dynaml.ControlIssue(ctx, "invalid switch value type: %s", dynaml.ExpressionType(v)) + } + } + if result == nil { + result = ctx.Option("default") + } + if result != nil { + return dynaml.ControlValue(ctx, result) + } + return dynaml.ControlIssue(ctx, "invalid switch value: %q", key) +} diff --git a/dynaml/control/typeswitch.go b/dynaml/control/typeswitch.go new file mode 100644 index 0000000..9020eae --- /dev/null +++ b/dynaml/control/typeswitch.go @@ -0,0 +1,17 @@ +package control + +import ( + "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + dynaml.RegisterControl("type", flowType, "default") +} + +func flowType(ctx *dynaml.ControlContext) (yaml.Node, bool) { + if node, ok := dynaml.ControlReady(ctx, true); !ok { + return node, false + } + return selected(ctx, dynaml.ExpressionType(ctx.Value)) +} diff --git a/dynaml/dynamic_expression.go b/dynaml/dynamic_expression.go index 10a7329..cf42221 100644 --- a/dynaml/dynamic_expression.go +++ b/dynaml/dynamic_expression.go @@ -21,11 +21,11 @@ func (e DynamicExpr) Evaluate(binding Binding, locally bool) (interface{}, Evalu locally = locally || info.Raw - if !isLocallyResolvedValue(root) { + if !isLocallyResolvedValue(root, binding) { return e, info, true } - if !locally && !isResolvedValue(root) { + if !locally && !isResolvedValue(root, binding) { return e, info, true } @@ -34,7 +34,7 @@ func (e DynamicExpr) Evaluate(binding Binding, locally bool) (interface{}, Evalu if !ok { return nil, info, false } - if !isResolvedValue(dyn) { + if !isResolvedValue(dyn, binding) { return e, info, true } @@ -66,7 +66,7 @@ func (e DynamicExpr) Evaluate(binding Binding, locally bool) (interface{}, Evalu return info.Error("index or field name required for reference qualifier") } return NewReferenceExpr(qual...).find(func(end int, path []string) (yaml.Node, bool) { - return yaml.Find(NewNode(root, nil), path[:end+1]...) + return yaml.Find(NewNode(root, nil), binding.GetFeatures(), path[:end+1]...) }, binding, locally) } diff --git a/dynaml/dynaml.peg b/dynaml/dynaml.peg index 9b2e007..6dbd875 100644 --- a/dynaml/dynaml.peg +++ b/dynaml/dynaml.peg @@ -7,8 +7,8 @@ Prefer <- ws 'prefer' req_ws Expression MarkedExpression <- ws Marker ( req_ws SubsequentMarker )* ws MarkerExpression ? ws SubsequentMarker <- Marker -Marker <- '&' ( 'template' / 'temporary' / 'local' / 'inject' / 'state' / 'default' / TagMarker ) -TagMarker <- 'tag:' '*'? TagName ( ':' TagName )* +Marker <- '&' ( 'template' / 'temporary' / 'local' / 'inject' / 'state' / 'default' / 'dynamic' / TagMarker ) +TagMarker <- 'tag:' '*'? Tag MarkerExpression <- Grouped Expression <- ( Scoped / LambdaExpr / Level7 ) ws @@ -119,9 +119,10 @@ Name <- [a-zA-Z0-9_]+ DefaultValue <- '=' Expression VarParams <- '...' ws -Reference <- (( Tag ('.' / Key )) / ( '.'? Key )) FollowUpRef -Tag <- ( ('doc:' '-'? [0-9]+) / (TagName ( ':' TagName )*) ) '::' -TagName <- [a-zA-Z_] [a-zA-Z0-9_]* +Reference <- (( TagPrefix ('.' / Key )) / ( '.'? Key )) FollowUpRef +TagPrefix <- ( ('doc' [.:] '-'? [0-9]+) / Tag ) '::' +Tag <- TagComponent ( [.:] TagComponent )* +TagComponent <- [a-zA-Z_] [a-zA-Z0-9_]* FollowUpRef <- PathComponent* PathComponent <- ( '.' Key ) / ( '.'? Index ) diff --git a/dynaml/dynaml.peg.go b/dynaml/dynaml.peg.go index cf6b3e4..4a71f8e 100644 --- a/dynaml/dynaml.peg.go +++ b/dynaml/dynaml.peg.go @@ -107,8 +107,9 @@ const ( ruleDefaultValue ruleVarParams ruleReference + ruleTagPrefix ruleTag - ruleTagName + ruleTagComponent ruleFollowUpRef rulePathComponent ruleKey @@ -220,8 +221,9 @@ var rul3s = [...]string{ "DefaultValue", "VarParams", "Reference", + "TagPrefix", "Tag", - "TagName", + "TagComponent", "FollowUpRef", "PathComponent", "Key", @@ -550,7 +552,7 @@ func (t *tokens32) Expand(index int) tokenTree { type DynamlGrammar struct { Buffer string buffer []rune - rules [106]func() bool + rules [107]func() bool Parse func(rule ...int) error Reset func() Pretty bool @@ -861,7 +863,7 @@ func (p *DynamlGrammar) Init() { position, tokenIndex, depth = position14, tokenIndex14, depth14 return false }, - /* 4 Marker <- <('&' (('t' 'e' 'm' 'p' 'l' 'a' 't' 'e') / ('t' 'e' 'm' 'p' 'o' 'r' 'a' 'r' 'y') / ('l' 'o' 'c' 'a' 'l') / ('i' 'n' 'j' 'e' 'c' 't') / ('s' 't' 'a' 't' 'e') / ('d' 'e' 'f' 'a' 'u' 'l' 't') / TagMarker))> */ + /* 4 Marker <- <('&' (('t' 'e' 'm' 'p' 'l' 'a' 't' 'e') / ('t' 'e' 'm' 'p' 'o' 'r' 'a' 'r' 'y') / ('l' 'o' 'c' 'a' 'l') / ('i' 'n' 'j' 'e' 'c' 't') / ('s' 't' 'a' 't' 'e') / ('d' 'e' 'f' 'a' 'u' 'l' 't') / ('d' 'y' 'n' 'a' 'm' 'i' 'c') / TagMarker))> */ func() bool { position16, tokenIndex16, depth16 := position, tokenIndex, depth { @@ -1050,6 +1052,37 @@ func (p *DynamlGrammar) Init() { position++ goto l18 l24: + position, tokenIndex, depth = position18, tokenIndex18, depth18 + if buffer[position] != rune('d') { + goto l25 + } + position++ + if buffer[position] != rune('y') { + goto l25 + } + position++ + if buffer[position] != rune('n') { + goto l25 + } + position++ + if buffer[position] != rune('a') { + goto l25 + } + position++ + if buffer[position] != rune('m') { + goto l25 + } + position++ + if buffer[position] != rune('i') { + goto l25 + } + position++ + if buffer[position] != rune('c') { + goto l25 + } + position++ + goto l18 + l25: position, tokenIndex, depth = position18, tokenIndex18, depth18 if !_rules[ruleTagMarker]() { goto l16 @@ -1064,566 +1097,563 @@ func (p *DynamlGrammar) Init() { position, tokenIndex, depth = position16, tokenIndex16, depth16 return false }, - /* 5 TagMarker <- <('t' 'a' 'g' ':' '*'? TagName (':' TagName)*)> */ + /* 5 TagMarker <- <('t' 'a' 'g' ':' '*'? Tag)> */ func() bool { - position25, tokenIndex25, depth25 := position, tokenIndex, depth + position26, tokenIndex26, depth26 := position, tokenIndex, depth { - position26 := position + position27 := position depth++ if buffer[position] != rune('t') { - goto l25 + goto l26 } position++ if buffer[position] != rune('a') { - goto l25 + goto l26 } position++ if buffer[position] != rune('g') { - goto l25 + goto l26 } position++ if buffer[position] != rune(':') { - goto l25 + goto l26 } position++ { - position27, tokenIndex27, depth27 := position, tokenIndex, depth + position28, tokenIndex28, depth28 := position, tokenIndex, depth if buffer[position] != rune('*') { - goto l27 + goto l28 } position++ - goto l28 - l27: - position, tokenIndex, depth = position27, tokenIndex27, depth27 - } - l28: - if !_rules[ruleTagName]() { - goto l25 + goto l29 + l28: + position, tokenIndex, depth = position28, tokenIndex28, depth28 } l29: - { - position30, tokenIndex30, depth30 := position, tokenIndex, depth - if buffer[position] != rune(':') { - goto l30 - } - position++ - if !_rules[ruleTagName]() { - goto l30 - } - goto l29 - l30: - position, tokenIndex, depth = position30, tokenIndex30, depth30 + if !_rules[ruleTag]() { + goto l26 } depth-- - add(ruleTagMarker, position26) + add(ruleTagMarker, position27) } return true - l25: - position, tokenIndex, depth = position25, tokenIndex25, depth25 + l26: + position, tokenIndex, depth = position26, tokenIndex26, depth26 return false }, /* 6 MarkerExpression <- */ func() bool { - position31, tokenIndex31, depth31 := position, tokenIndex, depth + position30, tokenIndex30, depth30 := position, tokenIndex, depth { - position32 := position + position31 := position depth++ if !_rules[ruleGrouped]() { - goto l31 + goto l30 } depth-- - add(ruleMarkerExpression, position32) + add(ruleMarkerExpression, position31) } return true - l31: - position, tokenIndex, depth = position31, tokenIndex31, depth31 + l30: + position, tokenIndex, depth = position30, tokenIndex30, depth30 return false }, /* 7 Expression <- <((Scoped / LambdaExpr / Level7) ws)> */ func() bool { - position33, tokenIndex33, depth33 := position, tokenIndex, depth + position32, tokenIndex32, depth32 := position, tokenIndex, depth { - position34 := position + position33 := position depth++ { - position35, tokenIndex35, depth35 := position, tokenIndex, depth + position34, tokenIndex34, depth34 := position, tokenIndex, depth if !_rules[ruleScoped]() { - goto l36 + goto l35 } - goto l35 - l36: - position, tokenIndex, depth = position35, tokenIndex35, depth35 + goto l34 + l35: + position, tokenIndex, depth = position34, tokenIndex34, depth34 if !_rules[ruleLambdaExpr]() { - goto l37 + goto l36 } - goto l35 - l37: - position, tokenIndex, depth = position35, tokenIndex35, depth35 + goto l34 + l36: + position, tokenIndex, depth = position34, tokenIndex34, depth34 if !_rules[ruleLevel7]() { - goto l33 + goto l32 } } - l35: + l34: if !_rules[rulews]() { - goto l33 + goto l32 } depth-- - add(ruleExpression, position34) + add(ruleExpression, position33) } return true - l33: - position, tokenIndex, depth = position33, tokenIndex33, depth33 + l32: + position, tokenIndex, depth = position32, tokenIndex32, depth32 return false }, /* 8 Scoped <- <(ws Scope ws Expression)> */ func() bool { - position38, tokenIndex38, depth38 := position, tokenIndex, depth + position37, tokenIndex37, depth37 := position, tokenIndex, depth { - position39 := position + position38 := position depth++ if !_rules[rulews]() { - goto l38 + goto l37 } if !_rules[ruleScope]() { - goto l38 + goto l37 } if !_rules[rulews]() { - goto l38 + goto l37 } if !_rules[ruleExpression]() { - goto l38 + goto l37 } depth-- - add(ruleScoped, position39) + add(ruleScoped, position38) } return true - l38: - position, tokenIndex, depth = position38, tokenIndex38, depth38 + l37: + position, tokenIndex, depth = position37, tokenIndex37, depth37 return false }, /* 9 Scope <- <(CreateScope ws Assignments? ')')> */ func() bool { - position40, tokenIndex40, depth40 := position, tokenIndex, depth + position39, tokenIndex39, depth39 := position, tokenIndex, depth { - position41 := position + position40 := position depth++ if !_rules[ruleCreateScope]() { - goto l40 + goto l39 } if !_rules[rulews]() { - goto l40 + goto l39 } { - position42, tokenIndex42, depth42 := position, tokenIndex, depth + position41, tokenIndex41, depth41 := position, tokenIndex, depth if !_rules[ruleAssignments]() { - goto l42 + goto l41 } - goto l43 - l42: - position, tokenIndex, depth = position42, tokenIndex42, depth42 + goto l42 + l41: + position, tokenIndex, depth = position41, tokenIndex41, depth41 } - l43: + l42: if buffer[position] != rune(')') { - goto l40 + goto l39 } position++ depth-- - add(ruleScope, position41) + add(ruleScope, position40) } return true - l40: - position, tokenIndex, depth = position40, tokenIndex40, depth40 + l39: + position, tokenIndex, depth = position39, tokenIndex39, depth39 return false }, /* 10 CreateScope <- <'('> */ func() bool { - position44, tokenIndex44, depth44 := position, tokenIndex, depth + position43, tokenIndex43, depth43 := position, tokenIndex, depth { - position45 := position + position44 := position depth++ if buffer[position] != rune('(') { - goto l44 + goto l43 } position++ depth-- - add(ruleCreateScope, position45) + add(ruleCreateScope, position44) } return true - l44: - position, tokenIndex, depth = position44, tokenIndex44, depth44 + l43: + position, tokenIndex, depth = position43, tokenIndex43, depth43 return false }, /* 11 Level7 <- <(ws Level6 (req_ws Or)*)> */ func() bool { - position46, tokenIndex46, depth46 := position, tokenIndex, depth + position45, tokenIndex45, depth45 := position, tokenIndex, depth { - position47 := position + position46 := position depth++ if !_rules[rulews]() { - goto l46 + goto l45 } if !_rules[ruleLevel6]() { - goto l46 + goto l45 } - l48: + l47: { - position49, tokenIndex49, depth49 := position, tokenIndex, depth + position48, tokenIndex48, depth48 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l49 + goto l48 } if !_rules[ruleOr]() { - goto l49 + goto l48 } - goto l48 - l49: - position, tokenIndex, depth = position49, tokenIndex49, depth49 + goto l47 + l48: + position, tokenIndex, depth = position48, tokenIndex48, depth48 } depth-- - add(ruleLevel7, position47) + add(ruleLevel7, position46) } return true - l46: - position, tokenIndex, depth = position46, tokenIndex46, depth46 + l45: + position, tokenIndex, depth = position45, tokenIndex45, depth45 return false }, /* 12 Or <- <(OrOp req_ws Level6)> */ func() bool { - position50, tokenIndex50, depth50 := position, tokenIndex, depth + position49, tokenIndex49, depth49 := position, tokenIndex, depth { - position51 := position + position50 := position depth++ if !_rules[ruleOrOp]() { - goto l50 + goto l49 } if !_rules[rulereq_ws]() { - goto l50 + goto l49 } if !_rules[ruleLevel6]() { - goto l50 + goto l49 } depth-- - add(ruleOr, position51) + add(ruleOr, position50) } return true - l50: - position, tokenIndex, depth = position50, tokenIndex50, depth50 + l49: + position, tokenIndex, depth = position49, tokenIndex49, depth49 return false }, /* 13 OrOp <- <(('|' '|') / ('/' '/'))> */ func() bool { - position52, tokenIndex52, depth52 := position, tokenIndex, depth + position51, tokenIndex51, depth51 := position, tokenIndex, depth { - position53 := position + position52 := position depth++ { - position54, tokenIndex54, depth54 := position, tokenIndex, depth + position53, tokenIndex53, depth53 := position, tokenIndex, depth if buffer[position] != rune('|') { - goto l55 + goto l54 } position++ if buffer[position] != rune('|') { - goto l55 + goto l54 } position++ - goto l54 - l55: - position, tokenIndex, depth = position54, tokenIndex54, depth54 + goto l53 + l54: + position, tokenIndex, depth = position53, tokenIndex53, depth53 if buffer[position] != rune('/') { - goto l52 + goto l51 } position++ if buffer[position] != rune('/') { - goto l52 + goto l51 } position++ } - l54: + l53: depth-- - add(ruleOrOp, position53) + add(ruleOrOp, position52) } return true - l52: - position, tokenIndex, depth = position52, tokenIndex52, depth52 + l51: + position, tokenIndex, depth = position51, tokenIndex51, depth51 return false }, /* 14 Level6 <- <(Conditional / Level5)> */ func() bool { - position56, tokenIndex56, depth56 := position, tokenIndex, depth + position55, tokenIndex55, depth55 := position, tokenIndex, depth { - position57 := position + position56 := position depth++ { - position58, tokenIndex58, depth58 := position, tokenIndex, depth + position57, tokenIndex57, depth57 := position, tokenIndex, depth if !_rules[ruleConditional]() { - goto l59 + goto l58 } - goto l58 - l59: - position, tokenIndex, depth = position58, tokenIndex58, depth58 + goto l57 + l58: + position, tokenIndex, depth = position57, tokenIndex57, depth57 if !_rules[ruleLevel5]() { - goto l56 + goto l55 } } - l58: + l57: depth-- - add(ruleLevel6, position57) + add(ruleLevel6, position56) } return true - l56: - position, tokenIndex, depth = position56, tokenIndex56, depth56 + l55: + position, tokenIndex, depth = position55, tokenIndex55, depth55 return false }, /* 15 Conditional <- <(Level5 ws '?' Expression ':' Expression)> */ func() bool { - position60, tokenIndex60, depth60 := position, tokenIndex, depth + position59, tokenIndex59, depth59 := position, tokenIndex, depth { - position61 := position + position60 := position depth++ if !_rules[ruleLevel5]() { - goto l60 + goto l59 } if !_rules[rulews]() { - goto l60 + goto l59 } if buffer[position] != rune('?') { - goto l60 + goto l59 } position++ if !_rules[ruleExpression]() { - goto l60 + goto l59 } if buffer[position] != rune(':') { - goto l60 + goto l59 } position++ if !_rules[ruleExpression]() { - goto l60 + goto l59 } depth-- - add(ruleConditional, position61) + add(ruleConditional, position60) } return true - l60: - position, tokenIndex, depth = position60, tokenIndex60, depth60 + l59: + position, tokenIndex, depth = position59, tokenIndex59, depth59 return false }, /* 16 Level5 <- <(Level4 Concatenation*)> */ func() bool { - position62, tokenIndex62, depth62 := position, tokenIndex, depth + position61, tokenIndex61, depth61 := position, tokenIndex, depth { - position63 := position + position62 := position depth++ if !_rules[ruleLevel4]() { - goto l62 + goto l61 } - l64: + l63: { - position65, tokenIndex65, depth65 := position, tokenIndex, depth + position64, tokenIndex64, depth64 := position, tokenIndex, depth if !_rules[ruleConcatenation]() { - goto l65 + goto l64 } - goto l64 - l65: - position, tokenIndex, depth = position65, tokenIndex65, depth65 + goto l63 + l64: + position, tokenIndex, depth = position64, tokenIndex64, depth64 } depth-- - add(ruleLevel5, position63) + add(ruleLevel5, position62) } return true - l62: - position, tokenIndex, depth = position62, tokenIndex62, depth62 + l61: + position, tokenIndex, depth = position61, tokenIndex61, depth61 return false }, /* 17 Concatenation <- <(req_ws Level4)> */ func() bool { - position66, tokenIndex66, depth66 := position, tokenIndex, depth + position65, tokenIndex65, depth65 := position, tokenIndex, depth { - position67 := position + position66 := position depth++ if !_rules[rulereq_ws]() { - goto l66 + goto l65 } if !_rules[ruleLevel4]() { - goto l66 + goto l65 } depth-- - add(ruleConcatenation, position67) + add(ruleConcatenation, position66) } return true - l66: - position, tokenIndex, depth = position66, tokenIndex66, depth66 + l65: + position, tokenIndex, depth = position65, tokenIndex65, depth65 return false }, /* 18 Level4 <- <(Level3 (req_ws (LogOr / LogAnd))*)> */ func() bool { - position68, tokenIndex68, depth68 := position, tokenIndex, depth + position67, tokenIndex67, depth67 := position, tokenIndex, depth { - position69 := position + position68 := position depth++ if !_rules[ruleLevel3]() { - goto l68 + goto l67 } - l70: + l69: { - position71, tokenIndex71, depth71 := position, tokenIndex, depth + position70, tokenIndex70, depth70 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l71 + goto l70 } { - position72, tokenIndex72, depth72 := position, tokenIndex, depth + position71, tokenIndex71, depth71 := position, tokenIndex, depth if !_rules[ruleLogOr]() { - goto l73 + goto l72 } - goto l72 - l73: - position, tokenIndex, depth = position72, tokenIndex72, depth72 + goto l71 + l72: + position, tokenIndex, depth = position71, tokenIndex71, depth71 if !_rules[ruleLogAnd]() { - goto l71 + goto l70 } } - l72: - goto l70 l71: - position, tokenIndex, depth = position71, tokenIndex71, depth71 + goto l69 + l70: + position, tokenIndex, depth = position70, tokenIndex70, depth70 } depth-- - add(ruleLevel4, position69) + add(ruleLevel4, position68) } return true - l68: - position, tokenIndex, depth = position68, tokenIndex68, depth68 + l67: + position, tokenIndex, depth = position67, tokenIndex67, depth67 return false }, /* 19 LogOr <- <('-' 'o' 'r' req_ws Level3)> */ func() bool { - position74, tokenIndex74, depth74 := position, tokenIndex, depth + position73, tokenIndex73, depth73 := position, tokenIndex, depth { - position75 := position + position74 := position depth++ if buffer[position] != rune('-') { - goto l74 + goto l73 } position++ if buffer[position] != rune('o') { - goto l74 + goto l73 } position++ if buffer[position] != rune('r') { - goto l74 + goto l73 } position++ if !_rules[rulereq_ws]() { - goto l74 + goto l73 } if !_rules[ruleLevel3]() { - goto l74 + goto l73 } depth-- - add(ruleLogOr, position75) + add(ruleLogOr, position74) } return true - l74: - position, tokenIndex, depth = position74, tokenIndex74, depth74 + l73: + position, tokenIndex, depth = position73, tokenIndex73, depth73 return false }, /* 20 LogAnd <- <('-' 'a' 'n' 'd' req_ws Level3)> */ func() bool { - position76, tokenIndex76, depth76 := position, tokenIndex, depth + position75, tokenIndex75, depth75 := position, tokenIndex, depth { - position77 := position + position76 := position depth++ if buffer[position] != rune('-') { - goto l76 + goto l75 } position++ if buffer[position] != rune('a') { - goto l76 + goto l75 } position++ if buffer[position] != rune('n') { - goto l76 + goto l75 } position++ if buffer[position] != rune('d') { - goto l76 + goto l75 } position++ if !_rules[rulereq_ws]() { - goto l76 + goto l75 } if !_rules[ruleLevel3]() { - goto l76 + goto l75 } depth-- - add(ruleLogAnd, position77) + add(ruleLogAnd, position76) } return true - l76: - position, tokenIndex, depth = position76, tokenIndex76, depth76 + l75: + position, tokenIndex, depth = position75, tokenIndex75, depth75 return false }, /* 21 Level3 <- <(Level2 (req_ws Comparison)*)> */ func() bool { - position78, tokenIndex78, depth78 := position, tokenIndex, depth + position77, tokenIndex77, depth77 := position, tokenIndex, depth { - position79 := position + position78 := position depth++ if !_rules[ruleLevel2]() { - goto l78 + goto l77 } - l80: + l79: { - position81, tokenIndex81, depth81 := position, tokenIndex, depth + position80, tokenIndex80, depth80 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l81 + goto l80 } if !_rules[ruleComparison]() { - goto l81 + goto l80 } - goto l80 - l81: - position, tokenIndex, depth = position81, tokenIndex81, depth81 + goto l79 + l80: + position, tokenIndex, depth = position80, tokenIndex80, depth80 } depth-- - add(ruleLevel3, position79) + add(ruleLevel3, position78) } return true - l78: - position, tokenIndex, depth = position78, tokenIndex78, depth78 + l77: + position, tokenIndex, depth = position77, tokenIndex77, depth77 return false }, /* 22 Comparison <- <(CompareOp req_ws Level2)> */ func() bool { - position82, tokenIndex82, depth82 := position, tokenIndex, depth + position81, tokenIndex81, depth81 := position, tokenIndex, depth { - position83 := position + position82 := position depth++ if !_rules[ruleCompareOp]() { - goto l82 + goto l81 } if !_rules[rulereq_ws]() { - goto l82 + goto l81 } if !_rules[ruleLevel2]() { - goto l82 + goto l81 } depth-- - add(ruleComparison, position83) + add(ruleComparison, position82) } return true - l82: - position, tokenIndex, depth = position82, tokenIndex82, depth82 + l81: + position, tokenIndex, depth = position81, tokenIndex81, depth81 return false }, /* 23 CompareOp <- <(('=' '=') / ('!' '=') / ('<' '=') / ('>' '=') / '>' / '<' / '>')> */ func() bool { - position84, tokenIndex84, depth84 := position, tokenIndex, depth + position83, tokenIndex83, depth83 := position, tokenIndex, depth { - position85 := position + position84 := position depth++ { - position86, tokenIndex86, depth86 := position, tokenIndex, depth + position85, tokenIndex85, depth85 := position, tokenIndex, depth if buffer[position] != rune('=') { + goto l86 + } + position++ + if buffer[position] != rune('=') { + goto l86 + } + position++ + goto l85 + l86: + position, tokenIndex, depth = position85, tokenIndex85, depth85 + if buffer[position] != rune('!') { goto l87 } position++ @@ -1631,10 +1661,10 @@ func (p *DynamlGrammar) Init() { goto l87 } position++ - goto l86 + goto l85 l87: - position, tokenIndex, depth = position86, tokenIndex86, depth86 - if buffer[position] != rune('!') { + position, tokenIndex, depth = position85, tokenIndex85, depth85 + if buffer[position] != rune('<') { goto l88 } position++ @@ -1642,10 +1672,10 @@ func (p *DynamlGrammar) Init() { goto l88 } position++ - goto l86 + goto l85 l88: - position, tokenIndex, depth = position86, tokenIndex86, depth86 - if buffer[position] != rune('<') { + position, tokenIndex, depth = position85, tokenIndex85, depth85 + if buffer[position] != rune('>') { goto l89 } position++ @@ -1653,3398 +1683,3426 @@ func (p *DynamlGrammar) Init() { goto l89 } position++ - goto l86 + goto l85 l89: - position, tokenIndex, depth = position86, tokenIndex86, depth86 + position, tokenIndex, depth = position85, tokenIndex85, depth85 if buffer[position] != rune('>') { goto l90 } position++ - if buffer[position] != rune('=') { - goto l90 - } - position++ - goto l86 + goto l85 l90: - position, tokenIndex, depth = position86, tokenIndex86, depth86 - if buffer[position] != rune('>') { + position, tokenIndex, depth = position85, tokenIndex85, depth85 + if buffer[position] != rune('<') { goto l91 } position++ - goto l86 + goto l85 l91: - position, tokenIndex, depth = position86, tokenIndex86, depth86 - if buffer[position] != rune('<') { - goto l92 - } - position++ - goto l86 - l92: - position, tokenIndex, depth = position86, tokenIndex86, depth86 + position, tokenIndex, depth = position85, tokenIndex85, depth85 if buffer[position] != rune('>') { - goto l84 + goto l83 } position++ } - l86: + l85: depth-- - add(ruleCompareOp, position85) + add(ruleCompareOp, position84) } return true - l84: - position, tokenIndex, depth = position84, tokenIndex84, depth84 + l83: + position, tokenIndex, depth = position83, tokenIndex83, depth83 return false }, /* 24 Level2 <- <(Level1 (req_ws (Addition / Subtraction))*)> */ func() bool { - position93, tokenIndex93, depth93 := position, tokenIndex, depth + position92, tokenIndex92, depth92 := position, tokenIndex, depth { - position94 := position + position93 := position depth++ if !_rules[ruleLevel1]() { - goto l93 + goto l92 } - l95: + l94: { - position96, tokenIndex96, depth96 := position, tokenIndex, depth + position95, tokenIndex95, depth95 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l96 + goto l95 } { - position97, tokenIndex97, depth97 := position, tokenIndex, depth + position96, tokenIndex96, depth96 := position, tokenIndex, depth if !_rules[ruleAddition]() { - goto l98 + goto l97 } - goto l97 - l98: - position, tokenIndex, depth = position97, tokenIndex97, depth97 + goto l96 + l97: + position, tokenIndex, depth = position96, tokenIndex96, depth96 if !_rules[ruleSubtraction]() { - goto l96 + goto l95 } } - l97: - goto l95 l96: - position, tokenIndex, depth = position96, tokenIndex96, depth96 + goto l94 + l95: + position, tokenIndex, depth = position95, tokenIndex95, depth95 } depth-- - add(ruleLevel2, position94) + add(ruleLevel2, position93) } return true - l93: - position, tokenIndex, depth = position93, tokenIndex93, depth93 + l92: + position, tokenIndex, depth = position92, tokenIndex92, depth92 return false }, /* 25 Addition <- <('+' req_ws Level1)> */ func() bool { - position99, tokenIndex99, depth99 := position, tokenIndex, depth + position98, tokenIndex98, depth98 := position, tokenIndex, depth { - position100 := position + position99 := position depth++ if buffer[position] != rune('+') { - goto l99 + goto l98 } position++ if !_rules[rulereq_ws]() { - goto l99 + goto l98 } if !_rules[ruleLevel1]() { - goto l99 + goto l98 } depth-- - add(ruleAddition, position100) + add(ruleAddition, position99) } return true - l99: - position, tokenIndex, depth = position99, tokenIndex99, depth99 + l98: + position, tokenIndex, depth = position98, tokenIndex98, depth98 return false }, /* 26 Subtraction <- <('-' req_ws Level1)> */ func() bool { - position101, tokenIndex101, depth101 := position, tokenIndex, depth + position100, tokenIndex100, depth100 := position, tokenIndex, depth { - position102 := position + position101 := position depth++ if buffer[position] != rune('-') { - goto l101 + goto l100 } position++ if !_rules[rulereq_ws]() { - goto l101 + goto l100 } if !_rules[ruleLevel1]() { - goto l101 + goto l100 } depth-- - add(ruleSubtraction, position102) + add(ruleSubtraction, position101) } return true - l101: - position, tokenIndex, depth = position101, tokenIndex101, depth101 + l100: + position, tokenIndex, depth = position100, tokenIndex100, depth100 return false }, /* 27 Level1 <- <(Level0 (req_ws (Multiplication / Division / Modulo))*)> */ func() bool { - position103, tokenIndex103, depth103 := position, tokenIndex, depth + position102, tokenIndex102, depth102 := position, tokenIndex, depth { - position104 := position + position103 := position depth++ if !_rules[ruleLevel0]() { - goto l103 + goto l102 } - l105: + l104: { - position106, tokenIndex106, depth106 := position, tokenIndex, depth + position105, tokenIndex105, depth105 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l106 + goto l105 } { - position107, tokenIndex107, depth107 := position, tokenIndex, depth + position106, tokenIndex106, depth106 := position, tokenIndex, depth if !_rules[ruleMultiplication]() { - goto l108 + goto l107 } - goto l107 - l108: - position, tokenIndex, depth = position107, tokenIndex107, depth107 + goto l106 + l107: + position, tokenIndex, depth = position106, tokenIndex106, depth106 if !_rules[ruleDivision]() { - goto l109 + goto l108 } - goto l107 - l109: - position, tokenIndex, depth = position107, tokenIndex107, depth107 + goto l106 + l108: + position, tokenIndex, depth = position106, tokenIndex106, depth106 if !_rules[ruleModulo]() { - goto l106 + goto l105 } } - l107: - goto l105 l106: - position, tokenIndex, depth = position106, tokenIndex106, depth106 + goto l104 + l105: + position, tokenIndex, depth = position105, tokenIndex105, depth105 } depth-- - add(ruleLevel1, position104) + add(ruleLevel1, position103) } return true - l103: - position, tokenIndex, depth = position103, tokenIndex103, depth103 + l102: + position, tokenIndex, depth = position102, tokenIndex102, depth102 return false }, /* 28 Multiplication <- <('*' req_ws Level0)> */ func() bool { - position110, tokenIndex110, depth110 := position, tokenIndex, depth + position109, tokenIndex109, depth109 := position, tokenIndex, depth { - position111 := position + position110 := position depth++ if buffer[position] != rune('*') { - goto l110 + goto l109 } position++ if !_rules[rulereq_ws]() { - goto l110 + goto l109 } if !_rules[ruleLevel0]() { - goto l110 + goto l109 } depth-- - add(ruleMultiplication, position111) + add(ruleMultiplication, position110) } return true - l110: - position, tokenIndex, depth = position110, tokenIndex110, depth110 + l109: + position, tokenIndex, depth = position109, tokenIndex109, depth109 return false }, /* 29 Division <- <('/' req_ws Level0)> */ func() bool { - position112, tokenIndex112, depth112 := position, tokenIndex, depth + position111, tokenIndex111, depth111 := position, tokenIndex, depth { - position113 := position + position112 := position depth++ if buffer[position] != rune('/') { - goto l112 + goto l111 } position++ if !_rules[rulereq_ws]() { - goto l112 + goto l111 } if !_rules[ruleLevel0]() { - goto l112 + goto l111 } depth-- - add(ruleDivision, position113) + add(ruleDivision, position112) } return true - l112: - position, tokenIndex, depth = position112, tokenIndex112, depth112 + l111: + position, tokenIndex, depth = position111, tokenIndex111, depth111 return false }, /* 30 Modulo <- <('%' req_ws Level0)> */ func() bool { - position114, tokenIndex114, depth114 := position, tokenIndex, depth + position113, tokenIndex113, depth113 := position, tokenIndex, depth { - position115 := position + position114 := position depth++ if buffer[position] != rune('%') { - goto l114 + goto l113 } position++ if !_rules[rulereq_ws]() { - goto l114 + goto l113 } if !_rules[ruleLevel0]() { - goto l114 + goto l113 } depth-- - add(ruleModulo, position115) + add(ruleModulo, position114) } return true - l114: - position, tokenIndex, depth = position114, tokenIndex114, depth114 + l113: + position, tokenIndex, depth = position113, tokenIndex113, depth113 return false }, /* 31 Level0 <- <(IP / String / Number / Boolean / Undefined / Nil / Symbol / Not / Substitution / Merge / Auto / Lambda / Chained)> */ func() bool { - position116, tokenIndex116, depth116 := position, tokenIndex, depth + position115, tokenIndex115, depth115 := position, tokenIndex, depth { - position117 := position + position116 := position depth++ { - position118, tokenIndex118, depth118 := position, tokenIndex, depth + position117, tokenIndex117, depth117 := position, tokenIndex, depth if !_rules[ruleIP]() { + goto l118 + } + goto l117 + l118: + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleString]() { goto l119 } - goto l118 + goto l117 l119: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleString]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleNumber]() { goto l120 } - goto l118 + goto l117 l120: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleNumber]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleBoolean]() { goto l121 } - goto l118 + goto l117 l121: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleBoolean]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleUndefined]() { goto l122 } - goto l118 + goto l117 l122: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleUndefined]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleNil]() { goto l123 } - goto l118 + goto l117 l123: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleNil]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleSymbol]() { goto l124 } - goto l118 + goto l117 l124: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleSymbol]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleNot]() { goto l125 } - goto l118 + goto l117 l125: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleNot]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleSubstitution]() { goto l126 } - goto l118 + goto l117 l126: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleSubstitution]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleMerge]() { goto l127 } - goto l118 + goto l117 l127: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleMerge]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleAuto]() { goto l128 } - goto l118 + goto l117 l128: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleAuto]() { + position, tokenIndex, depth = position117, tokenIndex117, depth117 + if !_rules[ruleLambda]() { goto l129 } - goto l118 + goto l117 l129: - position, tokenIndex, depth = position118, tokenIndex118, depth118 - if !_rules[ruleLambda]() { - goto l130 - } - goto l118 - l130: - position, tokenIndex, depth = position118, tokenIndex118, depth118 + position, tokenIndex, depth = position117, tokenIndex117, depth117 if !_rules[ruleChained]() { - goto l116 + goto l115 } } - l118: + l117: depth-- - add(ruleLevel0, position117) + add(ruleLevel0, position116) } return true - l116: - position, tokenIndex, depth = position116, tokenIndex116, depth116 + l115: + position, tokenIndex, depth = position115, tokenIndex115, depth115 return false }, /* 32 Chained <- <((MapMapping / Sync / Catch / Mapping / MapSelection / Selection / Sum / List / Map / Range / Grouped / Reference) ChainedQualifiedExpression*)> */ func() bool { - position131, tokenIndex131, depth131 := position, tokenIndex, depth + position130, tokenIndex130, depth130 := position, tokenIndex, depth { - position132 := position + position131 := position depth++ { - position133, tokenIndex133, depth133 := position, tokenIndex, depth + position132, tokenIndex132, depth132 := position, tokenIndex, depth if !_rules[ruleMapMapping]() { + goto l133 + } + goto l132 + l133: + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleSync]() { goto l134 } - goto l133 + goto l132 l134: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleSync]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleCatch]() { goto l135 } - goto l133 + goto l132 l135: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleCatch]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleMapping]() { goto l136 } - goto l133 + goto l132 l136: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleMapping]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleMapSelection]() { goto l137 } - goto l133 + goto l132 l137: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleMapSelection]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleSelection]() { goto l138 } - goto l133 + goto l132 l138: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleSelection]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleSum]() { goto l139 } - goto l133 + goto l132 l139: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleSum]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleList]() { goto l140 } - goto l133 + goto l132 l140: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleList]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleMap]() { goto l141 } - goto l133 + goto l132 l141: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleMap]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleRange]() { goto l142 } - goto l133 + goto l132 l142: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleRange]() { + position, tokenIndex, depth = position132, tokenIndex132, depth132 + if !_rules[ruleGrouped]() { goto l143 } - goto l133 + goto l132 l143: - position, tokenIndex, depth = position133, tokenIndex133, depth133 - if !_rules[ruleGrouped]() { - goto l144 - } - goto l133 - l144: - position, tokenIndex, depth = position133, tokenIndex133, depth133 + position, tokenIndex, depth = position132, tokenIndex132, depth132 if !_rules[ruleReference]() { - goto l131 + goto l130 } } - l133: - l145: + l132: + l144: { - position146, tokenIndex146, depth146 := position, tokenIndex, depth + position145, tokenIndex145, depth145 := position, tokenIndex, depth if !_rules[ruleChainedQualifiedExpression]() { - goto l146 + goto l145 } - goto l145 - l146: - position, tokenIndex, depth = position146, tokenIndex146, depth146 + goto l144 + l145: + position, tokenIndex, depth = position145, tokenIndex145, depth145 } depth-- - add(ruleChained, position132) + add(ruleChained, position131) } return true - l131: - position, tokenIndex, depth = position131, tokenIndex131, depth131 + l130: + position, tokenIndex, depth = position130, tokenIndex130, depth130 return false }, /* 33 ChainedQualifiedExpression <- <(ChainedCall / Currying / ChainedRef / ChainedDynRef / Projection)> */ func() bool { - position147, tokenIndex147, depth147 := position, tokenIndex, depth + position146, tokenIndex146, depth146 := position, tokenIndex, depth { - position148 := position + position147 := position depth++ { - position149, tokenIndex149, depth149 := position, tokenIndex, depth + position148, tokenIndex148, depth148 := position, tokenIndex, depth if !_rules[ruleChainedCall]() { + goto l149 + } + goto l148 + l149: + position, tokenIndex, depth = position148, tokenIndex148, depth148 + if !_rules[ruleCurrying]() { goto l150 } - goto l149 + goto l148 l150: - position, tokenIndex, depth = position149, tokenIndex149, depth149 - if !_rules[ruleCurrying]() { + position, tokenIndex, depth = position148, tokenIndex148, depth148 + if !_rules[ruleChainedRef]() { goto l151 } - goto l149 + goto l148 l151: - position, tokenIndex, depth = position149, tokenIndex149, depth149 - if !_rules[ruleChainedRef]() { + position, tokenIndex, depth = position148, tokenIndex148, depth148 + if !_rules[ruleChainedDynRef]() { goto l152 } - goto l149 + goto l148 l152: - position, tokenIndex, depth = position149, tokenIndex149, depth149 - if !_rules[ruleChainedDynRef]() { - goto l153 - } - goto l149 - l153: - position, tokenIndex, depth = position149, tokenIndex149, depth149 + position, tokenIndex, depth = position148, tokenIndex148, depth148 if !_rules[ruleProjection]() { - goto l147 + goto l146 } } - l149: + l148: depth-- - add(ruleChainedQualifiedExpression, position148) + add(ruleChainedQualifiedExpression, position147) } return true - l147: - position, tokenIndex, depth = position147, tokenIndex147, depth147 + l146: + position, tokenIndex, depth = position146, tokenIndex146, depth146 return false }, /* 34 ChainedRef <- <(PathComponent FollowUpRef)> */ func() bool { - position154, tokenIndex154, depth154 := position, tokenIndex, depth + position153, tokenIndex153, depth153 := position, tokenIndex, depth { - position155 := position + position154 := position depth++ if !_rules[rulePathComponent]() { - goto l154 + goto l153 } if !_rules[ruleFollowUpRef]() { - goto l154 + goto l153 } depth-- - add(ruleChainedRef, position155) + add(ruleChainedRef, position154) } return true - l154: - position, tokenIndex, depth = position154, tokenIndex154, depth154 + l153: + position, tokenIndex, depth = position153, tokenIndex153, depth153 return false }, /* 35 ChainedDynRef <- <('.'? '[' Expression ']')> */ func() bool { - position156, tokenIndex156, depth156 := position, tokenIndex, depth + position155, tokenIndex155, depth155 := position, tokenIndex, depth { - position157 := position + position156 := position depth++ { - position158, tokenIndex158, depth158 := position, tokenIndex, depth + position157, tokenIndex157, depth157 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l158 + goto l157 } position++ - goto l159 - l158: - position, tokenIndex, depth = position158, tokenIndex158, depth158 + goto l158 + l157: + position, tokenIndex, depth = position157, tokenIndex157, depth157 } - l159: + l158: if buffer[position] != rune('[') { - goto l156 + goto l155 } position++ if !_rules[ruleExpression]() { - goto l156 + goto l155 } if buffer[position] != rune(']') { - goto l156 + goto l155 } position++ depth-- - add(ruleChainedDynRef, position157) + add(ruleChainedDynRef, position156) } return true - l156: - position, tokenIndex, depth = position156, tokenIndex156, depth156 + l155: + position, tokenIndex, depth = position155, tokenIndex155, depth155 return false }, /* 36 Slice <- */ func() bool { - position160, tokenIndex160, depth160 := position, tokenIndex, depth + position159, tokenIndex159, depth159 := position, tokenIndex, depth { - position161 := position + position160 := position depth++ if !_rules[ruleRange]() { - goto l160 + goto l159 } depth-- - add(ruleSlice, position161) + add(ruleSlice, position160) } return true - l160: - position, tokenIndex, depth = position160, tokenIndex160, depth160 + l159: + position, tokenIndex, depth = position159, tokenIndex159, depth159 return false }, /* 37 Currying <- <('*' ChainedCall)> */ func() bool { - position162, tokenIndex162, depth162 := position, tokenIndex, depth + position161, tokenIndex161, depth161 := position, tokenIndex, depth { - position163 := position + position162 := position depth++ if buffer[position] != rune('*') { - goto l162 + goto l161 } position++ if !_rules[ruleChainedCall]() { - goto l162 + goto l161 } depth-- - add(ruleCurrying, position163) + add(ruleCurrying, position162) } return true - l162: - position, tokenIndex, depth = position162, tokenIndex162, depth162 + l161: + position, tokenIndex, depth = position161, tokenIndex161, depth161 return false }, /* 38 ChainedCall <- <(StartArguments NameArgumentList? ')')> */ func() bool { - position164, tokenIndex164, depth164 := position, tokenIndex, depth + position163, tokenIndex163, depth163 := position, tokenIndex, depth { - position165 := position + position164 := position depth++ if !_rules[ruleStartArguments]() { - goto l164 + goto l163 } { - position166, tokenIndex166, depth166 := position, tokenIndex, depth + position165, tokenIndex165, depth165 := position, tokenIndex, depth if !_rules[ruleNameArgumentList]() { - goto l166 + goto l165 } - goto l167 - l166: - position, tokenIndex, depth = position166, tokenIndex166, depth166 + goto l166 + l165: + position, tokenIndex, depth = position165, tokenIndex165, depth165 } - l167: + l166: if buffer[position] != rune(')') { - goto l164 + goto l163 } position++ depth-- - add(ruleChainedCall, position165) + add(ruleChainedCall, position164) } return true - l164: - position, tokenIndex, depth = position164, tokenIndex164, depth164 + l163: + position, tokenIndex, depth = position163, tokenIndex163, depth163 return false }, /* 39 StartArguments <- <('(' ws)> */ func() bool { - position168, tokenIndex168, depth168 := position, tokenIndex, depth + position167, tokenIndex167, depth167 := position, tokenIndex, depth { - position169 := position + position168 := position depth++ if buffer[position] != rune('(') { - goto l168 + goto l167 } position++ if !_rules[rulews]() { - goto l168 + goto l167 } depth-- - add(ruleStartArguments, position169) + add(ruleStartArguments, position168) } return true - l168: - position, tokenIndex, depth = position168, tokenIndex168, depth168 + l167: + position, tokenIndex, depth = position167, tokenIndex167, depth167 return false }, /* 40 NameArgumentList <- <(((NextNameArgument (',' NextNameArgument)*) / NextExpression) (',' NextExpression)*)> */ func() bool { - position170, tokenIndex170, depth170 := position, tokenIndex, depth + position169, tokenIndex169, depth169 := position, tokenIndex, depth { - position171 := position + position170 := position depth++ { - position172, tokenIndex172, depth172 := position, tokenIndex, depth + position171, tokenIndex171, depth171 := position, tokenIndex, depth if !_rules[ruleNextNameArgument]() { - goto l173 + goto l172 } - l174: + l173: { - position175, tokenIndex175, depth175 := position, tokenIndex, depth + position174, tokenIndex174, depth174 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l175 + goto l174 } position++ if !_rules[ruleNextNameArgument]() { - goto l175 + goto l174 } - goto l174 - l175: - position, tokenIndex, depth = position175, tokenIndex175, depth175 + goto l173 + l174: + position, tokenIndex, depth = position174, tokenIndex174, depth174 } - goto l172 - l173: - position, tokenIndex, depth = position172, tokenIndex172, depth172 + goto l171 + l172: + position, tokenIndex, depth = position171, tokenIndex171, depth171 if !_rules[ruleNextExpression]() { - goto l170 + goto l169 } } - l172: - l176: + l171: + l175: { - position177, tokenIndex177, depth177 := position, tokenIndex, depth + position176, tokenIndex176, depth176 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l177 + goto l176 } position++ if !_rules[ruleNextExpression]() { - goto l177 + goto l176 } - goto l176 - l177: - position, tokenIndex, depth = position177, tokenIndex177, depth177 + goto l175 + l176: + position, tokenIndex, depth = position176, tokenIndex176, depth176 } depth-- - add(ruleNameArgumentList, position171) + add(ruleNameArgumentList, position170) } return true - l170: - position, tokenIndex, depth = position170, tokenIndex170, depth170 + l169: + position, tokenIndex, depth = position169, tokenIndex169, depth169 return false }, /* 41 NextNameArgument <- <(ws Name ws '=' ws Expression ws)> */ func() bool { - position178, tokenIndex178, depth178 := position, tokenIndex, depth + position177, tokenIndex177, depth177 := position, tokenIndex, depth { - position179 := position + position178 := position depth++ if !_rules[rulews]() { - goto l178 + goto l177 } if !_rules[ruleName]() { - goto l178 + goto l177 } if !_rules[rulews]() { - goto l178 + goto l177 } if buffer[position] != rune('=') { - goto l178 + goto l177 } position++ if !_rules[rulews]() { - goto l178 + goto l177 } if !_rules[ruleExpression]() { - goto l178 + goto l177 } if !_rules[rulews]() { - goto l178 + goto l177 } depth-- - add(ruleNextNameArgument, position179) + add(ruleNextNameArgument, position178) } return true - l178: - position, tokenIndex, depth = position178, tokenIndex178, depth178 + l177: + position, tokenIndex, depth = position177, tokenIndex177, depth177 return false }, /* 42 ExpressionList <- <(NextExpression (',' NextExpression)*)> */ func() bool { - position180, tokenIndex180, depth180 := position, tokenIndex, depth + position179, tokenIndex179, depth179 := position, tokenIndex, depth { - position181 := position + position180 := position depth++ if !_rules[ruleNextExpression]() { - goto l180 + goto l179 } - l182: + l181: { - position183, tokenIndex183, depth183 := position, tokenIndex, depth + position182, tokenIndex182, depth182 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l183 + goto l182 } position++ if !_rules[ruleNextExpression]() { - goto l183 + goto l182 } - goto l182 - l183: - position, tokenIndex, depth = position183, tokenIndex183, depth183 + goto l181 + l182: + position, tokenIndex, depth = position182, tokenIndex182, depth182 } depth-- - add(ruleExpressionList, position181) + add(ruleExpressionList, position180) } return true - l180: - position, tokenIndex, depth = position180, tokenIndex180, depth180 + l179: + position, tokenIndex, depth = position179, tokenIndex179, depth179 return false }, /* 43 NextExpression <- <(Expression ListExpansion?)> */ func() bool { - position184, tokenIndex184, depth184 := position, tokenIndex, depth + position183, tokenIndex183, depth183 := position, tokenIndex, depth { - position185 := position + position184 := position depth++ if !_rules[ruleExpression]() { - goto l184 + goto l183 } { - position186, tokenIndex186, depth186 := position, tokenIndex, depth + position185, tokenIndex185, depth185 := position, tokenIndex, depth if !_rules[ruleListExpansion]() { - goto l186 + goto l185 } - goto l187 - l186: - position, tokenIndex, depth = position186, tokenIndex186, depth186 + goto l186 + l185: + position, tokenIndex, depth = position185, tokenIndex185, depth185 } - l187: + l186: depth-- - add(ruleNextExpression, position185) + add(ruleNextExpression, position184) } return true - l184: - position, tokenIndex, depth = position184, tokenIndex184, depth184 + l183: + position, tokenIndex, depth = position183, tokenIndex183, depth183 return false }, /* 44 ListExpansion <- <('.' '.' '.' ws)> */ func() bool { - position188, tokenIndex188, depth188 := position, tokenIndex, depth + position187, tokenIndex187, depth187 := position, tokenIndex, depth { - position189 := position + position188 := position depth++ if buffer[position] != rune('.') { - goto l188 + goto l187 } position++ if buffer[position] != rune('.') { - goto l188 + goto l187 } position++ if buffer[position] != rune('.') { - goto l188 + goto l187 } position++ if !_rules[rulews]() { - goto l188 + goto l187 } depth-- - add(ruleListExpansion, position189) + add(ruleListExpansion, position188) } return true - l188: - position, tokenIndex, depth = position188, tokenIndex188, depth188 + l187: + position, tokenIndex, depth = position187, tokenIndex187, depth187 return false }, /* 45 Projection <- <('.'? (('[' '*' ']') / Slice) ProjectionValue ChainedQualifiedExpression*)> */ func() bool { - position190, tokenIndex190, depth190 := position, tokenIndex, depth + position189, tokenIndex189, depth189 := position, tokenIndex, depth { - position191 := position + position190 := position depth++ { - position192, tokenIndex192, depth192 := position, tokenIndex, depth + position191, tokenIndex191, depth191 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l192 + goto l191 } position++ - goto l193 - l192: - position, tokenIndex, depth = position192, tokenIndex192, depth192 + goto l192 + l191: + position, tokenIndex, depth = position191, tokenIndex191, depth191 } - l193: + l192: { - position194, tokenIndex194, depth194 := position, tokenIndex, depth + position193, tokenIndex193, depth193 := position, tokenIndex, depth if buffer[position] != rune('[') { - goto l195 + goto l194 } position++ if buffer[position] != rune('*') { - goto l195 + goto l194 } position++ if buffer[position] != rune(']') { - goto l195 + goto l194 } position++ - goto l194 - l195: - position, tokenIndex, depth = position194, tokenIndex194, depth194 + goto l193 + l194: + position, tokenIndex, depth = position193, tokenIndex193, depth193 if !_rules[ruleSlice]() { - goto l190 + goto l189 } } - l194: + l193: if !_rules[ruleProjectionValue]() { - goto l190 + goto l189 } - l196: + l195: { - position197, tokenIndex197, depth197 := position, tokenIndex, depth + position196, tokenIndex196, depth196 := position, tokenIndex, depth if !_rules[ruleChainedQualifiedExpression]() { - goto l197 + goto l196 } - goto l196 - l197: - position, tokenIndex, depth = position197, tokenIndex197, depth197 + goto l195 + l196: + position, tokenIndex, depth = position196, tokenIndex196, depth196 } depth-- - add(ruleProjection, position191) + add(ruleProjection, position190) } return true - l190: - position, tokenIndex, depth = position190, tokenIndex190, depth190 + l189: + position, tokenIndex, depth = position189, tokenIndex189, depth189 return false }, /* 46 ProjectionValue <- */ func() bool { - position198, tokenIndex198, depth198 := position, tokenIndex, depth + position197, tokenIndex197, depth197 := position, tokenIndex, depth { - position199 := position + position198 := position depth++ if !_rules[ruleAction0]() { - goto l198 + goto l197 } depth-- - add(ruleProjectionValue, position199) + add(ruleProjectionValue, position198) } return true - l198: - position, tokenIndex, depth = position198, tokenIndex198, depth198 + l197: + position, tokenIndex, depth = position197, tokenIndex197, depth197 return false }, /* 47 Substitution <- <('*' Level0)> */ func() bool { - position200, tokenIndex200, depth200 := position, tokenIndex, depth + position199, tokenIndex199, depth199 := position, tokenIndex, depth { - position201 := position + position200 := position depth++ if buffer[position] != rune('*') { - goto l200 + goto l199 } position++ if !_rules[ruleLevel0]() { - goto l200 + goto l199 } depth-- - add(ruleSubstitution, position201) + add(ruleSubstitution, position200) } return true - l200: - position, tokenIndex, depth = position200, tokenIndex200, depth200 + l199: + position, tokenIndex, depth = position199, tokenIndex199, depth199 return false }, /* 48 Not <- <('!' ws Level0)> */ func() bool { - position202, tokenIndex202, depth202 := position, tokenIndex, depth + position201, tokenIndex201, depth201 := position, tokenIndex, depth { - position203 := position + position202 := position depth++ if buffer[position] != rune('!') { - goto l202 + goto l201 } position++ if !_rules[rulews]() { - goto l202 + goto l201 } if !_rules[ruleLevel0]() { - goto l202 + goto l201 } depth-- - add(ruleNot, position203) + add(ruleNot, position202) } return true - l202: - position, tokenIndex, depth = position202, tokenIndex202, depth202 + l201: + position, tokenIndex, depth = position201, tokenIndex201, depth201 return false }, /* 49 Grouped <- <('(' Expression ')')> */ func() bool { - position204, tokenIndex204, depth204 := position, tokenIndex, depth + position203, tokenIndex203, depth203 := position, tokenIndex, depth { - position205 := position + position204 := position depth++ if buffer[position] != rune('(') { - goto l204 + goto l203 } position++ if !_rules[ruleExpression]() { - goto l204 + goto l203 } if buffer[position] != rune(')') { - goto l204 + goto l203 } position++ depth-- - add(ruleGrouped, position205) + add(ruleGrouped, position204) } return true - l204: - position, tokenIndex, depth = position204, tokenIndex204, depth204 + l203: + position, tokenIndex, depth = position203, tokenIndex203, depth203 return false }, /* 50 Range <- <(StartRange Expression? RangeOp Expression? ']')> */ func() bool { - position206, tokenIndex206, depth206 := position, tokenIndex, depth + position205, tokenIndex205, depth205 := position, tokenIndex, depth { - position207 := position + position206 := position depth++ if !_rules[ruleStartRange]() { - goto l206 + goto l205 } { - position208, tokenIndex208, depth208 := position, tokenIndex, depth + position207, tokenIndex207, depth207 := position, tokenIndex, depth if !_rules[ruleExpression]() { - goto l208 + goto l207 } - goto l209 - l208: - position, tokenIndex, depth = position208, tokenIndex208, depth208 + goto l208 + l207: + position, tokenIndex, depth = position207, tokenIndex207, depth207 } - l209: + l208: if !_rules[ruleRangeOp]() { - goto l206 + goto l205 } { - position210, tokenIndex210, depth210 := position, tokenIndex, depth + position209, tokenIndex209, depth209 := position, tokenIndex, depth if !_rules[ruleExpression]() { - goto l210 + goto l209 } - goto l211 - l210: - position, tokenIndex, depth = position210, tokenIndex210, depth210 + goto l210 + l209: + position, tokenIndex, depth = position209, tokenIndex209, depth209 } - l211: + l210: if buffer[position] != rune(']') { - goto l206 + goto l205 } position++ depth-- - add(ruleRange, position207) + add(ruleRange, position206) } return true - l206: - position, tokenIndex, depth = position206, tokenIndex206, depth206 + l205: + position, tokenIndex, depth = position205, tokenIndex205, depth205 return false }, /* 51 StartRange <- <'['> */ func() bool { - position212, tokenIndex212, depth212 := position, tokenIndex, depth + position211, tokenIndex211, depth211 := position, tokenIndex, depth { - position213 := position + position212 := position depth++ if buffer[position] != rune('[') { - goto l212 + goto l211 } position++ depth-- - add(ruleStartRange, position213) + add(ruleStartRange, position212) } return true - l212: - position, tokenIndex, depth = position212, tokenIndex212, depth212 + l211: + position, tokenIndex, depth = position211, tokenIndex211, depth211 return false }, /* 52 RangeOp <- <('.' '.')> */ func() bool { - position214, tokenIndex214, depth214 := position, tokenIndex, depth + position213, tokenIndex213, depth213 := position, tokenIndex, depth { - position215 := position + position214 := position depth++ if buffer[position] != rune('.') { - goto l214 + goto l213 } position++ if buffer[position] != rune('.') { - goto l214 + goto l213 } position++ depth-- - add(ruleRangeOp, position215) + add(ruleRangeOp, position214) } return true - l214: - position, tokenIndex, depth = position214, tokenIndex214, depth214 + l213: + position, tokenIndex, depth = position213, tokenIndex213, depth213 return false }, /* 53 Number <- <('-'? [0-9] ([0-9] / '_')* ('.' [0-9] [0-9]*)? (('e' / 'E') '-'? [0-9] [0-9]*)? !(':' ':'))> */ func() bool { - position216, tokenIndex216, depth216 := position, tokenIndex, depth + position215, tokenIndex215, depth215 := position, tokenIndex, depth { - position217 := position + position216 := position depth++ { - position218, tokenIndex218, depth218 := position, tokenIndex, depth + position217, tokenIndex217, depth217 := position, tokenIndex, depth if buffer[position] != rune('-') { - goto l218 + goto l217 } position++ - goto l219 - l218: - position, tokenIndex, depth = position218, tokenIndex218, depth218 + goto l218 + l217: + position, tokenIndex, depth = position217, tokenIndex217, depth217 } - l219: + l218: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l216 + goto l215 } position++ - l220: + l219: { - position221, tokenIndex221, depth221 := position, tokenIndex, depth + position220, tokenIndex220, depth220 := position, tokenIndex, depth { - position222, tokenIndex222, depth222 := position, tokenIndex, depth + position221, tokenIndex221, depth221 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l223 + goto l222 } position++ - goto l222 - l223: - position, tokenIndex, depth = position222, tokenIndex222, depth222 + goto l221 + l222: + position, tokenIndex, depth = position221, tokenIndex221, depth221 if buffer[position] != rune('_') { - goto l221 + goto l220 } position++ } - l222: - goto l220 l221: - position, tokenIndex, depth = position221, tokenIndex221, depth221 + goto l219 + l220: + position, tokenIndex, depth = position220, tokenIndex220, depth220 } { - position224, tokenIndex224, depth224 := position, tokenIndex, depth + position223, tokenIndex223, depth223 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l224 + goto l223 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l224 + goto l223 } position++ - l226: + l225: { - position227, tokenIndex227, depth227 := position, tokenIndex, depth + position226, tokenIndex226, depth226 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l227 + goto l226 } position++ - goto l226 - l227: - position, tokenIndex, depth = position227, tokenIndex227, depth227 + goto l225 + l226: + position, tokenIndex, depth = position226, tokenIndex226, depth226 } - goto l225 - l224: - position, tokenIndex, depth = position224, tokenIndex224, depth224 + goto l224 + l223: + position, tokenIndex, depth = position223, tokenIndex223, depth223 } - l225: + l224: { - position228, tokenIndex228, depth228 := position, tokenIndex, depth + position227, tokenIndex227, depth227 := position, tokenIndex, depth { - position230, tokenIndex230, depth230 := position, tokenIndex, depth + position229, tokenIndex229, depth229 := position, tokenIndex, depth if buffer[position] != rune('e') { - goto l231 + goto l230 } position++ - goto l230 - l231: - position, tokenIndex, depth = position230, tokenIndex230, depth230 + goto l229 + l230: + position, tokenIndex, depth = position229, tokenIndex229, depth229 if buffer[position] != rune('E') { - goto l228 + goto l227 } position++ } - l230: + l229: { - position232, tokenIndex232, depth232 := position, tokenIndex, depth + position231, tokenIndex231, depth231 := position, tokenIndex, depth if buffer[position] != rune('-') { - goto l232 + goto l231 } position++ - goto l233 - l232: - position, tokenIndex, depth = position232, tokenIndex232, depth232 + goto l232 + l231: + position, tokenIndex, depth = position231, tokenIndex231, depth231 } - l233: + l232: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l228 + goto l227 } position++ - l234: + l233: { - position235, tokenIndex235, depth235 := position, tokenIndex, depth + position234, tokenIndex234, depth234 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l235 + goto l234 } position++ - goto l234 - l235: - position, tokenIndex, depth = position235, tokenIndex235, depth235 + goto l233 + l234: + position, tokenIndex, depth = position234, tokenIndex234, depth234 } - goto l229 - l228: - position, tokenIndex, depth = position228, tokenIndex228, depth228 + goto l228 + l227: + position, tokenIndex, depth = position227, tokenIndex227, depth227 } - l229: + l228: { - position236, tokenIndex236, depth236 := position, tokenIndex, depth + position235, tokenIndex235, depth235 := position, tokenIndex, depth if buffer[position] != rune(':') { - goto l236 + goto l235 } position++ if buffer[position] != rune(':') { - goto l236 + goto l235 } position++ - goto l216 - l236: - position, tokenIndex, depth = position236, tokenIndex236, depth236 + goto l215 + l235: + position, tokenIndex, depth = position235, tokenIndex235, depth235 } depth-- - add(ruleNumber, position217) + add(ruleNumber, position216) } return true - l216: - position, tokenIndex, depth = position216, tokenIndex216, depth216 + l215: + position, tokenIndex, depth = position215, tokenIndex215, depth215 return false }, /* 54 String <- <('"' (('\\' '"') / (!'"' .))* '"')> */ func() bool { - position237, tokenIndex237, depth237 := position, tokenIndex, depth + position236, tokenIndex236, depth236 := position, tokenIndex, depth { - position238 := position + position237 := position depth++ if buffer[position] != rune('"') { - goto l237 + goto l236 } position++ - l239: + l238: { - position240, tokenIndex240, depth240 := position, tokenIndex, depth + position239, tokenIndex239, depth239 := position, tokenIndex, depth { - position241, tokenIndex241, depth241 := position, tokenIndex, depth + position240, tokenIndex240, depth240 := position, tokenIndex, depth if buffer[position] != rune('\\') { - goto l242 + goto l241 } position++ if buffer[position] != rune('"') { - goto l242 + goto l241 } position++ - goto l241 - l242: - position, tokenIndex, depth = position241, tokenIndex241, depth241 + goto l240 + l241: + position, tokenIndex, depth = position240, tokenIndex240, depth240 { - position243, tokenIndex243, depth243 := position, tokenIndex, depth + position242, tokenIndex242, depth242 := position, tokenIndex, depth if buffer[position] != rune('"') { - goto l243 + goto l242 } position++ - goto l240 - l243: - position, tokenIndex, depth = position243, tokenIndex243, depth243 + goto l239 + l242: + position, tokenIndex, depth = position242, tokenIndex242, depth242 } if !matchDot() { - goto l240 + goto l239 } } - l241: - goto l239 l240: - position, tokenIndex, depth = position240, tokenIndex240, depth240 + goto l238 + l239: + position, tokenIndex, depth = position239, tokenIndex239, depth239 } if buffer[position] != rune('"') { - goto l237 + goto l236 } position++ depth-- - add(ruleString, position238) + add(ruleString, position237) } return true - l237: - position, tokenIndex, depth = position237, tokenIndex237, depth237 + l236: + position, tokenIndex, depth = position236, tokenIndex236, depth236 return false }, /* 55 Boolean <- <(('t' 'r' 'u' 'e') / ('f' 'a' 'l' 's' 'e'))> */ func() bool { - position244, tokenIndex244, depth244 := position, tokenIndex, depth + position243, tokenIndex243, depth243 := position, tokenIndex, depth { - position245 := position + position244 := position depth++ { - position246, tokenIndex246, depth246 := position, tokenIndex, depth + position245, tokenIndex245, depth245 := position, tokenIndex, depth if buffer[position] != rune('t') { - goto l247 + goto l246 } position++ if buffer[position] != rune('r') { - goto l247 + goto l246 } position++ if buffer[position] != rune('u') { - goto l247 + goto l246 } position++ if buffer[position] != rune('e') { - goto l247 + goto l246 } position++ - goto l246 - l247: - position, tokenIndex, depth = position246, tokenIndex246, depth246 + goto l245 + l246: + position, tokenIndex, depth = position245, tokenIndex245, depth245 if buffer[position] != rune('f') { - goto l244 + goto l243 } position++ if buffer[position] != rune('a') { - goto l244 + goto l243 } position++ if buffer[position] != rune('l') { - goto l244 + goto l243 } position++ if buffer[position] != rune('s') { - goto l244 + goto l243 } position++ if buffer[position] != rune('e') { - goto l244 + goto l243 } position++ } - l246: + l245: depth-- - add(ruleBoolean, position245) + add(ruleBoolean, position244) } return true - l244: - position, tokenIndex, depth = position244, tokenIndex244, depth244 + l243: + position, tokenIndex, depth = position243, tokenIndex243, depth243 return false }, /* 56 Nil <- <(('n' 'i' 'l') / '~')> */ func() bool { - position248, tokenIndex248, depth248 := position, tokenIndex, depth + position247, tokenIndex247, depth247 := position, tokenIndex, depth { - position249 := position + position248 := position depth++ { - position250, tokenIndex250, depth250 := position, tokenIndex, depth + position249, tokenIndex249, depth249 := position, tokenIndex, depth if buffer[position] != rune('n') { - goto l251 + goto l250 } position++ if buffer[position] != rune('i') { - goto l251 + goto l250 } position++ if buffer[position] != rune('l') { - goto l251 + goto l250 } position++ - goto l250 - l251: - position, tokenIndex, depth = position250, tokenIndex250, depth250 + goto l249 + l250: + position, tokenIndex, depth = position249, tokenIndex249, depth249 if buffer[position] != rune('~') { - goto l248 + goto l247 } position++ } - l250: + l249: depth-- - add(ruleNil, position249) + add(ruleNil, position248) } return true - l248: - position, tokenIndex, depth = position248, tokenIndex248, depth248 + l247: + position, tokenIndex, depth = position247, tokenIndex247, depth247 return false }, /* 57 Undefined <- <('~' '~')> */ func() bool { - position252, tokenIndex252, depth252 := position, tokenIndex, depth + position251, tokenIndex251, depth251 := position, tokenIndex, depth { - position253 := position + position252 := position depth++ if buffer[position] != rune('~') { - goto l252 + goto l251 } position++ if buffer[position] != rune('~') { - goto l252 + goto l251 } position++ depth-- - add(ruleUndefined, position253) + add(ruleUndefined, position252) } return true - l252: - position, tokenIndex, depth = position252, tokenIndex252, depth252 + l251: + position, tokenIndex, depth = position251, tokenIndex251, depth251 return false }, /* 58 Symbol <- <('$' Name)> */ func() bool { - position254, tokenIndex254, depth254 := position, tokenIndex, depth + position253, tokenIndex253, depth253 := position, tokenIndex, depth { - position255 := position + position254 := position depth++ if buffer[position] != rune('$') { - goto l254 + goto l253 } position++ if !_rules[ruleName]() { - goto l254 + goto l253 } depth-- - add(ruleSymbol, position255) + add(ruleSymbol, position254) } return true - l254: - position, tokenIndex, depth = position254, tokenIndex254, depth254 + l253: + position, tokenIndex, depth = position253, tokenIndex253, depth253 return false }, /* 59 List <- <(StartList ExpressionList? ']')> */ func() bool { - position256, tokenIndex256, depth256 := position, tokenIndex, depth + position255, tokenIndex255, depth255 := position, tokenIndex, depth { - position257 := position + position256 := position depth++ if !_rules[ruleStartList]() { - goto l256 + goto l255 } { - position258, tokenIndex258, depth258 := position, tokenIndex, depth + position257, tokenIndex257, depth257 := position, tokenIndex, depth if !_rules[ruleExpressionList]() { - goto l258 + goto l257 } - goto l259 - l258: - position, tokenIndex, depth = position258, tokenIndex258, depth258 + goto l258 + l257: + position, tokenIndex, depth = position257, tokenIndex257, depth257 } - l259: + l258: if buffer[position] != rune(']') { - goto l256 + goto l255 } position++ depth-- - add(ruleList, position257) + add(ruleList, position256) } return true - l256: - position, tokenIndex, depth = position256, tokenIndex256, depth256 + l255: + position, tokenIndex, depth = position255, tokenIndex255, depth255 return false }, /* 60 StartList <- <('[' ws)> */ func() bool { - position260, tokenIndex260, depth260 := position, tokenIndex, depth + position259, tokenIndex259, depth259 := position, tokenIndex, depth { - position261 := position + position260 := position depth++ if buffer[position] != rune('[') { - goto l260 + goto l259 } position++ if !_rules[rulews]() { - goto l260 + goto l259 } depth-- - add(ruleStartList, position261) + add(ruleStartList, position260) } return true - l260: - position, tokenIndex, depth = position260, tokenIndex260, depth260 + l259: + position, tokenIndex, depth = position259, tokenIndex259, depth259 return false }, /* 61 Map <- <(CreateMap ws Assignments? '}')> */ func() bool { - position262, tokenIndex262, depth262 := position, tokenIndex, depth + position261, tokenIndex261, depth261 := position, tokenIndex, depth { - position263 := position + position262 := position depth++ if !_rules[ruleCreateMap]() { - goto l262 + goto l261 } if !_rules[rulews]() { - goto l262 + goto l261 } { - position264, tokenIndex264, depth264 := position, tokenIndex, depth + position263, tokenIndex263, depth263 := position, tokenIndex, depth if !_rules[ruleAssignments]() { - goto l264 + goto l263 } - goto l265 - l264: - position, tokenIndex, depth = position264, tokenIndex264, depth264 + goto l264 + l263: + position, tokenIndex, depth = position263, tokenIndex263, depth263 } - l265: + l264: if buffer[position] != rune('}') { - goto l262 + goto l261 } position++ depth-- - add(ruleMap, position263) + add(ruleMap, position262) } return true - l262: - position, tokenIndex, depth = position262, tokenIndex262, depth262 + l261: + position, tokenIndex, depth = position261, tokenIndex261, depth261 return false }, /* 62 CreateMap <- <'{'> */ func() bool { - position266, tokenIndex266, depth266 := position, tokenIndex, depth + position265, tokenIndex265, depth265 := position, tokenIndex, depth { - position267 := position + position266 := position depth++ if buffer[position] != rune('{') { - goto l266 + goto l265 } position++ depth-- - add(ruleCreateMap, position267) + add(ruleCreateMap, position266) } return true - l266: - position, tokenIndex, depth = position266, tokenIndex266, depth266 + l265: + position, tokenIndex, depth = position265, tokenIndex265, depth265 return false }, /* 63 Assignments <- <(Assignment (',' Assignment)*)> */ func() bool { - position268, tokenIndex268, depth268 := position, tokenIndex, depth + position267, tokenIndex267, depth267 := position, tokenIndex, depth { - position269 := position + position268 := position depth++ if !_rules[ruleAssignment]() { - goto l268 + goto l267 } - l270: + l269: { - position271, tokenIndex271, depth271 := position, tokenIndex, depth + position270, tokenIndex270, depth270 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l271 + goto l270 } position++ if !_rules[ruleAssignment]() { - goto l271 + goto l270 } - goto l270 - l271: - position, tokenIndex, depth = position271, tokenIndex271, depth271 + goto l269 + l270: + position, tokenIndex, depth = position270, tokenIndex270, depth270 } depth-- - add(ruleAssignments, position269) + add(ruleAssignments, position268) } return true - l268: - position, tokenIndex, depth = position268, tokenIndex268, depth268 + l267: + position, tokenIndex, depth = position267, tokenIndex267, depth267 return false }, /* 64 Assignment <- <(Expression '=' Expression)> */ func() bool { - position272, tokenIndex272, depth272 := position, tokenIndex, depth + position271, tokenIndex271, depth271 := position, tokenIndex, depth { - position273 := position + position272 := position depth++ if !_rules[ruleExpression]() { - goto l272 + goto l271 } if buffer[position] != rune('=') { - goto l272 + goto l271 } position++ if !_rules[ruleExpression]() { - goto l272 + goto l271 } depth-- - add(ruleAssignment, position273) + add(ruleAssignment, position272) } return true - l272: - position, tokenIndex, depth = position272, tokenIndex272, depth272 + l271: + position, tokenIndex, depth = position271, tokenIndex271, depth271 return false }, /* 65 Merge <- <(RefMerge / SimpleMerge)> */ func() bool { - position274, tokenIndex274, depth274 := position, tokenIndex, depth + position273, tokenIndex273, depth273 := position, tokenIndex, depth { - position275 := position + position274 := position depth++ { - position276, tokenIndex276, depth276 := position, tokenIndex, depth + position275, tokenIndex275, depth275 := position, tokenIndex, depth if !_rules[ruleRefMerge]() { - goto l277 + goto l276 } - goto l276 - l277: - position, tokenIndex, depth = position276, tokenIndex276, depth276 + goto l275 + l276: + position, tokenIndex, depth = position275, tokenIndex275, depth275 if !_rules[ruleSimpleMerge]() { - goto l274 + goto l273 } } - l276: + l275: depth-- - add(ruleMerge, position275) + add(ruleMerge, position274) } return true - l274: - position, tokenIndex, depth = position274, tokenIndex274, depth274 + l273: + position, tokenIndex, depth = position273, tokenIndex273, depth273 return false }, /* 66 RefMerge <- <('m' 'e' 'r' 'g' 'e' !(req_ws Required) (req_ws (Replace / On))? req_ws Reference)> */ func() bool { - position278, tokenIndex278, depth278 := position, tokenIndex, depth + position277, tokenIndex277, depth277 := position, tokenIndex, depth { - position279 := position + position278 := position depth++ if buffer[position] != rune('m') { - goto l278 + goto l277 } position++ if buffer[position] != rune('e') { - goto l278 + goto l277 } position++ if buffer[position] != rune('r') { - goto l278 + goto l277 } position++ if buffer[position] != rune('g') { - goto l278 + goto l277 } position++ if buffer[position] != rune('e') { - goto l278 + goto l277 } position++ { - position280, tokenIndex280, depth280 := position, tokenIndex, depth + position279, tokenIndex279, depth279 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l280 + goto l279 } if !_rules[ruleRequired]() { - goto l280 + goto l279 } - goto l278 - l280: - position, tokenIndex, depth = position280, tokenIndex280, depth280 + goto l277 + l279: + position, tokenIndex, depth = position279, tokenIndex279, depth279 } { - position281, tokenIndex281, depth281 := position, tokenIndex, depth + position280, tokenIndex280, depth280 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l281 + goto l280 } { - position283, tokenIndex283, depth283 := position, tokenIndex, depth + position282, tokenIndex282, depth282 := position, tokenIndex, depth if !_rules[ruleReplace]() { - goto l284 + goto l283 } - goto l283 - l284: - position, tokenIndex, depth = position283, tokenIndex283, depth283 + goto l282 + l283: + position, tokenIndex, depth = position282, tokenIndex282, depth282 if !_rules[ruleOn]() { - goto l281 + goto l280 } } - l283: - goto l282 - l281: - position, tokenIndex, depth = position281, tokenIndex281, depth281 + l282: + goto l281 + l280: + position, tokenIndex, depth = position280, tokenIndex280, depth280 } - l282: + l281: if !_rules[rulereq_ws]() { - goto l278 + goto l277 } if !_rules[ruleReference]() { - goto l278 + goto l277 } depth-- - add(ruleRefMerge, position279) + add(ruleRefMerge, position278) } return true - l278: - position, tokenIndex, depth = position278, tokenIndex278, depth278 + l277: + position, tokenIndex, depth = position277, tokenIndex277, depth277 return false }, /* 67 SimpleMerge <- <('m' 'e' 'r' 'g' 'e' !'(' (req_ws (Replace / Required / On))?)> */ func() bool { - position285, tokenIndex285, depth285 := position, tokenIndex, depth + position284, tokenIndex284, depth284 := position, tokenIndex, depth { - position286 := position + position285 := position depth++ if buffer[position] != rune('m') { - goto l285 + goto l284 } position++ if buffer[position] != rune('e') { - goto l285 + goto l284 } position++ if buffer[position] != rune('r') { - goto l285 + goto l284 } position++ if buffer[position] != rune('g') { - goto l285 + goto l284 } position++ if buffer[position] != rune('e') { - goto l285 + goto l284 } position++ { - position287, tokenIndex287, depth287 := position, tokenIndex, depth + position286, tokenIndex286, depth286 := position, tokenIndex, depth if buffer[position] != rune('(') { - goto l287 + goto l286 } position++ - goto l285 - l287: - position, tokenIndex, depth = position287, tokenIndex287, depth287 + goto l284 + l286: + position, tokenIndex, depth = position286, tokenIndex286, depth286 } { - position288, tokenIndex288, depth288 := position, tokenIndex, depth + position287, tokenIndex287, depth287 := position, tokenIndex, depth if !_rules[rulereq_ws]() { - goto l288 + goto l287 } { - position290, tokenIndex290, depth290 := position, tokenIndex, depth + position289, tokenIndex289, depth289 := position, tokenIndex, depth if !_rules[ruleReplace]() { - goto l291 + goto l290 } - goto l290 - l291: - position, tokenIndex, depth = position290, tokenIndex290, depth290 + goto l289 + l290: + position, tokenIndex, depth = position289, tokenIndex289, depth289 if !_rules[ruleRequired]() { - goto l292 + goto l291 } - goto l290 - l292: - position, tokenIndex, depth = position290, tokenIndex290, depth290 + goto l289 + l291: + position, tokenIndex, depth = position289, tokenIndex289, depth289 if !_rules[ruleOn]() { - goto l288 + goto l287 } } - l290: - goto l289 - l288: - position, tokenIndex, depth = position288, tokenIndex288, depth288 + l289: + goto l288 + l287: + position, tokenIndex, depth = position287, tokenIndex287, depth287 } - l289: + l288: depth-- - add(ruleSimpleMerge, position286) + add(ruleSimpleMerge, position285) } return true - l285: - position, tokenIndex, depth = position285, tokenIndex285, depth285 + l284: + position, tokenIndex, depth = position284, tokenIndex284, depth284 return false }, /* 68 Replace <- <('r' 'e' 'p' 'l' 'a' 'c' 'e')> */ func() bool { - position293, tokenIndex293, depth293 := position, tokenIndex, depth + position292, tokenIndex292, depth292 := position, tokenIndex, depth { - position294 := position + position293 := position depth++ if buffer[position] != rune('r') { - goto l293 + goto l292 } position++ if buffer[position] != rune('e') { - goto l293 + goto l292 } position++ if buffer[position] != rune('p') { - goto l293 + goto l292 } position++ if buffer[position] != rune('l') { - goto l293 + goto l292 } position++ if buffer[position] != rune('a') { - goto l293 + goto l292 } position++ if buffer[position] != rune('c') { - goto l293 + goto l292 } position++ if buffer[position] != rune('e') { - goto l293 + goto l292 } position++ depth-- - add(ruleReplace, position294) + add(ruleReplace, position293) } return true - l293: - position, tokenIndex, depth = position293, tokenIndex293, depth293 + l292: + position, tokenIndex, depth = position292, tokenIndex292, depth292 return false }, /* 69 Required <- <('r' 'e' 'q' 'u' 'i' 'r' 'e' 'd')> */ func() bool { - position295, tokenIndex295, depth295 := position, tokenIndex, depth + position294, tokenIndex294, depth294 := position, tokenIndex, depth { - position296 := position + position295 := position depth++ if buffer[position] != rune('r') { - goto l295 + goto l294 } position++ if buffer[position] != rune('e') { - goto l295 + goto l294 } position++ if buffer[position] != rune('q') { - goto l295 + goto l294 } position++ if buffer[position] != rune('u') { - goto l295 + goto l294 } position++ if buffer[position] != rune('i') { - goto l295 + goto l294 } position++ if buffer[position] != rune('r') { - goto l295 + goto l294 } position++ if buffer[position] != rune('e') { - goto l295 + goto l294 } position++ if buffer[position] != rune('d') { - goto l295 + goto l294 } position++ depth-- - add(ruleRequired, position296) + add(ruleRequired, position295) } return true - l295: - position, tokenIndex, depth = position295, tokenIndex295, depth295 + l294: + position, tokenIndex, depth = position294, tokenIndex294, depth294 return false }, /* 70 On <- <('o' 'n' req_ws Name)> */ func() bool { - position297, tokenIndex297, depth297 := position, tokenIndex, depth + position296, tokenIndex296, depth296 := position, tokenIndex, depth { - position298 := position + position297 := position depth++ if buffer[position] != rune('o') { - goto l297 + goto l296 } position++ if buffer[position] != rune('n') { - goto l297 + goto l296 } position++ if !_rules[rulereq_ws]() { - goto l297 + goto l296 } if !_rules[ruleName]() { - goto l297 + goto l296 } depth-- - add(ruleOn, position298) + add(ruleOn, position297) } return true - l297: - position, tokenIndex, depth = position297, tokenIndex297, depth297 + l296: + position, tokenIndex, depth = position296, tokenIndex296, depth296 return false }, /* 71 Auto <- <('a' 'u' 't' 'o')> */ func() bool { - position299, tokenIndex299, depth299 := position, tokenIndex, depth + position298, tokenIndex298, depth298 := position, tokenIndex, depth { - position300 := position + position299 := position depth++ if buffer[position] != rune('a') { - goto l299 + goto l298 } position++ if buffer[position] != rune('u') { - goto l299 + goto l298 } position++ if buffer[position] != rune('t') { - goto l299 + goto l298 } position++ if buffer[position] != rune('o') { - goto l299 + goto l298 } position++ depth-- - add(ruleAuto, position300) + add(ruleAuto, position299) } return true - l299: - position, tokenIndex, depth = position299, tokenIndex299, depth299 + l298: + position, tokenIndex, depth = position298, tokenIndex298, depth298 return false }, /* 72 Default <- */ func() bool { - position301, tokenIndex301, depth301 := position, tokenIndex, depth + position300, tokenIndex300, depth300 := position, tokenIndex, depth { - position302 := position + position301 := position depth++ if !_rules[ruleAction1]() { - goto l301 + goto l300 } depth-- - add(ruleDefault, position302) + add(ruleDefault, position301) } return true - l301: - position, tokenIndex, depth = position301, tokenIndex301, depth301 + l300: + position, tokenIndex, depth = position300, tokenIndex300, depth300 return false }, /* 73 Sync <- <('s' 'y' 'n' 'c' '[' Level7 ((((LambdaExpr LambdaExt) / (LambdaOrExpr LambdaOrExpr)) (('|' Expression) / Default)) / (LambdaOrExpr Default Default)) ']')> */ func() bool { - position303, tokenIndex303, depth303 := position, tokenIndex, depth + position302, tokenIndex302, depth302 := position, tokenIndex, depth { - position304 := position + position303 := position depth++ if buffer[position] != rune('s') { - goto l303 + goto l302 } position++ if buffer[position] != rune('y') { - goto l303 + goto l302 } position++ if buffer[position] != rune('n') { - goto l303 + goto l302 } position++ if buffer[position] != rune('c') { - goto l303 + goto l302 } position++ if buffer[position] != rune('[') { - goto l303 + goto l302 } position++ if !_rules[ruleLevel7]() { - goto l303 + goto l302 } { - position305, tokenIndex305, depth305 := position, tokenIndex, depth + position304, tokenIndex304, depth304 := position, tokenIndex, depth { - position307, tokenIndex307, depth307 := position, tokenIndex, depth + position306, tokenIndex306, depth306 := position, tokenIndex, depth if !_rules[ruleLambdaExpr]() { - goto l308 + goto l307 } if !_rules[ruleLambdaExt]() { - goto l308 + goto l307 } - goto l307 - l308: - position, tokenIndex, depth = position307, tokenIndex307, depth307 + goto l306 + l307: + position, tokenIndex, depth = position306, tokenIndex306, depth306 if !_rules[ruleLambdaOrExpr]() { - goto l306 + goto l305 } if !_rules[ruleLambdaOrExpr]() { - goto l306 + goto l305 } } - l307: + l306: { - position309, tokenIndex309, depth309 := position, tokenIndex, depth + position308, tokenIndex308, depth308 := position, tokenIndex, depth if buffer[position] != rune('|') { - goto l310 + goto l309 } position++ if !_rules[ruleExpression]() { - goto l310 + goto l309 } - goto l309 - l310: - position, tokenIndex, depth = position309, tokenIndex309, depth309 + goto l308 + l309: + position, tokenIndex, depth = position308, tokenIndex308, depth308 if !_rules[ruleDefault]() { - goto l306 + goto l305 } } - l309: - goto l305 - l306: - position, tokenIndex, depth = position305, tokenIndex305, depth305 + l308: + goto l304 + l305: + position, tokenIndex, depth = position304, tokenIndex304, depth304 if !_rules[ruleLambdaOrExpr]() { - goto l303 + goto l302 } if !_rules[ruleDefault]() { - goto l303 + goto l302 } if !_rules[ruleDefault]() { - goto l303 + goto l302 } } - l305: + l304: if buffer[position] != rune(']') { - goto l303 + goto l302 } position++ depth-- - add(ruleSync, position304) + add(ruleSync, position303) } return true - l303: - position, tokenIndex, depth = position303, tokenIndex303, depth303 + l302: + position, tokenIndex, depth = position302, tokenIndex302, depth302 return false }, /* 74 LambdaExt <- <(',' Expression)> */ func() bool { - position311, tokenIndex311, depth311 := position, tokenIndex, depth + position310, tokenIndex310, depth310 := position, tokenIndex, depth { - position312 := position + position311 := position depth++ if buffer[position] != rune(',') { - goto l311 + goto l310 } position++ if !_rules[ruleExpression]() { - goto l311 + goto l310 } depth-- - add(ruleLambdaExt, position312) + add(ruleLambdaExt, position311) } return true - l311: - position, tokenIndex, depth = position311, tokenIndex311, depth311 + l310: + position, tokenIndex, depth = position310, tokenIndex310, depth310 return false }, /* 75 LambdaOrExpr <- <(LambdaExpr / ('|' Expression))> */ func() bool { - position313, tokenIndex313, depth313 := position, tokenIndex, depth + position312, tokenIndex312, depth312 := position, tokenIndex, depth { - position314 := position + position313 := position depth++ { - position315, tokenIndex315, depth315 := position, tokenIndex, depth + position314, tokenIndex314, depth314 := position, tokenIndex, depth if !_rules[ruleLambdaExpr]() { - goto l316 + goto l315 } - goto l315 - l316: - position, tokenIndex, depth = position315, tokenIndex315, depth315 + goto l314 + l315: + position, tokenIndex, depth = position314, tokenIndex314, depth314 if buffer[position] != rune('|') { - goto l313 + goto l312 } position++ if !_rules[ruleExpression]() { - goto l313 + goto l312 } } - l315: + l314: depth-- - add(ruleLambdaOrExpr, position314) + add(ruleLambdaOrExpr, position313) } return true - l313: - position, tokenIndex, depth = position313, tokenIndex313, depth313 + l312: + position, tokenIndex, depth = position312, tokenIndex312, depth312 return false }, /* 76 Catch <- <('c' 'a' 't' 'c' 'h' '[' Level7 LambdaOrExpr ']')> */ func() bool { - position317, tokenIndex317, depth317 := position, tokenIndex, depth + position316, tokenIndex316, depth316 := position, tokenIndex, depth { - position318 := position + position317 := position depth++ if buffer[position] != rune('c') { - goto l317 + goto l316 } position++ if buffer[position] != rune('a') { - goto l317 + goto l316 } position++ if buffer[position] != rune('t') { - goto l317 + goto l316 } position++ if buffer[position] != rune('c') { - goto l317 + goto l316 } position++ if buffer[position] != rune('h') { - goto l317 + goto l316 } position++ if buffer[position] != rune('[') { - goto l317 + goto l316 } position++ if !_rules[ruleLevel7]() { - goto l317 + goto l316 } if !_rules[ruleLambdaOrExpr]() { - goto l317 + goto l316 } if buffer[position] != rune(']') { - goto l317 + goto l316 } position++ depth-- - add(ruleCatch, position318) + add(ruleCatch, position317) } return true - l317: - position, tokenIndex, depth = position317, tokenIndex317, depth317 + l316: + position, tokenIndex, depth = position316, tokenIndex316, depth316 return false }, /* 77 MapMapping <- <('m' 'a' 'p' '{' Level7 LambdaOrExpr '}')> */ func() bool { - position319, tokenIndex319, depth319 := position, tokenIndex, depth + position318, tokenIndex318, depth318 := position, tokenIndex, depth { - position320 := position + position319 := position depth++ if buffer[position] != rune('m') { - goto l319 + goto l318 } position++ if buffer[position] != rune('a') { - goto l319 + goto l318 } position++ if buffer[position] != rune('p') { - goto l319 + goto l318 } position++ if buffer[position] != rune('{') { - goto l319 + goto l318 } position++ if !_rules[ruleLevel7]() { - goto l319 + goto l318 } if !_rules[ruleLambdaOrExpr]() { - goto l319 + goto l318 } if buffer[position] != rune('}') { - goto l319 + goto l318 } position++ depth-- - add(ruleMapMapping, position320) + add(ruleMapMapping, position319) } return true - l319: - position, tokenIndex, depth = position319, tokenIndex319, depth319 + l318: + position, tokenIndex, depth = position318, tokenIndex318, depth318 return false }, /* 78 Mapping <- <('m' 'a' 'p' '[' Level7 LambdaOrExpr ']')> */ func() bool { - position321, tokenIndex321, depth321 := position, tokenIndex, depth + position320, tokenIndex320, depth320 := position, tokenIndex, depth { - position322 := position + position321 := position depth++ if buffer[position] != rune('m') { - goto l321 + goto l320 } position++ if buffer[position] != rune('a') { - goto l321 + goto l320 } position++ if buffer[position] != rune('p') { - goto l321 + goto l320 } position++ if buffer[position] != rune('[') { - goto l321 + goto l320 } position++ if !_rules[ruleLevel7]() { - goto l321 + goto l320 } if !_rules[ruleLambdaOrExpr]() { - goto l321 + goto l320 } if buffer[position] != rune(']') { - goto l321 + goto l320 } position++ depth-- - add(ruleMapping, position322) + add(ruleMapping, position321) } return true - l321: - position, tokenIndex, depth = position321, tokenIndex321, depth321 + l320: + position, tokenIndex, depth = position320, tokenIndex320, depth320 return false }, /* 79 MapSelection <- <('s' 'e' 'l' 'e' 'c' 't' '{' Level7 LambdaOrExpr '}')> */ func() bool { - position323, tokenIndex323, depth323 := position, tokenIndex, depth + position322, tokenIndex322, depth322 := position, tokenIndex, depth { - position324 := position + position323 := position depth++ if buffer[position] != rune('s') { - goto l323 + goto l322 } position++ if buffer[position] != rune('e') { - goto l323 + goto l322 } position++ if buffer[position] != rune('l') { - goto l323 + goto l322 } position++ if buffer[position] != rune('e') { - goto l323 + goto l322 } position++ if buffer[position] != rune('c') { - goto l323 + goto l322 } position++ if buffer[position] != rune('t') { - goto l323 + goto l322 } position++ if buffer[position] != rune('{') { - goto l323 + goto l322 } position++ if !_rules[ruleLevel7]() { - goto l323 + goto l322 } if !_rules[ruleLambdaOrExpr]() { - goto l323 + goto l322 } if buffer[position] != rune('}') { - goto l323 + goto l322 } position++ depth-- - add(ruleMapSelection, position324) + add(ruleMapSelection, position323) } return true - l323: - position, tokenIndex, depth = position323, tokenIndex323, depth323 + l322: + position, tokenIndex, depth = position322, tokenIndex322, depth322 return false }, /* 80 Selection <- <('s' 'e' 'l' 'e' 'c' 't' '[' Level7 LambdaOrExpr ']')> */ func() bool { - position325, tokenIndex325, depth325 := position, tokenIndex, depth + position324, tokenIndex324, depth324 := position, tokenIndex, depth { - position326 := position + position325 := position depth++ if buffer[position] != rune('s') { - goto l325 + goto l324 } position++ if buffer[position] != rune('e') { - goto l325 + goto l324 } position++ if buffer[position] != rune('l') { - goto l325 + goto l324 } position++ if buffer[position] != rune('e') { - goto l325 + goto l324 } position++ if buffer[position] != rune('c') { - goto l325 + goto l324 } position++ if buffer[position] != rune('t') { - goto l325 + goto l324 } position++ if buffer[position] != rune('[') { - goto l325 + goto l324 } position++ if !_rules[ruleLevel7]() { - goto l325 + goto l324 } if !_rules[ruleLambdaOrExpr]() { - goto l325 + goto l324 } if buffer[position] != rune(']') { - goto l325 + goto l324 } position++ depth-- - add(ruleSelection, position326) + add(ruleSelection, position325) } return true - l325: - position, tokenIndex, depth = position325, tokenIndex325, depth325 + l324: + position, tokenIndex, depth = position324, tokenIndex324, depth324 return false }, /* 81 Sum <- <('s' 'u' 'm' '[' Level7 '|' Level7 LambdaOrExpr ']')> */ func() bool { - position327, tokenIndex327, depth327 := position, tokenIndex, depth + position326, tokenIndex326, depth326 := position, tokenIndex, depth { - position328 := position + position327 := position depth++ if buffer[position] != rune('s') { - goto l327 + goto l326 } position++ if buffer[position] != rune('u') { - goto l327 + goto l326 } position++ if buffer[position] != rune('m') { - goto l327 + goto l326 } position++ if buffer[position] != rune('[') { - goto l327 + goto l326 } position++ if !_rules[ruleLevel7]() { - goto l327 + goto l326 } if buffer[position] != rune('|') { - goto l327 + goto l326 } position++ if !_rules[ruleLevel7]() { - goto l327 + goto l326 } if !_rules[ruleLambdaOrExpr]() { - goto l327 + goto l326 } if buffer[position] != rune(']') { - goto l327 + goto l326 } position++ depth-- - add(ruleSum, position328) + add(ruleSum, position327) } return true - l327: - position, tokenIndex, depth = position327, tokenIndex327, depth327 + l326: + position, tokenIndex, depth = position326, tokenIndex326, depth326 return false }, /* 82 Lambda <- <('l' 'a' 'm' 'b' 'd' 'a' (LambdaRef / LambdaExpr))> */ func() bool { - position329, tokenIndex329, depth329 := position, tokenIndex, depth + position328, tokenIndex328, depth328 := position, tokenIndex, depth { - position330 := position + position329 := position depth++ if buffer[position] != rune('l') { - goto l329 + goto l328 } position++ if buffer[position] != rune('a') { - goto l329 + goto l328 } position++ if buffer[position] != rune('m') { - goto l329 + goto l328 } position++ if buffer[position] != rune('b') { - goto l329 + goto l328 } position++ if buffer[position] != rune('d') { - goto l329 + goto l328 } position++ if buffer[position] != rune('a') { - goto l329 + goto l328 } position++ { - position331, tokenIndex331, depth331 := position, tokenIndex, depth + position330, tokenIndex330, depth330 := position, tokenIndex, depth if !_rules[ruleLambdaRef]() { - goto l332 + goto l331 } - goto l331 - l332: - position, tokenIndex, depth = position331, tokenIndex331, depth331 + goto l330 + l331: + position, tokenIndex, depth = position330, tokenIndex330, depth330 if !_rules[ruleLambdaExpr]() { - goto l329 + goto l328 } } - l331: + l330: depth-- - add(ruleLambda, position330) + add(ruleLambda, position329) } return true - l329: - position, tokenIndex, depth = position329, tokenIndex329, depth329 + l328: + position, tokenIndex, depth = position328, tokenIndex328, depth328 return false }, /* 83 LambdaRef <- <(req_ws Expression)> */ func() bool { - position333, tokenIndex333, depth333 := position, tokenIndex, depth + position332, tokenIndex332, depth332 := position, tokenIndex, depth { - position334 := position + position333 := position depth++ if !_rules[rulereq_ws]() { - goto l333 + goto l332 } if !_rules[ruleExpression]() { - goto l333 + goto l332 } depth-- - add(ruleLambdaRef, position334) + add(ruleLambdaRef, position333) } return true - l333: - position, tokenIndex, depth = position333, tokenIndex333, depth333 + l332: + position, tokenIndex, depth = position332, tokenIndex332, depth332 return false }, /* 84 LambdaExpr <- <(ws Params ws ('-' '>') Expression)> */ func() bool { - position335, tokenIndex335, depth335 := position, tokenIndex, depth + position334, tokenIndex334, depth334 := position, tokenIndex, depth { - position336 := position + position335 := position depth++ if !_rules[rulews]() { - goto l335 + goto l334 } if !_rules[ruleParams]() { - goto l335 + goto l334 } if !_rules[rulews]() { - goto l335 + goto l334 } if buffer[position] != rune('-') { - goto l335 + goto l334 } position++ if buffer[position] != rune('>') { - goto l335 + goto l334 } position++ if !_rules[ruleExpression]() { - goto l335 + goto l334 } depth-- - add(ruleLambdaExpr, position336) + add(ruleLambdaExpr, position335) } return true - l335: - position, tokenIndex, depth = position335, tokenIndex335, depth335 + l334: + position, tokenIndex, depth = position334, tokenIndex334, depth334 return false }, /* 85 Params <- <('|' StartParams ws Names? '|')> */ func() bool { - position337, tokenIndex337, depth337 := position, tokenIndex, depth + position336, tokenIndex336, depth336 := position, tokenIndex, depth { - position338 := position + position337 := position depth++ if buffer[position] != rune('|') { - goto l337 + goto l336 } position++ if !_rules[ruleStartParams]() { - goto l337 + goto l336 } if !_rules[rulews]() { - goto l337 + goto l336 } { - position339, tokenIndex339, depth339 := position, tokenIndex, depth + position338, tokenIndex338, depth338 := position, tokenIndex, depth if !_rules[ruleNames]() { - goto l339 + goto l338 } - goto l340 - l339: - position, tokenIndex, depth = position339, tokenIndex339, depth339 + goto l339 + l338: + position, tokenIndex, depth = position338, tokenIndex338, depth338 } - l340: + l339: if buffer[position] != rune('|') { - goto l337 + goto l336 } position++ depth-- - add(ruleParams, position338) + add(ruleParams, position337) } return true - l337: - position, tokenIndex, depth = position337, tokenIndex337, depth337 + l336: + position, tokenIndex, depth = position336, tokenIndex336, depth336 return false }, /* 86 StartParams <- */ func() bool { - position341, tokenIndex341, depth341 := position, tokenIndex, depth + position340, tokenIndex340, depth340 := position, tokenIndex, depth { - position342 := position + position341 := position depth++ if !_rules[ruleAction2]() { - goto l341 + goto l340 } depth-- - add(ruleStartParams, position342) + add(ruleStartParams, position341) } return true - l341: - position, tokenIndex, depth = position341, tokenIndex341, depth341 + l340: + position, tokenIndex, depth = position340, tokenIndex340, depth340 return false }, /* 87 Names <- <(NextName (',' NextName)* DefaultValue? (',' NextName DefaultValue)* VarParams?)> */ func() bool { - position343, tokenIndex343, depth343 := position, tokenIndex, depth + position342, tokenIndex342, depth342 := position, tokenIndex, depth { - position344 := position + position343 := position depth++ if !_rules[ruleNextName]() { - goto l343 + goto l342 } - l345: + l344: { - position346, tokenIndex346, depth346 := position, tokenIndex, depth + position345, tokenIndex345, depth345 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l346 + goto l345 } position++ if !_rules[ruleNextName]() { - goto l346 + goto l345 } - goto l345 - l346: - position, tokenIndex, depth = position346, tokenIndex346, depth346 + goto l344 + l345: + position, tokenIndex, depth = position345, tokenIndex345, depth345 } { - position347, tokenIndex347, depth347 := position, tokenIndex, depth + position346, tokenIndex346, depth346 := position, tokenIndex, depth if !_rules[ruleDefaultValue]() { - goto l347 + goto l346 } - goto l348 - l347: - position, tokenIndex, depth = position347, tokenIndex347, depth347 + goto l347 + l346: + position, tokenIndex, depth = position346, tokenIndex346, depth346 } + l347: l348: - l349: { - position350, tokenIndex350, depth350 := position, tokenIndex, depth + position349, tokenIndex349, depth349 := position, tokenIndex, depth if buffer[position] != rune(',') { - goto l350 + goto l349 } position++ if !_rules[ruleNextName]() { - goto l350 + goto l349 } if !_rules[ruleDefaultValue]() { - goto l350 + goto l349 } - goto l349 - l350: - position, tokenIndex, depth = position350, tokenIndex350, depth350 + goto l348 + l349: + position, tokenIndex, depth = position349, tokenIndex349, depth349 } { - position351, tokenIndex351, depth351 := position, tokenIndex, depth + position350, tokenIndex350, depth350 := position, tokenIndex, depth if !_rules[ruleVarParams]() { - goto l351 + goto l350 } - goto l352 - l351: - position, tokenIndex, depth = position351, tokenIndex351, depth351 + goto l351 + l350: + position, tokenIndex, depth = position350, tokenIndex350, depth350 } - l352: + l351: depth-- - add(ruleNames, position344) + add(ruleNames, position343) } return true - l343: - position, tokenIndex, depth = position343, tokenIndex343, depth343 + l342: + position, tokenIndex, depth = position342, tokenIndex342, depth342 return false }, /* 88 NextName <- <(ws Name ws)> */ func() bool { - position353, tokenIndex353, depth353 := position, tokenIndex, depth + position352, tokenIndex352, depth352 := position, tokenIndex, depth { - position354 := position + position353 := position depth++ if !_rules[rulews]() { - goto l353 + goto l352 } if !_rules[ruleName]() { - goto l353 + goto l352 } if !_rules[rulews]() { - goto l353 + goto l352 } depth-- - add(ruleNextName, position354) + add(ruleNextName, position353) } return true - l353: - position, tokenIndex, depth = position353, tokenIndex353, depth353 + l352: + position, tokenIndex, depth = position352, tokenIndex352, depth352 return false }, /* 89 Name <- <([a-z] / [A-Z] / [0-9] / '_')+> */ func() bool { - position355, tokenIndex355, depth355 := position, tokenIndex, depth + position354, tokenIndex354, depth354 := position, tokenIndex, depth { - position356 := position + position355 := position depth++ { - position359, tokenIndex359, depth359 := position, tokenIndex, depth + position358, tokenIndex358, depth358 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l360 + goto l359 } position++ - goto l359 - l360: - position, tokenIndex, depth = position359, tokenIndex359, depth359 + goto l358 + l359: + position, tokenIndex, depth = position358, tokenIndex358, depth358 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l361 + goto l360 } position++ - goto l359 - l361: - position, tokenIndex, depth = position359, tokenIndex359, depth359 + goto l358 + l360: + position, tokenIndex, depth = position358, tokenIndex358, depth358 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l362 + goto l361 } position++ - goto l359 - l362: - position, tokenIndex, depth = position359, tokenIndex359, depth359 + goto l358 + l361: + position, tokenIndex, depth = position358, tokenIndex358, depth358 if buffer[position] != rune('_') { - goto l355 + goto l354 } position++ } - l359: - l357: + l358: + l356: { - position358, tokenIndex358, depth358 := position, tokenIndex, depth + position357, tokenIndex357, depth357 := position, tokenIndex, depth { - position363, tokenIndex363, depth363 := position, tokenIndex, depth + position362, tokenIndex362, depth362 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l364 + goto l363 } position++ - goto l363 - l364: - position, tokenIndex, depth = position363, tokenIndex363, depth363 + goto l362 + l363: + position, tokenIndex, depth = position362, tokenIndex362, depth362 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l365 + goto l364 } position++ - goto l363 - l365: - position, tokenIndex, depth = position363, tokenIndex363, depth363 + goto l362 + l364: + position, tokenIndex, depth = position362, tokenIndex362, depth362 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l366 + goto l365 } position++ - goto l363 - l366: - position, tokenIndex, depth = position363, tokenIndex363, depth363 + goto l362 + l365: + position, tokenIndex, depth = position362, tokenIndex362, depth362 if buffer[position] != rune('_') { - goto l358 + goto l357 } position++ } - l363: - goto l357 - l358: - position, tokenIndex, depth = position358, tokenIndex358, depth358 + l362: + goto l356 + l357: + position, tokenIndex, depth = position357, tokenIndex357, depth357 } depth-- - add(ruleName, position356) + add(ruleName, position355) } return true - l355: - position, tokenIndex, depth = position355, tokenIndex355, depth355 + l354: + position, tokenIndex, depth = position354, tokenIndex354, depth354 return false }, /* 90 DefaultValue <- <('=' Expression)> */ func() bool { - position367, tokenIndex367, depth367 := position, tokenIndex, depth + position366, tokenIndex366, depth366 := position, tokenIndex, depth { - position368 := position + position367 := position depth++ if buffer[position] != rune('=') { - goto l367 + goto l366 } position++ if !_rules[ruleExpression]() { - goto l367 + goto l366 } depth-- - add(ruleDefaultValue, position368) + add(ruleDefaultValue, position367) } return true - l367: - position, tokenIndex, depth = position367, tokenIndex367, depth367 + l366: + position, tokenIndex, depth = position366, tokenIndex366, depth366 return false }, /* 91 VarParams <- <('.' '.' '.' ws)> */ func() bool { - position369, tokenIndex369, depth369 := position, tokenIndex, depth + position368, tokenIndex368, depth368 := position, tokenIndex, depth { - position370 := position + position369 := position depth++ if buffer[position] != rune('.') { - goto l369 + goto l368 } position++ if buffer[position] != rune('.') { - goto l369 + goto l368 } position++ if buffer[position] != rune('.') { - goto l369 + goto l368 } position++ if !_rules[rulews]() { - goto l369 + goto l368 } depth-- - add(ruleVarParams, position370) + add(ruleVarParams, position369) } return true - l369: - position, tokenIndex, depth = position369, tokenIndex369, depth369 + l368: + position, tokenIndex, depth = position368, tokenIndex368, depth368 return false }, - /* 92 Reference <- <(((Tag ('.' / Key)) / ('.'? Key)) FollowUpRef)> */ + /* 92 Reference <- <(((TagPrefix ('.' / Key)) / ('.'? Key)) FollowUpRef)> */ func() bool { - position371, tokenIndex371, depth371 := position, tokenIndex, depth + position370, tokenIndex370, depth370 := position, tokenIndex, depth { - position372 := position + position371 := position depth++ { - position373, tokenIndex373, depth373 := position, tokenIndex, depth - if !_rules[ruleTag]() { - goto l374 + position372, tokenIndex372, depth372 := position, tokenIndex, depth + if !_rules[ruleTagPrefix]() { + goto l373 } { - position375, tokenIndex375, depth375 := position, tokenIndex, depth + position374, tokenIndex374, depth374 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l376 + goto l375 } position++ - goto l375 - l376: - position, tokenIndex, depth = position375, tokenIndex375, depth375 + goto l374 + l375: + position, tokenIndex, depth = position374, tokenIndex374, depth374 if !_rules[ruleKey]() { - goto l374 + goto l373 } } - l375: - goto l373 l374: - position, tokenIndex, depth = position373, tokenIndex373, depth373 + goto l372 + l373: + position, tokenIndex, depth = position372, tokenIndex372, depth372 { - position377, tokenIndex377, depth377 := position, tokenIndex, depth + position376, tokenIndex376, depth376 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l377 + goto l376 } position++ - goto l378 - l377: - position, tokenIndex, depth = position377, tokenIndex377, depth377 + goto l377 + l376: + position, tokenIndex, depth = position376, tokenIndex376, depth376 } - l378: + l377: if !_rules[ruleKey]() { - goto l371 + goto l370 } } - l373: + l372: if !_rules[ruleFollowUpRef]() { - goto l371 + goto l370 } depth-- - add(ruleReference, position372) + add(ruleReference, position371) } return true - l371: - position, tokenIndex, depth = position371, tokenIndex371, depth371 + l370: + position, tokenIndex, depth = position370, tokenIndex370, depth370 return false }, - /* 93 Tag <- <((('d' 'o' 'c' ':' '-'? [0-9]+) / (TagName (':' TagName)*)) (':' ':'))> */ + /* 93 TagPrefix <- <((('d' 'o' 'c' ('.' / ':') '-'? [0-9]+) / Tag) (':' ':'))> */ func() bool { - position379, tokenIndex379, depth379 := position, tokenIndex, depth + position378, tokenIndex378, depth378 := position, tokenIndex, depth { - position380 := position + position379 := position depth++ { - position381, tokenIndex381, depth381 := position, tokenIndex, depth + position380, tokenIndex380, depth380 := position, tokenIndex, depth if buffer[position] != rune('d') { - goto l382 + goto l381 } position++ if buffer[position] != rune('o') { - goto l382 + goto l381 } position++ if buffer[position] != rune('c') { - goto l382 - } - position++ - if buffer[position] != rune(':') { - goto l382 + goto l381 } position++ { - position383, tokenIndex383, depth383 := position, tokenIndex, depth - if buffer[position] != rune('-') { + position382, tokenIndex382, depth382 := position, tokenIndex, depth + if buffer[position] != rune('.') { goto l383 } position++ - goto l384 - l383: - position, tokenIndex, depth = position383, tokenIndex383, depth383 - } - l384: - if c := buffer[position]; c < rune('0') || c > rune('9') { goto l382 + l383: + position, tokenIndex, depth = position382, tokenIndex382, depth382 + if buffer[position] != rune(':') { + goto l381 + } + position++ } - position++ - l385: + l382: { - position386, tokenIndex386, depth386 := position, tokenIndex, depth - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l386 + position384, tokenIndex384, depth384 := position, tokenIndex, depth + if buffer[position] != rune('-') { + goto l384 } position++ goto l385 - l386: - position, tokenIndex, depth = position386, tokenIndex386, depth386 + l384: + position, tokenIndex, depth = position384, tokenIndex384, depth384 } - goto l381 - l382: - position, tokenIndex, depth = position381, tokenIndex381, depth381 - if !_rules[ruleTagName]() { - goto l379 + l385: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l381 } - l387: + position++ + l386: { - position388, tokenIndex388, depth388 := position, tokenIndex, depth - if buffer[position] != rune(':') { - goto l388 + position387, tokenIndex387, depth387 := position, tokenIndex, depth + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l387 } position++ - if !_rules[ruleTagName]() { - goto l388 - } - goto l387 - l388: - position, tokenIndex, depth = position388, tokenIndex388, depth388 + goto l386 + l387: + position, tokenIndex, depth = position387, tokenIndex387, depth387 + } + goto l380 + l381: + position, tokenIndex, depth = position380, tokenIndex380, depth380 + if !_rules[ruleTag]() { + goto l378 } } - l381: + l380: if buffer[position] != rune(':') { - goto l379 + goto l378 } position++ if buffer[position] != rune(':') { - goto l379 + goto l378 } position++ depth-- - add(ruleTag, position380) + add(ruleTagPrefix, position379) } return true - l379: - position, tokenIndex, depth = position379, tokenIndex379, depth379 + l378: + position, tokenIndex, depth = position378, tokenIndex378, depth378 return false }, - /* 94 TagName <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_')*)> */ + /* 94 Tag <- <(TagComponent (('.' / ':') TagComponent)*)> */ func() bool { - position389, tokenIndex389, depth389 := position, tokenIndex, depth + position388, tokenIndex388, depth388 := position, tokenIndex, depth { - position390 := position + position389 := position depth++ + if !_rules[ruleTagComponent]() { + goto l388 + } + l390: { position391, tokenIndex391, depth391 := position, tokenIndex, depth - if c := buffer[position]; c < rune('a') || c > rune('z') { + { + position392, tokenIndex392, depth392 := position, tokenIndex, depth + if buffer[position] != rune('.') { + goto l393 + } + position++ goto l392 + l393: + position, tokenIndex, depth = position392, tokenIndex392, depth392 + if buffer[position] != rune(':') { + goto l391 + } + position++ } - position++ - goto l391 l392: + if !_rules[ruleTagComponent]() { + goto l391 + } + goto l390 + l391: position, tokenIndex, depth = position391, tokenIndex391, depth391 + } + depth-- + add(ruleTag, position389) + } + return true + l388: + position, tokenIndex, depth = position388, tokenIndex388, depth388 + return false + }, + /* 95 TagComponent <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_')*)> */ + func() bool { + position394, tokenIndex394, depth394 := position, tokenIndex, depth + { + position395 := position + depth++ + { + position396, tokenIndex396, depth396 := position, tokenIndex, depth + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l397 + } + position++ + goto l396 + l397: + position, tokenIndex, depth = position396, tokenIndex396, depth396 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l393 + goto l398 } position++ - goto l391 - l393: - position, tokenIndex, depth = position391, tokenIndex391, depth391 + goto l396 + l398: + position, tokenIndex, depth = position396, tokenIndex396, depth396 if buffer[position] != rune('_') { - goto l389 + goto l394 } position++ } - l391: - l394: + l396: + l399: { - position395, tokenIndex395, depth395 := position, tokenIndex, depth + position400, tokenIndex400, depth400 := position, tokenIndex, depth { - position396, tokenIndex396, depth396 := position, tokenIndex, depth + position401, tokenIndex401, depth401 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l397 + goto l402 } position++ - goto l396 - l397: - position, tokenIndex, depth = position396, tokenIndex396, depth396 + goto l401 + l402: + position, tokenIndex, depth = position401, tokenIndex401, depth401 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l398 + goto l403 } position++ - goto l396 - l398: - position, tokenIndex, depth = position396, tokenIndex396, depth396 + goto l401 + l403: + position, tokenIndex, depth = position401, tokenIndex401, depth401 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l399 + goto l404 } position++ - goto l396 - l399: - position, tokenIndex, depth = position396, tokenIndex396, depth396 + goto l401 + l404: + position, tokenIndex, depth = position401, tokenIndex401, depth401 if buffer[position] != rune('_') { - goto l395 + goto l400 } position++ } - l396: - goto l394 - l395: - position, tokenIndex, depth = position395, tokenIndex395, depth395 + l401: + goto l399 + l400: + position, tokenIndex, depth = position400, tokenIndex400, depth400 } depth-- - add(ruleTagName, position390) + add(ruleTagComponent, position395) } return true - l389: - position, tokenIndex, depth = position389, tokenIndex389, depth389 + l394: + position, tokenIndex, depth = position394, tokenIndex394, depth394 return false }, - /* 95 FollowUpRef <- */ + /* 96 FollowUpRef <- */ func() bool { { - position401 := position + position406 := position depth++ - l402: + l407: { - position403, tokenIndex403, depth403 := position, tokenIndex, depth + position408, tokenIndex408, depth408 := position, tokenIndex, depth if !_rules[rulePathComponent]() { - goto l403 + goto l408 } - goto l402 - l403: - position, tokenIndex, depth = position403, tokenIndex403, depth403 + goto l407 + l408: + position, tokenIndex, depth = position408, tokenIndex408, depth408 } depth-- - add(ruleFollowUpRef, position401) + add(ruleFollowUpRef, position406) } return true }, - /* 96 PathComponent <- <(('.' Key) / ('.'? Index))> */ + /* 97 PathComponent <- <(('.' Key) / ('.'? Index))> */ func() bool { - position404, tokenIndex404, depth404 := position, tokenIndex, depth + position409, tokenIndex409, depth409 := position, tokenIndex, depth { - position405 := position + position410 := position depth++ { - position406, tokenIndex406, depth406 := position, tokenIndex, depth + position411, tokenIndex411, depth411 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l407 + goto l412 } position++ if !_rules[ruleKey]() { - goto l407 + goto l412 } - goto l406 - l407: - position, tokenIndex, depth = position406, tokenIndex406, depth406 + goto l411 + l412: + position, tokenIndex, depth = position411, tokenIndex411, depth411 { - position408, tokenIndex408, depth408 := position, tokenIndex, depth + position413, tokenIndex413, depth413 := position, tokenIndex, depth if buffer[position] != rune('.') { - goto l408 + goto l413 } position++ - goto l409 - l408: - position, tokenIndex, depth = position408, tokenIndex408, depth408 + goto l414 + l413: + position, tokenIndex, depth = position413, tokenIndex413, depth413 } - l409: + l414: if !_rules[ruleIndex]() { - goto l404 + goto l409 } } - l406: + l411: depth-- - add(rulePathComponent, position405) + add(rulePathComponent, position410) } return true - l404: - position, tokenIndex, depth = position404, tokenIndex404, depth404 + l409: + position, tokenIndex, depth = position409, tokenIndex409, depth409 return false }, - /* 97 Key <- <(([a-z] / [A-Z] / [0-9] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')* (':' ([a-z] / [A-Z] / [0-9] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)?)> */ + /* 98 Key <- <(([a-z] / [A-Z] / [0-9] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')* (':' ([a-z] / [A-Z] / [0-9] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)?)> */ func() bool { - position410, tokenIndex410, depth410 := position, tokenIndex, depth + position415, tokenIndex415, depth415 := position, tokenIndex, depth { - position411 := position + position416 := position depth++ { - position412, tokenIndex412, depth412 := position, tokenIndex, depth + position417, tokenIndex417, depth417 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l413 + goto l418 } position++ - goto l412 - l413: - position, tokenIndex, depth = position412, tokenIndex412, depth412 + goto l417 + l418: + position, tokenIndex, depth = position417, tokenIndex417, depth417 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l414 + goto l419 } position++ - goto l412 - l414: - position, tokenIndex, depth = position412, tokenIndex412, depth412 + goto l417 + l419: + position, tokenIndex, depth = position417, tokenIndex417, depth417 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l415 + goto l420 } position++ - goto l412 - l415: - position, tokenIndex, depth = position412, tokenIndex412, depth412 + goto l417 + l420: + position, tokenIndex, depth = position417, tokenIndex417, depth417 if buffer[position] != rune('_') { - goto l410 + goto l415 } position++ } - l412: - l416: + l417: + l421: { - position417, tokenIndex417, depth417 := position, tokenIndex, depth + position422, tokenIndex422, depth422 := position, tokenIndex, depth { - position418, tokenIndex418, depth418 := position, tokenIndex, depth + position423, tokenIndex423, depth423 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l419 + goto l424 } position++ - goto l418 - l419: - position, tokenIndex, depth = position418, tokenIndex418, depth418 + goto l423 + l424: + position, tokenIndex, depth = position423, tokenIndex423, depth423 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l420 + goto l425 } position++ - goto l418 - l420: - position, tokenIndex, depth = position418, tokenIndex418, depth418 + goto l423 + l425: + position, tokenIndex, depth = position423, tokenIndex423, depth423 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l421 + goto l426 } position++ - goto l418 - l421: - position, tokenIndex, depth = position418, tokenIndex418, depth418 + goto l423 + l426: + position, tokenIndex, depth = position423, tokenIndex423, depth423 if buffer[position] != rune('_') { - goto l422 + goto l427 } position++ - goto l418 - l422: - position, tokenIndex, depth = position418, tokenIndex418, depth418 + goto l423 + l427: + position, tokenIndex, depth = position423, tokenIndex423, depth423 if buffer[position] != rune('-') { - goto l417 + goto l422 } position++ } - l418: - goto l416 - l417: - position, tokenIndex, depth = position417, tokenIndex417, depth417 + l423: + goto l421 + l422: + position, tokenIndex, depth = position422, tokenIndex422, depth422 } { - position423, tokenIndex423, depth423 := position, tokenIndex, depth + position428, tokenIndex428, depth428 := position, tokenIndex, depth if buffer[position] != rune(':') { - goto l423 + goto l428 } position++ { - position425, tokenIndex425, depth425 := position, tokenIndex, depth + position430, tokenIndex430, depth430 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l426 + goto l431 } position++ - goto l425 - l426: - position, tokenIndex, depth = position425, tokenIndex425, depth425 + goto l430 + l431: + position, tokenIndex, depth = position430, tokenIndex430, depth430 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l427 + goto l432 } position++ - goto l425 - l427: - position, tokenIndex, depth = position425, tokenIndex425, depth425 + goto l430 + l432: + position, tokenIndex, depth = position430, tokenIndex430, depth430 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l428 + goto l433 } position++ - goto l425 - l428: - position, tokenIndex, depth = position425, tokenIndex425, depth425 + goto l430 + l433: + position, tokenIndex, depth = position430, tokenIndex430, depth430 if buffer[position] != rune('_') { - goto l423 + goto l428 } position++ } - l425: - l429: + l430: + l434: { - position430, tokenIndex430, depth430 := position, tokenIndex, depth + position435, tokenIndex435, depth435 := position, tokenIndex, depth { - position431, tokenIndex431, depth431 := position, tokenIndex, depth + position436, tokenIndex436, depth436 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l432 + goto l437 } position++ - goto l431 - l432: - position, tokenIndex, depth = position431, tokenIndex431, depth431 + goto l436 + l437: + position, tokenIndex, depth = position436, tokenIndex436, depth436 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l433 + goto l438 } position++ - goto l431 - l433: - position, tokenIndex, depth = position431, tokenIndex431, depth431 + goto l436 + l438: + position, tokenIndex, depth = position436, tokenIndex436, depth436 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l434 + goto l439 } position++ - goto l431 - l434: - position, tokenIndex, depth = position431, tokenIndex431, depth431 + goto l436 + l439: + position, tokenIndex, depth = position436, tokenIndex436, depth436 if buffer[position] != rune('_') { - goto l435 + goto l440 } position++ - goto l431 - l435: - position, tokenIndex, depth = position431, tokenIndex431, depth431 + goto l436 + l440: + position, tokenIndex, depth = position436, tokenIndex436, depth436 if buffer[position] != rune('-') { - goto l430 + goto l435 } position++ } - l431: - goto l429 - l430: - position, tokenIndex, depth = position430, tokenIndex430, depth430 + l436: + goto l434 + l435: + position, tokenIndex, depth = position435, tokenIndex435, depth435 } - goto l424 - l423: - position, tokenIndex, depth = position423, tokenIndex423, depth423 + goto l429 + l428: + position, tokenIndex, depth = position428, tokenIndex428, depth428 } - l424: + l429: depth-- - add(ruleKey, position411) + add(ruleKey, position416) } return true - l410: - position, tokenIndex, depth = position410, tokenIndex410, depth410 + l415: + position, tokenIndex, depth = position415, tokenIndex415, depth415 return false }, - /* 98 Index <- <('[' '-'? [0-9]+ ']')> */ + /* 99 Index <- <('[' '-'? [0-9]+ ']')> */ func() bool { - position436, tokenIndex436, depth436 := position, tokenIndex, depth + position441, tokenIndex441, depth441 := position, tokenIndex, depth { - position437 := position + position442 := position depth++ if buffer[position] != rune('[') { - goto l436 + goto l441 } position++ { - position438, tokenIndex438, depth438 := position, tokenIndex, depth + position443, tokenIndex443, depth443 := position, tokenIndex, depth if buffer[position] != rune('-') { - goto l438 + goto l443 } position++ - goto l439 - l438: - position, tokenIndex, depth = position438, tokenIndex438, depth438 + goto l444 + l443: + position, tokenIndex, depth = position443, tokenIndex443, depth443 } - l439: + l444: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l436 + goto l441 } position++ - l440: + l445: { - position441, tokenIndex441, depth441 := position, tokenIndex, depth + position446, tokenIndex446, depth446 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l441 + goto l446 } position++ - goto l440 - l441: - position, tokenIndex, depth = position441, tokenIndex441, depth441 + goto l445 + l446: + position, tokenIndex, depth = position446, tokenIndex446, depth446 } if buffer[position] != rune(']') { - goto l436 + goto l441 } position++ depth-- - add(ruleIndex, position437) + add(ruleIndex, position442) } return true - l436: - position, tokenIndex, depth = position436, tokenIndex436, depth436 + l441: + position, tokenIndex, depth = position441, tokenIndex441, depth441 return false }, - /* 99 IP <- <([0-9]+ '.' [0-9]+ '.' [0-9]+ '.' [0-9]+)> */ + /* 100 IP <- <([0-9]+ '.' [0-9]+ '.' [0-9]+ '.' [0-9]+)> */ func() bool { - position442, tokenIndex442, depth442 := position, tokenIndex, depth + position447, tokenIndex447, depth447 := position, tokenIndex, depth { - position443 := position + position448 := position depth++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l442 + goto l447 } position++ - l444: + l449: { - position445, tokenIndex445, depth445 := position, tokenIndex, depth + position450, tokenIndex450, depth450 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l445 + goto l450 } position++ - goto l444 - l445: - position, tokenIndex, depth = position445, tokenIndex445, depth445 + goto l449 + l450: + position, tokenIndex, depth = position450, tokenIndex450, depth450 } if buffer[position] != rune('.') { - goto l442 + goto l447 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l442 + goto l447 } position++ - l446: + l451: { - position447, tokenIndex447, depth447 := position, tokenIndex, depth + position452, tokenIndex452, depth452 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l452 } position++ - goto l446 - l447: - position, tokenIndex, depth = position447, tokenIndex447, depth447 + goto l451 + l452: + position, tokenIndex, depth = position452, tokenIndex452, depth452 } if buffer[position] != rune('.') { - goto l442 + goto l447 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l442 + goto l447 } position++ - l448: + l453: { - position449, tokenIndex449, depth449 := position, tokenIndex, depth + position454, tokenIndex454, depth454 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l449 + goto l454 } position++ - goto l448 - l449: - position, tokenIndex, depth = position449, tokenIndex449, depth449 + goto l453 + l454: + position, tokenIndex, depth = position454, tokenIndex454, depth454 } if buffer[position] != rune('.') { - goto l442 + goto l447 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l442 + goto l447 } position++ - l450: + l455: { - position451, tokenIndex451, depth451 := position, tokenIndex, depth + position456, tokenIndex456, depth456 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l451 + goto l456 } position++ - goto l450 - l451: - position, tokenIndex, depth = position451, tokenIndex451, depth451 + goto l455 + l456: + position, tokenIndex, depth = position456, tokenIndex456, depth456 } depth-- - add(ruleIP, position443) + add(ruleIP, position448) } return true - l442: - position, tokenIndex, depth = position442, tokenIndex442, depth442 + l447: + position, tokenIndex, depth = position447, tokenIndex447, depth447 return false }, - /* 100 ws <- <(' ' / '\t' / '\n' / '\r')*> */ + /* 101 ws <- <(' ' / '\t' / '\n' / '\r')*> */ func() bool { { - position453 := position + position458 := position depth++ - l454: + l459: { - position455, tokenIndex455, depth455 := position, tokenIndex, depth + position460, tokenIndex460, depth460 := position, tokenIndex, depth { - position456, tokenIndex456, depth456 := position, tokenIndex, depth + position461, tokenIndex461, depth461 := position, tokenIndex, depth if buffer[position] != rune(' ') { - goto l457 + goto l462 } position++ - goto l456 - l457: - position, tokenIndex, depth = position456, tokenIndex456, depth456 + goto l461 + l462: + position, tokenIndex, depth = position461, tokenIndex461, depth461 if buffer[position] != rune('\t') { - goto l458 + goto l463 } position++ - goto l456 - l458: - position, tokenIndex, depth = position456, tokenIndex456, depth456 + goto l461 + l463: + position, tokenIndex, depth = position461, tokenIndex461, depth461 if buffer[position] != rune('\n') { - goto l459 + goto l464 } position++ - goto l456 - l459: - position, tokenIndex, depth = position456, tokenIndex456, depth456 + goto l461 + l464: + position, tokenIndex, depth = position461, tokenIndex461, depth461 if buffer[position] != rune('\r') { - goto l455 + goto l460 } position++ } - l456: - goto l454 - l455: - position, tokenIndex, depth = position455, tokenIndex455, depth455 + l461: + goto l459 + l460: + position, tokenIndex, depth = position460, tokenIndex460, depth460 } depth-- - add(rulews, position453) + add(rulews, position458) } return true }, - /* 101 req_ws <- <(' ' / '\t' / '\n' / '\r')+> */ + /* 102 req_ws <- <(' ' / '\t' / '\n' / '\r')+> */ func() bool { - position460, tokenIndex460, depth460 := position, tokenIndex, depth + position465, tokenIndex465, depth465 := position, tokenIndex, depth { - position461 := position + position466 := position depth++ { - position464, tokenIndex464, depth464 := position, tokenIndex, depth + position469, tokenIndex469, depth469 := position, tokenIndex, depth if buffer[position] != rune(' ') { - goto l465 + goto l470 } position++ - goto l464 - l465: - position, tokenIndex, depth = position464, tokenIndex464, depth464 + goto l469 + l470: + position, tokenIndex, depth = position469, tokenIndex469, depth469 if buffer[position] != rune('\t') { - goto l466 + goto l471 } position++ - goto l464 - l466: - position, tokenIndex, depth = position464, tokenIndex464, depth464 + goto l469 + l471: + position, tokenIndex, depth = position469, tokenIndex469, depth469 if buffer[position] != rune('\n') { - goto l467 + goto l472 } position++ - goto l464 - l467: - position, tokenIndex, depth = position464, tokenIndex464, depth464 + goto l469 + l472: + position, tokenIndex, depth = position469, tokenIndex469, depth469 if buffer[position] != rune('\r') { - goto l460 + goto l465 } position++ } - l464: - l462: + l469: + l467: { - position463, tokenIndex463, depth463 := position, tokenIndex, depth + position468, tokenIndex468, depth468 := position, tokenIndex, depth { - position468, tokenIndex468, depth468 := position, tokenIndex, depth + position473, tokenIndex473, depth473 := position, tokenIndex, depth if buffer[position] != rune(' ') { - goto l469 + goto l474 } position++ - goto l468 - l469: - position, tokenIndex, depth = position468, tokenIndex468, depth468 + goto l473 + l474: + position, tokenIndex, depth = position473, tokenIndex473, depth473 if buffer[position] != rune('\t') { - goto l470 + goto l475 } position++ - goto l468 - l470: - position, tokenIndex, depth = position468, tokenIndex468, depth468 + goto l473 + l475: + position, tokenIndex, depth = position473, tokenIndex473, depth473 if buffer[position] != rune('\n') { - goto l471 + goto l476 } position++ - goto l468 - l471: - position, tokenIndex, depth = position468, tokenIndex468, depth468 + goto l473 + l476: + position, tokenIndex, depth = position473, tokenIndex473, depth473 if buffer[position] != rune('\r') { - goto l463 + goto l468 } position++ } + l473: + goto l467 l468: - goto l462 - l463: - position, tokenIndex, depth = position463, tokenIndex463, depth463 + position, tokenIndex, depth = position468, tokenIndex468, depth468 } depth-- - add(rulereq_ws, position461) + add(rulereq_ws, position466) } return true - l460: - position, tokenIndex, depth = position460, tokenIndex460, depth460 + l465: + position, tokenIndex, depth = position465, tokenIndex465, depth465 return false }, - /* 103 Action0 <- <{}> */ + /* 104 Action0 <- <{}> */ func() bool { { add(ruleAction0, position) } return true }, - /* 104 Action1 <- <{}> */ + /* 105 Action1 <- <{}> */ func() bool { { add(ruleAction1, position) } return true }, - /* 105 Action2 <- <{}> */ + /* 106 Action2 <- <{}> */ func() bool { { add(ruleAction2, position) diff --git a/dynaml/exec.go b/dynaml/exec.go index e4bb6dc..9abc5f3 100644 --- a/dynaml/exec.go +++ b/dynaml/exec.go @@ -16,6 +16,8 @@ import ( ) func func_exec(cached bool, arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + var cache ExecCache + info := DefaultInfo() if len(arguments) < 1 { @@ -24,6 +26,9 @@ func func_exec(cached bool, arguments []interface{}, binding Binding) (interface if !binding.GetState().OSAccessAllowed() { return info.DenyOSOperation("exec") } + if cached { + cache = binding.GetState().GetExecCache() + } args := []string{} wopt := WriteOpts{} debug.Debug("exec: found %d arguments for call\n", len(arguments)) @@ -51,7 +56,7 @@ func func_exec(cached bool, arguments []interface{}, binding Binding) (interface args = append(args, v) } } - result, err := cachedExecute(cached, nil, args) + result, err := cachedExecute(cache, nil, args) if err != nil { return info.Error("execution '%s' failed", args[0]) } @@ -121,13 +126,11 @@ func getArg(key interface{}, value interface{}, wopt WriteOpts, allowyaml bool) } } -var cache = make(map[string][]byte) - type Bytes interface { Bytes() []byte } -func cachedExecute(cached bool, content *string, args []string) ([]byte, error) { +func cachedExecute(cache ExecCache, content *string, args []string) ([]byte, error) { h := md5.New() if content != nil { h.Write([]byte(*content)) @@ -136,8 +139,10 @@ func cachedExecute(cached bool, content *string, args []string) ([]byte, error) h.Write([]byte(arg)) } hash := fmt.Sprintf("%x", h.Sum(nil)) - if cached { - result := cache[hash] + if cache != nil { + cache.Lock() + defer cache.Unlock() + result := cache.Get(hash) if result != nil { debug.Debug("exec: reusing cache %s for %v\n", hash, args) return result, nil @@ -154,7 +159,9 @@ func cachedExecute(cached bool, content *string, args []string) ([]byte, error) fmt.Fprintf(os.Stderr, "exec: calling %v\n", args) fmt.Fprintf(os.Stderr, " error: %v\n", stderr) } - cache[hash] = result + if cache != nil { + cache.Set(hash, result) + } return result, err } diff --git a/dynaml/expression.go b/dynaml/expression.go index 2a85108..8940270 100644 --- a/dynaml/expression.go +++ b/dynaml/expression.go @@ -3,6 +3,7 @@ package dynaml import ( "github.com/mandelsoft/vfs/pkg/vfs" + "github.com/mandelsoft/spiff/features" "github.com/mandelsoft/spiff/yaml" ) @@ -16,6 +17,14 @@ type SourceProvider interface { SourceName() string } +type ExecCache interface { + Lock() + Unlock() + Get(key string) []byte + Set(key string, content []byte) + Clear() +} + type State interface { GetTempName(data []byte) (string, error) GetFileContent(file string, cached bool) ([]byte, error) @@ -23,13 +32,14 @@ type State interface { OSAccessAllowed() bool FileAccessAllowed() bool FileSystem() vfs.VFS - GetFunctions() Registry + GetRegistry() Registry + GetFeatures() features.FeatureFlags + GetExecCache() ExecCache InterpolationEnabled() bool + ControlEnabled() bool SetTag(name string, node yaml.Node, path []string, scope TagScope) error GetTag(name string) *Tag GetTags(name string) []*TagInfo - - EnableInterpolation() } type Binding interface { @@ -54,6 +64,7 @@ type Binding interface { NoMerge() bool GetState() State + GetFeatures() features.FeatureFlags GetTempName(data []byte) (string, error) GetFileContent(file string, cached bool) ([]byte, error) @@ -196,6 +207,10 @@ func (i EvaluationInfo) CleanError() EvaluationInfo { return i } +func (i EvaluationInfo) GetError() string { + return i.Issue.Issue +} + func (i EvaluationInfo) Join(o EvaluationInfo) EvaluationInfo { if o.RedirectPath != nil { i.RedirectPath = o.RedirectPath diff --git a/dynaml/fake_binding_helper_test.go b/dynaml/fake_binding_helper_test.go index 9ad0443..f56f04b 100644 --- a/dynaml/fake_binding_helper_test.go +++ b/dynaml/fake_binding_helper_test.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/mandelsoft/spiff/features" "github.com/mandelsoft/spiff/yaml" ) @@ -28,6 +29,10 @@ func (c FakeBinding) GetState() State { return nil } +func (c FakeBinding) GetFeatures() features.FeatureFlags { + return nil +} + func (c FakeBinding) Outer() Binding { return nil } diff --git a/dynaml/features.go b/dynaml/features.go new file mode 100644 index 0000000..a34cb06 --- /dev/null +++ b/dynaml/features.go @@ -0,0 +1,30 @@ +package dynaml + +import ( + "github.com/mandelsoft/spiff/yaml" +) + +func init() { + RegisterFunction("features", func_features) +} + +func func_features(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + + switch len(arguments) { + case 0: + result := []yaml.Node{} + for f := range binding.GetFeatures() { + result = append(result, NewNode(f, binding)) + } + return result, info, true + case 1: + name, ok := arguments[0].(string) + if !ok { + return info.Error("features: argument must be a string") + } + return binding.GetFeatures().Enabled(name), info, true + default: + return info.Error("features acctepts a maximum of one arguments") + } +} diff --git a/dynaml/lambda.go b/dynaml/lambda.go index 11a8602..a91437e 100644 --- a/dynaml/lambda.go +++ b/dynaml/lambda.go @@ -64,7 +64,7 @@ func (e LambdaExpr) Evaluate(binding Binding, locally bool) (interface{}, Evalua info.Issue.Sequence = true return nil, info, ok } - if isExpression(value) { + if IsExpression(value) { debug.Debug("delay LAMBDA expression for default argument %d", i) return nil, info, ok } @@ -126,7 +126,7 @@ func (e LambdaRefExpr) Evaluate(binding Binding, locally bool) (interface{}, Eva return info.Error("'%s' is no lambda expression", v) } value, info, ok := lexpr.Evaluate(binding, locally) - if !ok || isExpression(value) { + if !ok || IsExpression(value) { return value, info, ok } lambda = value.(LambdaValue) @@ -175,13 +175,13 @@ func (e LambdaValue) EquivalentTo(val interface{}) bool { return ok && reflect.DeepEqual(e.lambda, o.lambda) } -func short(val interface{}, all bool) string { +func Short(val interface{}, all bool) string { switch v := val.(type) { case []yaml.Node: s := "[" sep := "" for _, e := range v { - s = fmt.Sprintf("%s%s%s", s, sep, short(e.Value(), all)) + s = fmt.Sprintf("%s%s%s", s, sep, Short(e.Value(), all)) sep = ", " } return s + "]" @@ -190,7 +190,7 @@ func short(val interface{}, all bool) string { sep := "" for _, k := range getSortedKeys(v) { if all || k != "_" { - s = fmt.Sprintf("%s%s%s: %s", s, sep, k, short(v[k].Value(), all)) + s = fmt.Sprintf("%s%s%s: %s", s, sep, k, Short(v[k].Value(), all)) sep = ", " } } @@ -203,9 +203,9 @@ func short(val interface{}, all bool) string { func (e LambdaValue) String() string { binding := "" if len(e.static) > 0 { - binding = short(e.static, false) + binding = Short(e.static, false) } - return fmt.Sprintf("%s%s", shorten(binding), e.lambda) + return fmt.Sprintf("%s%s", Shorten(binding), e.lambda) } func (e LambdaValue) NumOptional() int { @@ -220,7 +220,7 @@ func (e LambdaValue) NumOptional() int { return 0 } -func shorten(s string) string { +func Shorten(s string) string { if len(s) > 40 { s = s[:17] + " ... " + s[len(s)-17:] } @@ -362,12 +362,12 @@ func (e LambdaValue) Evaluate(inline bool, curry, autocurry bool, nargs map[stri if !ok { debug.Debug("failed LAMBDA CALL: %s", info.Issue.Issue) nested := info.Issue - info.SetError("evaluation of lambda expression failed: %s: %s", e, shorten(short(inp, false))) + info.SetError("evaluation of lambda expression failed: %s: %s", e, Shorten(Short(inp, false))) info.Issue.Nested = append(info.Issue.Nested, nested) info.Issue.Sequence = true return false, nil, info, ok } - if isExpression(value) { + if IsExpression(value) { debug.Debug("delay LAMBDA CALL") return false, nil, info, ok } diff --git a/dynaml/log_or.go b/dynaml/log_or.go index 2b72f55..05280ac 100644 --- a/dynaml/log_or.go +++ b/dynaml/log_or.go @@ -51,7 +51,7 @@ func resolveLOperands(a, b Expression, binding Binding) (eff_a, eff_b interface{ va, infoa, first_ok = a.Evaluate(binding, false) if first_ok { - if isExpression(va) { + if IsExpression(va) { return nil, nil, infoa, false, true, true } @@ -61,7 +61,7 @@ func resolveLOperands(a, b Expression, binding Binding) (eff_a, eff_b interface{ return va, nil, info, true, true, false } - if isExpression(vb) { + if IsExpression(vb) { return nil, nil, info, false, true, true } diff --git a/dynaml/marker.go b/dynaml/marker.go index d53c745..0835b31 100644 --- a/dynaml/marker.go +++ b/dynaml/marker.go @@ -15,6 +15,7 @@ const ( INJECT = "&inject" DEFAULT = "&default" STATE = "&state" + DYNAMIC = "&dynamic" // POC ) type MarkerExpr struct { @@ -22,6 +23,20 @@ type MarkerExpr struct { expr Expression } +func NewTemplateMarker(expr Expression) MarkerExpr { + return MarkerExpr{list: []string{TEMPLATE}, expr: expr} +} + +func (e MarkerExpr) Add(marker string) MarkerExpr { + for _, v := range e.list { + if v == marker { + return e + } + } + e.list = append(e.list, marker) + return e +} + func (e MarkerExpr) String() string { if e.expr != nil { return fmt.Sprintf("%s (%s)", strings.Join(e.list, " "), e.expr) @@ -52,6 +67,8 @@ func (e MarkerExpr) GetFlags() yaml.NodeFlags { flags.SetDefault() case STATE: flags.SetState() + case DYNAMIC: + flags.SetDynamic() } } return flags @@ -102,11 +119,14 @@ func (e MarkerExpr) TemplateExpression(orig yaml.Node) yaml.Node { debug.Debug(" omitting marker %s", m) } } - if len(nlist) > 0 { - return yaml.SubstituteNode(fmt.Sprintf("(( %s ))", MarkerExpr{nlist, e.expr}), orig) + m := MarkerExpr{nlist, e.expr} + + // TODO: remove case + if false && len(nlist) > 0 { + return yaml.SubstituteNode(fmt.Sprintf("(( %s ))", m), orig) } if e.expr != nil { - return yaml.SubstituteNode(fmt.Sprintf("(( %s ))", e.expr), orig) + return yaml.AddFlags(yaml.SubstituteNode(fmt.Sprintf("(( %s ))", e.expr), orig), m.GetFlags()) } return nil } diff --git a/dynaml/node.go b/dynaml/node.go index 3f2dce6..2df6ad9 100644 --- a/dynaml/node.go +++ b/dynaml/node.go @@ -28,3 +28,14 @@ func NewNode(val interface{}, src SourceProvider) yaml.Node { return yaml.NewNode(val, source) } + +func IssueNode(env Binding, preservePath bool, node yaml.Node, error bool, failed bool, issue yaml.Issue) yaml.Node { + if node.Issue().OrigPath != nil { + issue.OrigPath = node.Issue().OrigPath + } else { + if env != nil && preservePath { + issue.OrigPath = env.Path() + } + } + return yaml.IssueNode(node, error, failed, issue) +} diff --git a/dynaml/or.go b/dynaml/or.go index cbd9943..b8cdc01 100644 --- a/dynaml/or.go +++ b/dynaml/or.go @@ -18,7 +18,7 @@ func (e OrExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluation return e, infoa, true } // fmt.Printf("++++++++++++++++++ %s\n", e.A) - if isExpression(a) { + if IsExpression(a) { return e, infoa, true } return a, infoa, true diff --git a/dynaml/parser.go b/dynaml/parser.go index 5bf2c02..da2c73b 100644 --- a/dynaml/parser.go +++ b/dynaml/parser.go @@ -514,7 +514,7 @@ func buildExpression(grammar *DynamlGrammar, path []string, stubPath []string) ( tokens.Push(expressionListHelper{}) case ruleKey, ruleIndex: - case ruleTag, ruleTagName: + case ruleTag, ruleTagComponent, ruleTagPrefix: case ruleLevel0, ruleLevel1, ruleLevel2, ruleLevel3, ruleLevel4, ruleLevel5, ruleLevel6, ruleLevel7: case ruleExpression: case ruleExpressionList: diff --git a/dynaml/pipe.go b/dynaml/pipe.go index ae4628c..2b6087a 100644 --- a/dynaml/pipe.go +++ b/dynaml/pipe.go @@ -6,6 +6,7 @@ import ( ) func func_pipe(cached bool, arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + var cache ExecCache info := DefaultInfo() if len(arguments) <= 2 { @@ -14,6 +15,9 @@ func func_pipe(cached bool, arguments []interface{}, binding Binding) (interface if !binding.GetState().OSAccessAllowed() { return info.DenyOSOperation("pipe") } + if cached { + cache = binding.GetState().GetExecCache() + } args := []string{} wopt := WriteOpts{} debug.Debug("pipe: found %d arguments for call\n", len(arguments)) @@ -49,7 +53,7 @@ func func_pipe(cached bool, arguments []interface{}, binding Binding) (interface args = append(args, v) } } - result, err := cachedExecute(cached, &args[0], args[1:]) + result, err := cachedExecute(cache, &args[0], args[1:]) if err != nil { return info.Error("execution '%s' failed", args[1]) } diff --git a/dynaml/projection.go b/dynaml/projection.go index 28a676a..e787a5f 100644 --- a/dynaml/projection.go +++ b/dynaml/projection.go @@ -32,10 +32,10 @@ func (e ProjectionExpr) Evaluate(binding Binding, locally bool) (interface{}, Ev if !ok { return nil, infoa, false } - if !isLocallyResolvedValue(newList[index]) { + if !isLocallyResolvedValue(newList[index], binding) { return e, infoa, true } - if !locally && !isResolvedValue(newList[index]) { + if !locally && !isResolvedValue(newList[index], binding) { return e, infoa, true } newList[index] = NewNode(result, binding) @@ -50,10 +50,10 @@ func (e ProjectionExpr) Evaluate(binding Binding, locally bool) (interface{}, Ev if !ok { return nil, infoa, false } - if !isLocallyResolvedValue(newList[index]) { + if !isLocallyResolvedValue(newList[index], binding) { return e, infoa, true } - if !locally && !isResolvedValue(newList[index]) { + if !locally && !isResolvedValue(newList[index], binding) { return e, infoa, true } newList[index] = NewNode(result, binding) diff --git a/dynaml/qualified_expression.go b/dynaml/qualified_expression.go index e6e7e73..138b04a 100644 --- a/dynaml/qualified_expression.go +++ b/dynaml/qualified_expression.go @@ -19,7 +19,7 @@ func (e QualifiedExpr) Evaluate(binding Binding, locally bool) (interface{}, Eva return nil, info, false } locally = locally || info.Raw - if !isLocallyResolvedValue(root) { + if !isLocallyResolvedValue(root, binding) { debug.Debug("not locally resolved: %v\n", root) if root != nil { if ex, ok := root.(Expression); ok { @@ -28,14 +28,14 @@ func (e QualifiedExpr) Evaluate(binding Binding, locally bool) (interface{}, Eva } return e, info, true } - if !locally && !isResolvedValue(root) { + if !locally && !isResolvedValue(root, binding) { debug.Debug("not resoved: %v\n", root) return e, info, true } debug.Debug("qualified reference (%t): %v\n", locally, e.Reference.Path) return e.Reference.find(func(end int, path []string) (yaml.Node, bool) { - return yaml.Find(NewNode(root, nil), path[:end+1]...) + return yaml.Find(NewNode(root, nil), binding.GetFeatures(), path[:end+1]...) }, binding, locally) } diff --git a/dynaml/reference.go b/dynaml/reference.go index a7595a0..b3fe28b 100644 --- a/dynaml/reference.go +++ b/dynaml/reference.go @@ -34,7 +34,7 @@ func (e ReferenceExpr) Evaluate(binding Binding, locally bool) (interface{}, Eva return binding.FindFromRoot(path[start : end+1]) } else { if tag != nil { - return yaml.Find(tag.Node(), path...) + return yaml.Find(tag.Node(), binding.GetFeatures(), path...) } return binding.FindReference(path[:end+1]) } @@ -42,7 +42,7 @@ func (e ReferenceExpr) Evaluate(binding Binding, locally bool) (interface{}, Eva if e.Tag != "" { info := DefaultInfo() - if e.Tag != "doc:0" { + if e.Tag != "doc:0" && e.Tag != "doc.0" { tags := binding.GetState().GetTags(e.Tag) if len(tags) == 0 { return info.Error("tag '%s' not found", e.Tag) @@ -110,7 +110,7 @@ func (e ReferenceExpr) find(f func(int, []string) (node yaml.Node, x bool), bind return info.Error("'%s' not found", strings.Join(e.Path[0:i+1], ".")) } - if !isLocallyResolved(step) { + if !isLocallyResolved(step, binding) { debug.Debug(" locally unresolved %T\n", step.Value()) if _, ok := step.Value().(Expression); ok { info.Issue = yaml.NewIssue("'%s' unresolved", strings.Join(e.Path[0:i+1], ".")) @@ -122,7 +122,7 @@ func (e ReferenceExpr) find(f func(int, []string) (node yaml.Node, x bool), bind } } - if !locally && !isResolvedValue(step.Value()) { + if !locally && !isResolvedValue(step.Value(), binding) { debug.Debug(" unresolved\n") info.Issue = yaml.NewIssue("'%s' unresolved", strings.Join(e.Path, ".")) info.Failed = step.Failed() || step.HasError() diff --git a/dynaml/registry.go b/dynaml/registry.go new file mode 100644 index 0000000..cac2c39 --- /dev/null +++ b/dynaml/registry.go @@ -0,0 +1,62 @@ +package dynaml + +type Registry interface { + LookupFunction(name string) Function + + LookupControl(name string) (*Control, bool) + IsTemplateControlOption(name string) bool + + WithFunctions(Functions) Registry + WithControls(Controls) Registry +} + +type registry struct { + functions Functions + controls Controls +} + +func (r *registry) WithFunctions(f Functions) Registry { + if r == nil { + return ®istry{functions: f} + } + return ®istry{ + functions: f, + controls: r.controls, + } +} + +func (r *registry) WithControls(c Controls) Registry { + if r == nil { + return ®istry{controls: c} + } + return ®istry{ + functions: r.functions, + controls: c, + } +} + +func (r *registry) LookupFunction(name string) Function { + if r == nil || r.functions == nil { + return function_registry.LookupFunction(name) + } + return r.functions.LookupFunction(name) +} + +func (r *registry) LookupControl(name string) (*Control, bool) { + if r == nil || r.controls == nil { + return control_registry.LookupControl(name) + } + return r.controls.LookupControl(name) +} + +func (r *registry) IsTemplateControlOption(name string) bool { + if r == nil || r.controls == nil { + return control_registry.IsTemplateControlOption(name) + } + return r.controls.IsTemplateControlOption(name) +} + +func DefaultRegistry() Registry { + var r *registry + return r // standard beaviour support on nil pointer inter +} diff --git a/dynaml/scope.go b/dynaml/scope.go index f3ca50b..524c52b 100644 --- a/dynaml/scope.go +++ b/dynaml/scope.go @@ -25,7 +25,7 @@ func (e ScopeExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluat binding = binding.WithLocalScope(b) debug.Debug("SCOPE: %s\n", binding) local, info, ok = e.E.Evaluate(binding, locally) - if ok && isExpression(local) { + if ok && IsExpression(local) { return e, info, ok } return local, info, ok diff --git a/dynaml/semver/compare.go b/dynaml/semver/compare.go new file mode 100644 index 0000000..3f512a3 --- /dev/null +++ b/dynaml/semver/compare.go @@ -0,0 +1,27 @@ +package semver + +import ( + . "github.com/mandelsoft/spiff/dynaml" +) + +const F_Compare = "semvercmp" + +func init() { + RegisterFunction(F_Compare, func_compare) +} + +func func_compare(args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + if len(args) != 2 { + return info.Error("%s requires two arguments", F_Compare) + } + v1, info := parse(F_Compare, args[0]) + if v1 == nil { + return nil, info, false + } + v2, info := parse(F_Compare, args[1]) + if v2 == nil { + return nil, info, false + } + return v1.Compare(v2), info, true +} diff --git a/dynaml/semver/match.go b/dynaml/semver/match.go new file mode 100644 index 0000000..1c3b765 --- /dev/null +++ b/dynaml/semver/match.go @@ -0,0 +1,25 @@ +package semver + +import ( + . "github.com/mandelsoft/spiff/dynaml" +) + +const F_Match = "semvermatch" + +func init() { + RegisterFunction(F_Match, func_match) +} + +func func_match(args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + + if len(args) == 0 { + return info.Error("%s requires at least one arguments", F_Match) + } + + ok, _, err, _ := validate(F_Match, false, args[0], binding, args[1:]...) + if err != nil { + return info.Error("%s", err) + } + return ok, info, true +} diff --git a/dynaml/semver/mod.go b/dynaml/semver/mod.go new file mode 100644 index 0000000..a754db2 --- /dev/null +++ b/dynaml/semver/mod.go @@ -0,0 +1,29 @@ +package semver + +import ( + "github.com/Masterminds/semver/v3" + + . "github.com/mandelsoft/spiff/dynaml" +) + +const F_IncMajor = "semverincmajor" +const F_IncMinor = "semverincminor" +const F_IncPatch = "semverincpatch" + +func init() { + RegisterFunction(F_IncMajor, func_incmajor) + RegisterFunction(F_IncMinor, func_incminor) + RegisterFunction(F_IncPatch, func_incpatch) +} + +func func_incmajor(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_IncMajor, func(v *semver.Version) interface{} { r := v.IncMajor(); return r.Original() }, arguments, binding) +} + +func func_incminor(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_IncMinor, func(v *semver.Version) interface{} { r := v.IncMinor(); return r.Original() }, arguments, binding) +} + +func func_incpatch(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_IncPatch, func(v *semver.Version) interface{} { r := v.IncPatch(); return r.Original() }, arguments, binding) +} diff --git a/dynaml/semver/semver.go b/dynaml/semver/semver.go new file mode 100644 index 0000000..f27e5c2 --- /dev/null +++ b/dynaml/semver/semver.go @@ -0,0 +1,138 @@ +package semver + +import ( + "github.com/Masterminds/semver/v3" + + . "github.com/mandelsoft/spiff/dynaml" +) + +const F_Major = "semvermajor" +const F_Minor = "semverminor" +const F_Patch = "semverpatch" +const F_Prerelease = "semverprerelease" +const F_Metadata = "semvermetadata" +const F_Release = "semverrelease" +const F_Normalize = "semver" + +func init() { + RegisterFunction(F_Major, func_major) + RegisterFunction(F_Minor, func_minor) + RegisterFunction(F_Patch, func_patch) + RegisterFunction(F_Prerelease, func_prerelease) + RegisterFunction(F_Metadata, func_metadata) + RegisterFunction(F_Release, func_release) + RegisterFunction(F_Normalize, func_normalize) +} + +func parse(name string, arg interface{}) (*semver.Version, EvaluationInfo) { + info := DefaultInfo() + s, ok := arg.(string) + if !ok { + info.SetError("%s requires one string argument, but got %s", name, ExpressionType(arg)) + return nil, info + } + v, err := semver.NewVersion(s) + if err != nil { + info.SetError("%s: %q: %s", name, s, err) + return nil, info + } + return v, info +} + +func func_semver(name string, get func(version *semver.Version) interface{}, args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver2(name, get, nil, args, binding) +} + +func func_semver2(name string, get func(version *semver.Version) interface{}, set func(version *semver.Version, arg interface{}) (interface{}, EvaluationInfo, bool), args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + + if set != nil && len(args) > 1 { + if len(args) > 2 { + return info.Error("%s requires one semver argument and an optional value", name) + } + } else { + if len(args) != 1 { + return info.Error("%s requires one semver argument", name) + } + } + v, info := parse(name, args[0]) + + if v == nil { + return nil, info, false + } + if set != nil && len(args) == 2 { + return set(v, args[1]) + } + return get(v), info, true +} + +func setter(name, attr string, f func(v *semver.Version, s string) (semver.Version, error)) func(v *semver.Version, val interface{}) (interface{}, EvaluationInfo, bool) { + return func(v *semver.Version, val interface{}) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + s, err := StringValue(attr, val) + if err != nil { + return info.Error("%s: %s", name, err) + } + r, err := f(v, s) + if err != nil { + return info.Error("%s: invalid %s %q: %s", name, attr, s, err) + } + return r.Original(), info, true + } +} + +//////////////////////////////////////////////////////////////////////////////// + +func func_major(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_Major, func(v *semver.Version) interface{} { return int64(v.Major()) }, arguments, binding) +} + +func func_minor(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_Minor, func(v *semver.Version) interface{} { return int64(v.Minor()) }, arguments, binding) +} + +func func_patch(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_Patch, func(v *semver.Version) interface{} { return int64(v.Patch()) }, arguments, binding) +} + +func func_prerelease(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver2(F_Prerelease, + func(v *semver.Version) interface{} { + return v.Prerelease() + }, + setter(F_Prerelease, "prerelease", func(v *semver.Version, s string) (semver.Version, error) { return v.SetPrerelease(s) }), + arguments, binding) +} + +func func_metadata(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver2(F_Metadata, + func(v *semver.Version) interface{} { + return v.Metadata() + }, + setter(F_Metadata, "metadata", func(v *semver.Version, s string) (semver.Version, error) { return v.SetMetadata(s) }), + arguments, binding) +} + +func func_release(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver2(F_Release, + func(v *semver.Version) interface{} { + r, _ := v.SetMetadata("") + r, _ = r.SetPrerelease("") + return r.Original() + }, + setter(F_Release, "release", + func(v *semver.Version, s string) (semver.Version, error) { + n, err := semver.NewVersion(s) + if err != nil { + return semver.Version{}, err + } + r, _ := n.SetMetadata(v.Metadata()) + r, _ = r.SetPrerelease(v.Prerelease()) + return r, nil + }), + arguments, binding) +} + +func func_normalize(arguments []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + return func_semver(F_Prerelease, func(v *semver.Version) interface{} { return v.String() }, arguments, binding) +} diff --git a/dynaml/semver/sort.go b/dynaml/semver/sort.go new file mode 100644 index 0000000..61d1a3b --- /dev/null +++ b/dynaml/semver/sort.go @@ -0,0 +1,45 @@ +package semver + +import ( + "sort" + + "github.com/Masterminds/semver/v3" + + . "github.com/mandelsoft/spiff/dynaml" + "github.com/mandelsoft/spiff/yaml" +) + +const F_Sort = "semversort" + +func init() { + RegisterFunction(F_Sort, func_sort) +} + +func func_sort(args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + + if len(args) == 1 { + if a, ok := args[0].([]yaml.Node); ok { + args = make([]interface{}, len(a)) + for i, v := range a { + args[i] = v.Value() + } + } + } + versions := make([]*semver.Version, len(args)) + + for i, a := range args { + v, info := parse(F_Compare, a) + if v == nil { + return nil, info, false + } + versions[i] = v + } + sort.Sort(semver.Collection(versions)) + + val := make([]yaml.Node, len(args)) + for i, v := range versions { + val[i] = yaml.NewNode(v.Original(), binding.SourceName()) + } + return val, info, true +} diff --git a/dynaml/semver/validate.go b/dynaml/semver/validate.go new file mode 100644 index 0000000..e01ccec --- /dev/null +++ b/dynaml/semver/validate.go @@ -0,0 +1,65 @@ +package semver + +import ( + "github.com/Masterminds/semver/v3" + + . "github.com/mandelsoft/spiff/dynaml" +) + +const F_Validate = "semvervalidate" +const V_Validate = "semver" + +func init() { + RegisterFunction(F_Validate, func_validate) + RegisterValidator(V_Validate, validate_semver) +} + +func func_validate(args []interface{}, binding Binding) (interface{}, EvaluationInfo, bool) { + info := DefaultInfo() + if len(args) == 0 { + return info.Error("%s requires at least one arguments", F_Validate) + } + + ok, msg, err, _ := validate(F_Validate, false, args[0], binding, args[1:]...) + + if err != nil { + return info.Error("%s: %q: %s", F_Validate, args[0], err) + } + if !ok { + return info.Error("%s: %q: %s", F_Validate, args[0], msg) + } + return args[0], info, true +} + +func validate_semver(value interface{}, binding Binding, args ...interface{}) (bool, string, error, bool) { + return validate(V_Validate, true, value, binding, args...) +} + +func validate(name string, noerr bool, value interface{}, binding Binding, args ...interface{}) (bool, string, error, bool) { + v, info := parse(name, value) + if v == nil { + if noerr { + return ValidatorResult(false, "%s", info.GetError()) + } + return ValidatorErrorf("%s", info.GetError()) + } + for i, a := range args { + constraint, ok := a.(string) + if !ok { + return ValidatorErrorf("%s: constraint argument %d must be string", name, i) + } + + c, err := semver.NewConstraint(constraint) + if err != nil { + return ValidatorErrorf("%s: invalid constraint %q[%d]: %s", name, constraint, i, err) + } + ok, msgs := c.Validate(v) + if !ok { + return ValidatorResult(ok, "%v", msgs) + } + } + if len(args) > 0 { + return ValidatorResult(true, "matches contraint") + } + return true, "is semantic version", nil, true +} diff --git a/dynaml/slice.go b/dynaml/slice.go index 3cdff95..25de6df 100644 --- a/dynaml/slice.go +++ b/dynaml/slice.go @@ -18,10 +18,10 @@ func (e SliceExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluat if !ok { return nil, info, false } - if !isLocallyResolvedValue(root) { + if !isLocallyResolvedValue(root, binding) { return e, info, true } - if !locally && !isResolvedValue(root) { + if !locally && !isResolvedValue(root, binding) { return e, info, true } diff --git a/dynaml/static_ips.go b/dynaml/static_ips.go index 3422154..0583c51 100644 --- a/dynaml/static_ips.go +++ b/dynaml/static_ips.go @@ -100,7 +100,7 @@ func generateStaticIPs(binding Binding, indices []int) (interface{}, EvaluationI func findInstanceCount(binding Binding) (*int64, EvaluationInfo, bool) { nearestInstances, info, found := refInstances.Evaluate(binding, false) - if !found || isExpression(nearestInstances) { + if !found || IsExpression(nearestInstances) { return nil, info, false } @@ -110,7 +110,7 @@ func findInstanceCount(binding Binding) (*int64, EvaluationInfo, bool) { func findStaticIPRanges(binding Binding) ([]string, EvaluationInfo, bool) { nearestNetworkName, info, found := refName.Evaluate(binding, false) - if !found || isExpression(nearestNetworkName) { + if !found || IsExpression(nearestNetworkName) { return nil, info, found } @@ -126,7 +126,7 @@ func findStaticIPRanges(binding Binding) ([]string, EvaluationInfo, bool) { if !found { return nil, info, false } - if isExpression(subnets) { + if IsExpression(subnets) { return nil, info, true } diff --git a/dynaml/subtraction.go b/dynaml/subtraction.go index 4043aba..6fccdf4 100644 --- a/dynaml/subtraction.go +++ b/dynaml/subtraction.go @@ -29,26 +29,43 @@ func (e SubtractionExpr) Evaluate(binding Binding, locally bool) (interface{}, E str, ok := a.(string) if ok { + var cidr *net.IPNet + var err error ip := net.ParseIP(str) - if ip != nil { - bint, bok := b.(int64) - if bok { - return IPAdd(ip, -bint).String(), info, true + if ip == nil { + ip, cidr, err = net.ParseCIDR(str) + if err != nil { + return info.Error("first argument for substraction must be IP address, CIDR or number") } - bstr, ok := b.(string) - if ok { - ipb := net.ParseIP(bstr) - if ip != nil { - if len(ip) != len(ipb) { - return info.Error("IP type mismatch") - } - return DiffIP(ip, ipb), info, true + } + bint, bok := b.(int64) + if bok { + ip = IPAdd(ip, -bint) + if cidr != nil { + if !cidr.Contains(ip) { + return info.Error("resulting ip address not in CIDR range") } - return info.Error("second argument of IP address subtraction must be IP address or integer") + cidr.IP = ip + return cidr.String(), info, true + } + return ip.String(), info, true + } + bstr, ok := b.(string) + if ok { + ipb := net.ParseIP(bstr) + if ipb == nil { + ip, _, err := net.ParseCIDR(bstr) + if err != nil { + return info.Error("second argument for substraction must be IP address, CIDR or number") + } + ipb = ip + } + if len(ip) != len(ipb) { + return info.Error("IP type mismatch (%d != %d)", len(ip), len(ipb)) } - return info.Error("second argument of IP address subtraction must be IP address or integer") + return DiffIP(ip, ipb), info, true } - return info.Error("string argument for MINUS must be an IP address") + return info.Error("second argument of IP address subtraction must be IP address or integer") } a, b, err := NumberOperands(a, b) diff --git a/dynaml/subtraction_test.go b/dynaml/subtraction_test.go index cb062e4..cdd42b1 100644 --- a/dynaml/subtraction_test.go +++ b/dynaml/subtraction_test.go @@ -83,4 +83,55 @@ var _ = Describe("subtraction", func() { Expect(expr).To(EvaluateAs(1.25, FakeBinding{})) }) }) + Context("IPs", func() { + It("subtracts ips and ips", func() { + expr := SubtractionExpr{ + StringExpr{"10.0.0.10"}, + StringExpr{"10.0.0.1"}, + } + + Expect(expr).To(EvaluateAs(9, FakeBinding{})) + }) + It("subtracts cidr and ips", func() { + expr := SubtractionExpr{ + StringExpr{"10.0.0.10/24"}, + StringExpr{"10.0.0.1"}, + } + + Expect(expr).To(EvaluateAs(9, FakeBinding{})) + }) + It("subtracts cidr and cidrs", func() { + expr := SubtractionExpr{ + StringExpr{"10.0.0.10/24"}, + StringExpr{"10.0.0.1/30"}, + } + + Expect(expr).To(EvaluateAs(9, FakeBinding{})) + }) + It("subtracts cidr and int", func() { + expr := SubtractionExpr{ + StringExpr{"10.0.0.10/24"}, + IntegerExpr{9}, + } + + Expect(expr).To(EvaluateAs("10.0.0.1/24", FakeBinding{})) + }) + + It("adds ip and int", func() { + expr := AdditionExpr{ + StringExpr{"10.0.0.10"}, + IntegerExpr{2}, + } + + Expect(expr).To(EvaluateAs("10.0.0.12", FakeBinding{})) + }) + It("adds cidr and int", func() { + expr := AdditionExpr{ + StringExpr{"10.0.0.10/24"}, + IntegerExpr{2}, + } + + Expect(expr).To(EvaluateAs("10.0.0.12/24", FakeBinding{})) + }) + }) }) diff --git a/dynaml/sync.go b/dynaml/sync.go index 1bda338..a3223fb 100644 --- a/dynaml/sync.go +++ b/dynaml/sync.go @@ -132,7 +132,7 @@ func (e SyncExpr) Evaluate(binding Binding, locally bool) (interface{}, Evaluati if !ok { return info.AnnotateError(infoc, "value expression failed)") } - if isExpression(value) { + if IsExpression(value) { return e, infov, true } diff --git a/dynaml/tag.go b/dynaml/tag.go index 7cb720b..9d1b88b 100644 --- a/dynaml/tag.go +++ b/dynaml/tag.go @@ -113,7 +113,7 @@ func NewTagInfo(tag *Tag) *TagInfo { comp := "" comps := []string{} for _, c := range tag.name { - if c == ':' { + if c == ':' || c == '.' { comps = append(comps, comp) comp = "" l++ @@ -133,7 +133,7 @@ func CheckTagName(name string) error { l := 0 for _, c := range name { switch c { - case ':': + case ':', '.': if l == 0 { return fmt.Errorf("empty tag component not allowed") } diff --git a/dynaml/template.go b/dynaml/template.go index 8d12189..d6f4354 100644 --- a/dynaml/template.go +++ b/dynaml/template.go @@ -16,7 +16,7 @@ type SubstitutionExpr struct { func (e SubstitutionExpr) Evaluate(binding Binding, locally bool) (interface{}, EvaluationInfo, bool) { debug.Debug("evaluating expression to determine template: %s\n", binding) n, info, ok := e.Template.Evaluate(binding, false) - if !ok || isExpression(n) { + if !ok || IsExpression(n) { return e, info, ok } inp := map[string]yaml.Node{} @@ -30,6 +30,9 @@ func (e SubstitutionExpr) Evaluate(binding Binding, locally bool) (interface{}, debug.Debug("resolving template '%s' %s\n", strings.Join(template.Path, "."), binding) result, state := binding.WithLocalScope(inp).Flow(prepared, false) info = DefaultInfo() + if result != nil && result.Undefined() { + info.Undefined = true + } if state != nil { if state.HasError() { debug.Debug("resolving template failed: " + state.Error()) @@ -63,7 +66,7 @@ func NewTemplateValue(path []string, prepared yaml.Node, orig yaml.Node, binding } func (e TemplateValue) String() string { - return fmt.Sprintf("