Add new SQL parser to support S3 Select syntax (#7102)

- New parser written from scratch, allows easier and complete parsing
  of the full S3 Select SQL syntax. Parser definition is directly
  provided by the AST defined for the SQL grammar.

- Bring support to parse and interpret SQL involving JSON path
  expressions; evaluation of JSON path expressions will be
  subsequently added.

- Bring automatic type inference and conversion for untyped
  values (e.g. CSV data).
This commit is contained in:
Aditya Manthramurthy
2019-01-28 17:59:48 -08:00
committed by Harshavardhana
parent 0a28c28a8c
commit 2786055df4
65 changed files with 6405 additions and 18231 deletions

19
vendor/github.com/alecthomas/participle/COPYING generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2017 Alec Thomas
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

345
vendor/github.com/alecthomas/participle/README.md generated vendored Normal file
View File

@@ -0,0 +1,345 @@
# A dead simple parser package for Go
[![Godoc](https://godoc.org/github.com/alecthomas/participle?status.svg)](http://godoc.org/github.com/alecthomas/participle) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/participle.svg)](https://circleci.com/gh/alecthomas/participle)
[![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/participle)](https://goreportcard.com/report/github.com/alecthomas/participle) [![Gitter chat](https://badges.gitter.im/alecthomas.png)](https://gitter.im/alecthomas/Lobby)
<!-- TOC -->
1. [Introduction](#introduction)
2. [Limitations](#limitations)
3. [Tutorial](#tutorial)
4. [Overview](#overview)
5. [Annotation syntax](#annotation-syntax)
6. [Capturing](#capturing)
7. [Streaming](#streaming)
8. [Lexing](#lexing)
9. [Options](#options)
10. [Examples](#examples)
11. [Performance](#performance)
<!-- /TOC -->
<a id="markdown-introduction" name="introduction"></a>
## Introduction
The goal of this package is to provide a simple, idiomatic and elegant way of
defining parsers in Go.
Participle's method of defining grammars should be familiar to any Go
programmer who has used the `encoding/json` package: struct field tags define
what and how input is mapped to those same fields. This is not unusual for Go
encoders, but is unusual for a parser.
<a id="markdown-limitations" name="limitations"></a>
## Limitations
Participle parsers are recursive descent. Among other things, this means that they do not support left recursion.
There is an experimental lookahead option for using precomputed lookahead
tables for disambiguation. You can enable this with the parser option
`participle.UseLookahead()`.
Left recursion must be eliminated by restructuring your grammar.
<a id="markdown-tutorial" name="tutorial"></a>
## Tutorial
A [tutorial](TUTORIAL.md) is available, walking through the creation of an .ini parser.
<a id="markdown-overview" name="overview"></a>
## Overview
A grammar is an annotated Go structure used to both define the parser grammar,
and be the AST output by the parser. As an example, following is the final INI
parser from the tutorial.
```go
type INI struct {
Properties []*Property `{ @@ }`
Sections []*Section `{ @@ }`
}
type Section struct {
Identifier string `"[" @Ident "]"`
Properties []*Property `{ @@ }`
}
type Property struct {
Key string `@Ident "="`
Value *Value `@@`
}
type Value struct {
String *string ` @String`
Number *float64 `| @Float`
}
```
> **Note:** Participle also supports named struct tags (eg. <code>Hello string &#96;parser:"@Ident"&#96;</code>).
A parser is constructed from a grammar and a lexer:
```go
parser, err := participle.Build(&INI{})
```
Once constructed, the parser is applied to input to produce an AST:
```go
ast := &INI{}
err := parser.ParseString("size = 10", ast)
// ast == &INI{
// Properties: []*Property{
// {Key: "size", Value: &Value{Number: &10}},
// },
// }
```
<a id="markdown-annotation-syntax" name="annotation-syntax"></a>
## Annotation syntax
- `@<expr>` Capture expression into the field.
- `@@` Recursively capture using the fields own type.
- `<identifier>` Match named lexer token.
- `( ... )` Group.
- `"..."` Match the literal (note that the lexer must emit tokens matching this literal exactly).
- `"...":<identifier>` Match the literal, specifying the exact lexer token type to match.
- `<expr> <expr> ...` Match expressions.
- `<expr> | <expr>` Match one of the alternatives.
The following modifiers can be used after any expression:
- `*` Expression can match zero or more times.
- `+` Expression must match one or more times.
- `?` Expression can match zero or once.
- `!` Require a non-empty match (this is useful with a sequence of optional matches eg. `("a"? "b"? "c"?)!`).
Supported but deprecated:
- `{ ... }` Match 0 or more times (**DEPRECATED** - prefer `( ... )*`).
- `[ ... ]` Optional (**DEPRECATED** - prefer `( ... )?`).
Notes:
- Each struct is a single production, with each field applied in sequence.
- `@<expr>` is the mechanism for capturing matches into the field.
- if a struct field is not keyed with "parser", the entire struct tag
will be used as the grammar fragment. This allows the grammar syntax to remain
clear and simple to maintain.
<a id="markdown-capturing" name="capturing"></a>
## Capturing
Prefixing any expression in the grammar with `@` will capture matching values
for that expression into the corresponding field.
For example:
```go
// The grammar definition.
type Grammar struct {
Hello string `@Ident`
}
// The source text to parse.
source := "world"
// After parsing, the resulting AST.
result == &Grammar{
Hello: "world",
}
```
For slice and string fields, each instance of `@` will accumulate into the
field (including repeated patterns). Accumulation into other types is not
supported.
A successful capture match into a boolean field will set the field to true.
For integer and floating point types, a successful capture will be parsed
with `strconv.ParseInt()` and `strconv.ParseBool()` respectively.
Custom control of how values are captured into fields can be achieved by a
field type implementing the `Capture` interface (`Capture(values []string)
error`).
<a id="markdown-streaming" name="streaming"></a>
## Streaming
Participle supports streaming parsing. Simply pass a channel of your grammar into
`Parse*()`. The grammar will be repeatedly parsed and sent to the channel. Note that
the `Parse*()` call will not return until parsing completes, so it should generally be
started in a goroutine.
```go
type token struct {
Str string ` @Ident`
Num int `| @Int`
}
parser, err := participle.Build(&token{})
tokens := make(chan *token, 128)
err := parser.ParseString(`hello 10 11 12 world`, tokens)
for token := range tokens {
fmt.Printf("%#v\n", token)
}
```
<a id="markdown-lexing" name="lexing"></a>
## Lexing
Participle operates on tokens and thus relies on a lexer to convert character
streams to tokens.
Three lexers are provided, varying in speed and flexibility. The fastest lexer
is based on the [text/scanner](https://golang.org/pkg/text/scanner/) package
but only allows tokens provided by that package. Next fastest is the regexp
lexer (`lexer.Regexp()`). The slowest is currently the EBNF based lexer, but it has a large potential for optimisation through code generation.
To use your own Lexer you will need to implement two interfaces:
[Definition](https://godoc.org/github.com/alecthomas/participle/lexer#Definition)
and [Lexer](https://godoc.org/github.com/alecthomas/participle/lexer#Lexer).
<a id="markdown-options" name="options"></a>
## Options
The Parser's behaviour can be configured via [Options](https://godoc.org/github.com/alecthomas/participle#Option).
<a id="markdown-examples" name="examples"></a>
## Examples
There are several [examples](https://github.com/alecthomas/participle/tree/master/_examples) included:
Example | Description
--------|---------------
[BASIC](https://github.com/alecthomas/participle/tree/master/_examples/basic) | A lexer, parser and interpreter for a [rudimentary dialect](https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora058.html) of BASIC.
[EBNF](https://github.com/alecthomas/participle/tree/master/_examples/ebnf) | Parser for the form of EBNF used by Go.
[Expr](https://github.com/alecthomas/participle/tree/master/_examples/expr) | A basic mathematical expression parser and evaluator.
[GraphQL](https://github.com/alecthomas/participle/tree/master/_examples/graphql) | Lexer+parser for GraphQL schemas
[HCL](https://github.com/alecthomas/participle/tree/master/_examples/hcl) | A parser for the [HashiCorp Configuration Language](https://github.com/hashicorp/hcl).
[INI](https://github.com/alecthomas/participle/tree/master/_examples/ini) | An INI file parser.
[Protobuf](https://github.com/alecthomas/participle/tree/master/_examples/protobuf) | A full [Protobuf](https://developers.google.com/protocol-buffers/) version 2 and 3 parser.
[SQL](https://github.com/alecthomas/participle/tree/master/_examples/sql) | A *very* rudimentary SQL SELECT parser.
[Thrift](https://github.com/alecthomas/participle/tree/master/_examples/thrift) | A full [Thrift](https://thrift.apache.org/docs/idl) parser.
[TOML](https://github.com/alecthomas/participle/blob/master/_examples/toml/main.go) | A [TOML](https://github.com/toml-lang/toml) parser.
Included below is a full GraphQL lexer and parser:
```go
package main
import (
"os"
"github.com/alecthomas/kong"
"github.com/alecthomas/repr"
"github.com/alecthomas/participle"
"github.com/alecthomas/participle/lexer"
"github.com/alecthomas/participle/lexer/ebnf"
)
type File struct {
Entries []*Entry `{ @@ }`
}
type Entry struct {
Type *Type ` @@`
Schema *Schema `| @@`
Enum *Enum `| @@`
Scalar string `| "scalar" @Ident`
}
type Enum struct {
Name string `"enum" @Ident`
Cases []string `"{" { @Ident } "}"`
}
type Schema struct {
Fields []*Field `"schema" "{" { @@ } "}"`
}
type Type struct {
Name string `"type" @Ident`
Implements string `[ "implements" @Ident ]`
Fields []*Field `"{" { @@ } "}"`
}
type Field struct {
Name string `@Ident`
Arguments []*Argument `[ "(" [ @@ { "," @@ } ] ")" ]`
Type *TypeRef `":" @@`
Annotation string `[ "@" @Ident ]`
}
type Argument struct {
Name string `@Ident`
Type *TypeRef `":" @@`
Default *Value `[ "=" @@ ]`
}
type TypeRef struct {
Array *TypeRef `( "[" @@ "]"`
Type string ` | @Ident )`
NonNullable bool `[ @"!" ]`
}
type Value struct {
Symbol string `@Ident`
}
var (
graphQLLexer = lexer.Must(ebnf.New(`
Comment = ("#" | "//") { "\u0000"…"\uffff"-"\n" } .
Ident = (alpha | "_") { "_" | alpha | digit } .
Number = ("." | digit) {"." | digit} .
Whitespace = " " | "\t" | "\n" | "\r" .
Punct = "!"…"/" | ":"…"@" | "["…`+"\"`\""+` | "{"…"~" .
alpha = "a"…"z" | "A"…"Z" .
digit = "0"…"9" .
`))
parser = participle.MustBuild(&File{},
participle.Lexer(graphQLLexer),
participle.Elide("Comment", "Whitespace"),
)
cli struct {
Files []string `arg:"" type:"existingfile" required:"" help:"GraphQL schema files to parse."`
}
)
func main() {
ctx := kong.Parse(&cli)
for _, file := range cli.Files {
ast := &File{}
r, err := os.Open(file)
ctx.FatalIfErrorf(err)
err = parser.Parse(r, ast)
r.Close()
repr.Println(ast)
ctx.FatalIfErrorf(err)
}
}
```
<a id="markdown-performance" name="performance"></a>
## Performance
One of the included examples is a complete Thrift parser
(shell-style comments are not supported). This gives
a convenient baseline for comparing to the PEG based
[pigeon](https://github.com/PuerkitoBio/pigeon), which is the parser used by
[go-thrift](https://github.com/samuel/go-thrift). Additionally, the pigeon
parser is utilising a generated parser, while the participle parser is built at
run time.
You can run the benchmarks yourself, but here's the output on my machine:
BenchmarkParticipleThrift-4 10000 221818 ns/op 48880 B/op 1240 allocs/op
BenchmarkGoThriftParser-4 2000 804709 ns/op 170301 B/op 3086 allocs/op
On a real life codebase of 47K lines of Thrift, Participle takes 200ms and go-
thrift takes 630ms, which aligns quite closely with the benchmarks.

255
vendor/github.com/alecthomas/participle/TUTORIAL.md generated vendored Normal file
View File

@@ -0,0 +1,255 @@
# Participle parser tutorial
<!-- MarkdownTOC -->
1. [Introduction](#introduction)
1. [The complete grammar](#the-complete-grammar)
1. [Root of the .ini AST \(structure, fields\)](#root-of-the-ini-ast-structure-fields)
1. [.ini properties \(named tokens, capturing, literals\)](#ini-properties-named-tokens-capturing-literals)
1. [.ini property values \(alternates, recursive structs, sequences\)](#ini-property-values-alternates-recursive-structs-sequences)
1. [Complete, but limited, .ini grammar \(top-level properties only\)](#complete-but-limited-ini-grammar-top-level-properties-only)
1. [Extending our grammar to support sections](#extending-our-grammar-to-support-sections)
1. [\(Optional\) Source positional information](#optional-source-positional-information)
1. [Parsing using our grammar](#parsing-using-our-grammar)
<!-- /MarkdownTOC -->
## Introduction
Writing a parser in Participle typically involves starting from the "root" of
the AST, annotating fields with the grammar, then recursively expanding until
it is complete. The AST is expressed via Go data types and the grammar is
expressed through struct field tags, as a form of EBNF.
The parser we're going to create for this tutorial parses .ini files
like this:
```ini
age = 21
name = "Bob Smith"
[address]
city = "Beverly Hills"
postal_code = 90210
```
## The complete grammar
I think it's useful to see the complete grammar first, to see what we're
working towards. Read on below for details.
```go
type INI struct {
Properties []*Property `@@*`
Sections []*Section `@@*`
}
type Section struct {
Identifier string `"[" @Ident "]"`
Properties []*Property `@@*`
}
type Property struct {
Key string `@Ident "="`
Value *Value `@@`
}
type Value struct {
String *string ` @String`
Number *float64 `| @Float`
}
```
## Root of the .ini AST (structure, fields)
The first step is to create a root struct for our grammar. In the case of our
.ini parser, this struct will contain a sequence of properties:
```go
type INI struct {
Properties []*Property
}
type Property struct {
}
```
## .ini properties (named tokens, capturing, literals)
Each property in an .ini file has an identifier key:
```go
type Property struct {
Key string
}
```
The default lexer tokenises Go source code, and includes an `Ident` token type
that matches identifiers. To match this token we simply use the token type
name:
```go
type Property struct {
Key string `Ident`
}
```
This will *match* identifiers, but not *capture* them into the `Key` field. To
capture input tokens into AST fields, prefix any grammar node with `@`:
```go
type Property struct {
Key string `@Ident`
}
```
In .ini files, each key is separated from its value with a literal `=`. To
match a literal, enclose the literal in double quotes:
```go
type Property struct {
Key string `@Ident "="`
}
```
> Note: literals in the grammar must match tokens from the lexer *exactly*. In
> this example if the lexer does not output `=` as a distinct token the
> grammar will not match.
## .ini property values (alternates, recursive structs, sequences)
For the purposes of our example we are only going to support quoted string
and numeric property values. As each value can be *either* a string or a float
we'll need something akin to a sum type. Go's type system cannot express this
directly, so we'll use the common approach of making each element a pointer.
The selected "case" will *not* be nil.
```go
type Value struct {
String *string
Number *float64
}
```
> Note: Participle will hydrate pointers as necessary.
To express matching a set of alternatives we use the `|` operator:
```go
type Value struct {
String *string ` @String`
Number *float64 `| @Float`
}
```
> Note: the grammar can cross fields.
Next, we'll match values and capture them into the `Property`. To recursively
capture structs use `@@` (capture self):
```go
type Property struct {
Key string `@Ident "="`
Value *Value `@@`
}
```
Now that we can parse a `Property` we need to go back to the root of the
grammar. We want to parse 0 or more properties. To do this, we use `<expr>*`.
Participle will accumulate each match into the slice until matching fails,
then move to the next node in the grammar.
```go
type INI struct {
Properties []*Property `@@*`
}
```
> Note: tokens can also be accumulated into strings, appending each match.
## Complete, but limited, .ini grammar (top-level properties only)
We now have a functional, but limited, .ini parser!
```go
type INI struct {
Properties []*Property `@@*`
}
type Property struct {
Key string `@Ident "="`
Value *Value `@@`
}
type Value struct {
String *string ` @String`
Number *float64 `| @Float`
}
```
## Extending our grammar to support sections
Adding support for sections is simply a matter of utilising the constructs
we've just learnt. A section consists of a header identifier, and a sequence
of properties:
```go
type Section struct {
Identifier string `"[" @Ident "]"`
Properties []*Property `@@*`
}
```
Simple!
Now we just add a sequence of `Section`s to our root node:
```go
type INI struct {
Properties []*Property `@@*`
Sections []*Section `@@*`
}
```
And we're done!
## (Optional) Source positional information
If a grammar node includes a field with the name `Pos` and type `lexer.Position`, it will be automatically populated by positional information. eg.
```go
type Value struct {
Pos lexer.Position
String *string ` @String`
Number *float64 `| @Float`
}
```
This is useful for error reporting.
## Parsing using our grammar
To parse with this grammar we first construct the parser (we'll use the
default lexer for now):
```go
parser, err := participle.Build(&INI{})
```
Then create a root node and parse into it with `parser.Parse{,String,Bytes}()`:
```go
ini := &INI{}
err = parser.ParseString(`
age = 21
name = "Bob Smith"
[address]
city = "Beverly Hills"
postal_code = 90210
`, ini)
```
You can find the full example [here](_examples/ini/main.go), alongside
other examples including an SQL `SELECT` parser and a full
[Thrift](https://thrift.apache.org/) parser.

19
vendor/github.com/alecthomas/participle/api.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package participle
import (
"github.com/alecthomas/participle/lexer"
)
// Capture can be implemented by fields in order to transform captured tokens into field values.
type Capture interface {
Capture(values []string) error
}
// The Parseable interface can be implemented by any element in the grammar to provide custom parsing.
type Parseable interface {
// Parse into the receiver.
//
// Should return NextMatch if no tokens matched and parsing should continue.
// Nil should be returned if parsing was successful.
Parse(lex lexer.PeekingLexer) error
}

123
vendor/github.com/alecthomas/participle/context.go generated vendored Normal file
View File

@@ -0,0 +1,123 @@
package participle
import (
"reflect"
"github.com/alecthomas/participle/lexer"
)
type contextFieldSet struct {
pos lexer.Position
strct reflect.Value
field structLexerField
fieldValue []reflect.Value
}
// Context for a single parse.
type parseContext struct {
*rewinder
lookahead int
caseInsensitive map[rune]bool
apply []*contextFieldSet
}
func newParseContext(lex lexer.Lexer, lookahead int, caseInsensitive map[rune]bool) (*parseContext, error) {
rew, err := newRewinder(lex)
if err != nil {
return nil, err
}
return &parseContext{
rewinder: rew,
caseInsensitive: caseInsensitive,
lookahead: lookahead,
}, nil
}
// Defer adds a function to be applied once a branch has been picked.
func (p *parseContext) Defer(pos lexer.Position, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) {
p.apply = append(p.apply, &contextFieldSet{pos, strct, field, fieldValue})
}
// Apply deferred functions.
func (p *parseContext) Apply() error {
for _, apply := range p.apply {
if err := setField(apply.pos, apply.strct, apply.field, apply.fieldValue); err != nil {
return err
}
}
p.apply = nil
return nil
}
// Branch accepts the branch as the correct branch.
func (p *parseContext) Accept(branch *parseContext) {
p.apply = append(p.apply, branch.apply...)
p.rewinder = branch.rewinder
}
// Branch starts a new lookahead branch.
func (p *parseContext) Branch() *parseContext {
branch := &parseContext{}
*branch = *p
branch.apply = nil
branch.rewinder = p.rewinder.Lookahead()
return branch
}
// Stop returns true if parsing should terminate after the given "branch" failed to match.
func (p *parseContext) Stop(branch *parseContext) bool {
if branch.cursor > p.cursor+p.lookahead {
p.Accept(branch)
return true
}
return false
}
type rewinder struct {
cursor, limit int
tokens []lexer.Token
}
func newRewinder(lex lexer.Lexer) (*rewinder, error) {
r := &rewinder{}
for {
t, err := lex.Next()
if err != nil {
return nil, err
}
if t.EOF() {
break
}
r.tokens = append(r.tokens, t)
}
return r, nil
}
func (r *rewinder) Next() (lexer.Token, error) {
if r.cursor >= len(r.tokens) {
return lexer.EOFToken(lexer.Position{}), nil
}
r.cursor++
return r.tokens[r.cursor-1], nil
}
func (r *rewinder) Peek(n int) (lexer.Token, error) {
i := r.cursor + n
if i >= len(r.tokens) {
return lexer.EOFToken(lexer.Position{}), nil
}
return r.tokens[i], nil
}
// Lookahead returns a new rewinder usable for lookahead.
func (r *rewinder) Lookahead() *rewinder {
clone := &rewinder{}
*clone = *r
clone.limit = clone.cursor
return clone
}
// Keep this lookahead rewinder.
func (r *rewinder) Keep() {
r.limit = 0
}

73
vendor/github.com/alecthomas/participle/doc.go generated vendored Normal file
View File

@@ -0,0 +1,73 @@
// Package participle constructs parsers from definitions in struct tags and parses directly into
// those structs. The approach is philosophically similar to how other marshallers work in Go,
// "unmarshalling" an instance of a grammar into a struct.
//
// The supported annotation syntax is:
//
// - `@<expr>` Capture expression into the field.
// - `@@` Recursively capture using the fields own type.
// - `<identifier>` Match named lexer token.
// - `( ... )` Group.
// - `"..."` Match the literal (note that the lexer must emit tokens matching this literal exactly).
// - `"...":<identifier>` Match the literal, specifying the exact lexer token type to match.
// - `<expr> <expr> ...` Match expressions.
// - `<expr> | <expr>` Match one of the alternatives.
//
// The following modifiers can be used after any expression:
//
// - `*` Expression can match zero or more times.
// - `+` Expression must match one or more times.
// - `?` Expression can match zero or once.
// - `!` Require a non-empty match (this is useful with a sequence of optional matches eg. `("a"? "b"? "c"?)!`).
//
// Supported but deprecated:
//
// - `{ ... }` Match 0 or more times (**DEPRECATED** - prefer `( ... )*`).
// - `[ ... ]` Optional (**DEPRECATED** - prefer `( ... )?`).
//
// Here's an example of an EBNF grammar.
//
// type Group struct {
// Expression *Expression `"(" @@ ")"`
// }
//
// type Option struct {
// Expression *Expression `"[" @@ "]"`
// }
//
// type Repetition struct {
// Expression *Expression `"{" @@ "}"`
// }
//
// type Literal struct {
// Start string `@String` // lexer.Lexer token "String"
// End string `("…" @String)?`
// }
//
// type Term struct {
// Name string ` @Ident`
// Literal *Literal `| @@`
// Group *Group `| @@`
// Option *Option `| @@`
// Repetition *Repetition `| @@`
// }
//
// type Sequence struct {
// Terms []*Term `@@+`
// }
//
// type Expression struct {
// Alternatives []*Sequence `@@ ("|" @@)*`
// }
//
// type Expressions []*Expression
//
// type Production struct {
// Name string `@Ident "="`
// Expressions Expressions `@@+ "."`
// }
//
// type EBNF struct {
// Productions []*Production `@@*`
// }
package participle

7
vendor/github.com/alecthomas/participle/go.mod generated vendored Normal file
View File

@@ -0,0 +1,7 @@
module github.com/alecthomas/participle
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
)

6
vendor/github.com/alecthomas/participle/go.sum generated vendored Normal file
View File

@@ -0,0 +1,6 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

324
vendor/github.com/alecthomas/participle/grammar.go generated vendored Normal file
View File

@@ -0,0 +1,324 @@
package participle
import (
"fmt"
"reflect"
"text/scanner"
"github.com/alecthomas/participle/lexer"
)
type generatorContext struct {
lexer.Definition
typeNodes map[reflect.Type]node
symbolsToIDs map[rune]string
}
func newGeneratorContext(lex lexer.Definition) *generatorContext {
return &generatorContext{
Definition: lex,
typeNodes: map[reflect.Type]node{},
symbolsToIDs: lexer.SymbolsByRune(lex),
}
}
// Takes a type and builds a tree of nodes out of it.
func (g *generatorContext) parseType(t reflect.Type) (_ node, returnedError error) {
rt := t
t = indirectType(t)
if n, ok := g.typeNodes[t]; ok {
return n, nil
}
if rt.Implements(parseableType) {
return &parseable{rt.Elem()}, nil
}
if reflect.PtrTo(rt).Implements(parseableType) {
return &parseable{rt}, nil
}
switch t.Kind() {
case reflect.Slice, reflect.Ptr:
t = indirectType(t.Elem())
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected a struct but got %T", t)
}
fallthrough
case reflect.Struct:
slexer, err := lexStruct(t)
if err != nil {
return nil, err
}
out := &strct{typ: t}
g.typeNodes[t] = out // Ensure we avoid infinite recursion.
if slexer.NumField() == 0 {
return nil, fmt.Errorf("can not parse into empty struct %s", t)
}
defer decorate(&returnedError, func() string { return slexer.Field().Name })
e, err := g.parseDisjunction(slexer)
if err != nil {
return nil, err
}
if e == nil {
return nil, fmt.Errorf("no grammar found in %s", t)
}
if token, _ := slexer.Peek(); !token.EOF() {
return nil, fmt.Errorf("unexpected input %q", token.Value)
}
out.expr = e
return out, nil
}
return nil, fmt.Errorf("%s should be a struct or should implement the Parseable interface", t)
}
func (g *generatorContext) parseDisjunction(slexer *structLexer) (node, error) {
out := &disjunction{}
for {
n, err := g.parseSequence(slexer)
if err != nil {
return nil, err
}
out.nodes = append(out.nodes, n)
if token, _ := slexer.Peek(); token.Type != '|' {
break
}
_, err = slexer.Next() // |
if err != nil {
return nil, err
}
}
if len(out.nodes) == 1 {
return out.nodes[0], nil
}
return out, nil
}
func (g *generatorContext) parseSequence(slexer *structLexer) (node, error) {
head := &sequence{}
cursor := head
loop:
for {
if token, err := slexer.Peek(); err != nil {
return nil, err
} else if token.Type == lexer.EOF {
break loop
}
term, err := g.parseTerm(slexer)
if err != nil {
return nil, err
}
if term == nil {
break loop
}
if cursor.node == nil {
cursor.head = true
cursor.node = term
} else {
cursor.next = &sequence{node: term}
cursor = cursor.next
}
}
if head.node == nil {
return nil, nil
}
if head.next == nil {
return head.node, nil
}
return head, nil
}
func (g *generatorContext) parseTermNoModifiers(slexer *structLexer) (node, error) {
t, err := slexer.Peek()
if err != nil {
return nil, err
}
var out node
switch t.Type {
case '@':
out, err = g.parseCapture(slexer)
case scanner.String, scanner.RawString, scanner.Char:
out, err = g.parseLiteral(slexer)
case '[':
return g.parseOptional(slexer)
case '{':
return g.parseRepetition(slexer)
case '(':
out, err = g.parseGroup(slexer)
case scanner.Ident:
out, err = g.parseReference(slexer)
case lexer.EOF:
_, _ = slexer.Next()
return nil, nil
default:
return nil, nil
}
return out, err
}
func (g *generatorContext) parseTerm(slexer *structLexer) (node, error) {
out, err := g.parseTermNoModifiers(slexer)
if err != nil {
return nil, err
}
return g.parseModifier(slexer, out)
}
// Parse modifiers: ?, *, + and/or !
func (g *generatorContext) parseModifier(slexer *structLexer, expr node) (node, error) {
out := &group{expr: expr}
t, err := slexer.Peek()
if err != nil {
return nil, err
}
switch t.Type {
case '!':
out.mode = groupMatchNonEmpty
case '+':
out.mode = groupMatchOneOrMore
case '*':
out.mode = groupMatchZeroOrMore
case '?':
out.mode = groupMatchZeroOrOne
default:
return expr, nil
}
_, _ = slexer.Next()
return out, nil
}
// @<expression> captures <expression> into the current field.
func (g *generatorContext) parseCapture(slexer *structLexer) (node, error) {
_, _ = slexer.Next()
token, err := slexer.Peek()
if err != nil {
return nil, err
}
field := slexer.Field()
if token.Type == '@' {
_, _ = slexer.Next()
n, err := g.parseType(field.Type)
if err != nil {
return nil, err
}
return &capture{field, n}, nil
}
if indirectType(field.Type).Kind() == reflect.Struct && !field.Type.Implements(captureType) {
return nil, fmt.Errorf("structs can only be parsed with @@ or by implementing the Capture interface")
}
n, err := g.parseTermNoModifiers(slexer)
if err != nil {
return nil, err
}
return &capture{field, n}, nil
}
// A reference in the form <identifier> refers to a named token from the lexer.
func (g *generatorContext) parseReference(slexer *structLexer) (node, error) { // nolint: interfacer
token, err := slexer.Next()
if err != nil {
return nil, err
}
if token.Type != scanner.Ident {
return nil, fmt.Errorf("expected identifier but got %q", token)
}
typ, ok := g.Symbols()[token.Value]
if !ok {
return nil, fmt.Errorf("unknown token type %q", token)
}
return &reference{typ: typ, identifier: token.Value}, nil
}
// [ <expression> ] optionally matches <expression>.
func (g *generatorContext) parseOptional(slexer *structLexer) (node, error) {
_, _ = slexer.Next() // [
disj, err := g.parseDisjunction(slexer)
if err != nil {
return nil, err
}
n := &group{expr: disj, mode: groupMatchZeroOrOne}
next, err := slexer.Next()
if err != nil {
return nil, err
}
if next.Type != ']' {
return nil, fmt.Errorf("expected ] but got %q", next)
}
return n, nil
}
// { <expression> } matches 0 or more repititions of <expression>
func (g *generatorContext) parseRepetition(slexer *structLexer) (node, error) {
_, _ = slexer.Next() // {
disj, err := g.parseDisjunction(slexer)
if err != nil {
return nil, err
}
n := &group{expr: disj, mode: groupMatchZeroOrMore}
next, err := slexer.Next()
if err != nil {
return nil, err
}
if next.Type != '}' {
return nil, fmt.Errorf("expected } but got %q", next)
}
return n, nil
}
// ( <expression> ) groups a sub-expression
func (g *generatorContext) parseGroup(slexer *structLexer) (node, error) {
_, _ = slexer.Next() // (
disj, err := g.parseDisjunction(slexer)
if err != nil {
return nil, err
}
next, err := slexer.Next() // )
if err != nil {
return nil, err
}
if next.Type != ')' {
return nil, fmt.Errorf("expected ) but got %q", next)
}
return &group{expr: disj}, nil
}
// A literal string.
//
// Note that for this to match, the tokeniser must be able to produce this string. For example,
// if the tokeniser only produces individual characters but the literal is "hello", or vice versa.
func (g *generatorContext) parseLiteral(lex *structLexer) (node, error) { // nolint: interfacer
token, err := lex.Next()
if err != nil {
return nil, err
}
if token.Type != scanner.String && token.Type != scanner.RawString && token.Type != scanner.Char {
return nil, fmt.Errorf("expected quoted string but got %q", token)
}
s := token.Value
t := rune(-1)
token, err = lex.Peek()
if err != nil {
return nil, err
}
if token.Value == ":" && (token.Type == scanner.Char || token.Type == ':') {
_, _ = lex.Next()
token, err = lex.Next()
if err != nil {
return nil, err
}
if token.Type != scanner.Ident {
return nil, fmt.Errorf("expected identifier for literal type constraint but got %q", token)
}
var ok bool
t, ok = g.Symbols()[token.Value]
if !ok {
return nil, fmt.Errorf("unknown token type %q in literal type constraint", token)
}
}
return &literal{s: s, t: t, tt: g.symbolsToIDs[t]}, nil
}
func indirectType(t reflect.Type) reflect.Type {
if t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice {
return indirectType(t.Elem())
}
return t
}

19
vendor/github.com/alecthomas/participle/lexer/doc.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// Package lexer defines interfaces and implementations used by Participle to perform lexing.
//
// The primary interfaces are Definition and Lexer. There are three implementations of these
// interfaces:
//
// TextScannerLexer is based on text/scanner. This is the fastest, but least flexible, in that
// tokens are restricted to those supported by that package. It can scan about 5M tokens/second on a
// late 2013 15" MacBook Pro.
//
// The second lexer is constructed via the Regexp() function, mapping regexp capture groups
// to tokens. The complete input source is read into memory, so it is unsuitable for large inputs.
//
// The final lexer provided accepts a lexical grammar in EBNF. Each capitalised production is a
// lexical token supported by the resulting Lexer. This is very flexible, but a bit slower, scanning
// around 730K tokens/second on the same machine, though it is currently completely unoptimised.
// This could/should be converted to a table-based lexer.
//
// Lexer implementations must use Panic/Panicf to report errors.
package lexer

View File

@@ -0,0 +1,26 @@
package lexer
import "fmt"
// Error represents an error while parsing.
type Error struct {
Message string
Pos Position
}
// Errorf creats a new Error at the given position.
func Errorf(pos Position, format string, args ...interface{}) *Error {
return &Error{
Message: fmt.Sprintf(format, args...),
Pos: pos,
}
}
// Error complies with the error interface and reports the position of an error.
func (e *Error) Error() string {
filename := e.Pos.Filename
if filename == "" {
filename = "<source>"
}
return fmt.Sprintf("%s:%d:%d: %s", filename, e.Pos.Line, e.Pos.Column, e.Message)
}

150
vendor/github.com/alecthomas/participle/lexer/lexer.go generated vendored Normal file
View File

@@ -0,0 +1,150 @@
package lexer
import (
"fmt"
"io"
)
const (
// EOF represents an end of file.
EOF rune = -(iota + 1)
)
// EOFToken creates a new EOF token at the given position.
func EOFToken(pos Position) Token {
return Token{Type: EOF, Pos: pos}
}
// Definition provides the parser with metadata for a lexer.
type Definition interface {
// Lex an io.Reader.
Lex(io.Reader) (Lexer, error)
// Symbols returns a map of symbolic names to the corresponding pseudo-runes for those symbols.
// This is the same approach as used by text/scanner. For example, "EOF" might have the rune
// value of -1, "Ident" might be -2, and so on.
Symbols() map[string]rune
}
// A Lexer returns tokens from a source.
type Lexer interface {
// Next consumes and returns the next token.
Next() (Token, error)
}
// A PeekingLexer returns tokens from a source and allows peeking.
type PeekingLexer interface {
Lexer
// Peek at the next token.
Peek(n int) (Token, error)
}
// SymbolsByRune returns a map of lexer symbol names keyed by rune.
func SymbolsByRune(def Definition) map[rune]string {
out := map[rune]string{}
for s, r := range def.Symbols() {
out[r] = s
}
return out
}
// NameOfReader attempts to retrieve the filename of a reader.
func NameOfReader(r interface{}) string {
if nr, ok := r.(interface{ Name() string }); ok {
return nr.Name()
}
return ""
}
// Must takes the result of a Definition constructor call and returns the definition, but panics if
// it errors
//
// eg.
//
// lex = lexer.Must(lexer.Build(`Symbol = "symbol" .`))
func Must(def Definition, err error) Definition {
if err != nil {
panic(err)
}
return def
}
// ConsumeAll reads all tokens from a Lexer.
func ConsumeAll(lexer Lexer) ([]Token, error) {
tokens := []Token{}
for {
token, err := lexer.Next()
if err != nil {
return nil, err
}
tokens = append(tokens, token)
if token.Type == EOF {
return tokens, nil
}
}
}
// Position of a token.
type Position struct {
Filename string
Offset int
Line int
Column int
}
func (p Position) GoString() string {
return fmt.Sprintf("Position{Filename: %q, Offset: %d, Line: %d, Column: %d}",
p.Filename, p.Offset, p.Line, p.Column)
}
func (p Position) String() string {
filename := p.Filename
if filename == "" {
filename = "<source>"
}
return fmt.Sprintf("%s:%d:%d", filename, p.Line, p.Column)
}
// A Token returned by a Lexer.
type Token struct {
// Type of token. This is the value keyed by symbol as returned by Definition.Symbols().
Type rune
Value string
Pos Position
}
// RuneToken represents a rune as a Token.
func RuneToken(r rune) Token {
return Token{Type: r, Value: string(r)}
}
// EOF returns true if this Token is an EOF token.
func (t Token) EOF() bool {
return t.Type == EOF
}
func (t Token) String() string {
if t.EOF() {
return "<EOF>"
}
return t.Value
}
func (t Token) GoString() string {
return fmt.Sprintf("Token{%d, %q}", t.Type, t.Value)
}
// MakeSymbolTable builds a lookup table for checking token ID existence.
//
// For each symbolic name in "types", the returned map will contain the corresponding token ID as a key.
func MakeSymbolTable(def Definition, types ...string) (map[rune]bool, error) {
symbols := def.Symbols()
table := map[rune]bool{}
for _, symbol := range types {
rn, ok := symbols[symbol]
if !ok {
return nil, fmt.Errorf("lexer does not support symbol %q", symbol)
}
table[rn] = true
}
return table, nil
}

37
vendor/github.com/alecthomas/participle/lexer/peek.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package lexer
// Upgrade a Lexer to a PeekingLexer with arbitrary lookahead.
func Upgrade(lexer Lexer) PeekingLexer {
if peeking, ok := lexer.(PeekingLexer); ok {
return peeking
}
return &lookaheadLexer{Lexer: lexer}
}
type lookaheadLexer struct {
Lexer
peeked []Token
}
func (l *lookaheadLexer) Peek(n int) (Token, error) {
for len(l.peeked) <= n {
t, err := l.Lexer.Next()
if err != nil {
return Token{}, err
}
if t.EOF() {
return t, nil
}
l.peeked = append(l.peeked, t)
}
return l.peeked[n], nil
}
func (l *lookaheadLexer) Next() (Token, error) {
if len(l.peeked) > 0 {
t := l.peeked[0]
l.peeked = l.peeked[1:]
return t, nil
}
return l.Lexer.Next()
}

112
vendor/github.com/alecthomas/participle/lexer/regexp.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
package lexer
import (
"bytes"
"io"
"io/ioutil"
"regexp"
"unicode/utf8"
)
var eolBytes = []byte("\n")
type regexpDefinition struct {
re *regexp.Regexp
symbols map[string]rune
}
// Regexp creates a lexer definition from a regular expression.
//
// Each named sub-expression in the regular expression matches a token. Anonymous sub-expressions
// will be matched and discarded.
//
// eg.
//
// def, err := Regexp(`(?P<Ident>[a-z]+)|(\s+)|(?P<Number>\d+)`)
func Regexp(pattern string) (Definition, error) {
re, err := regexp.Compile(pattern)
if err != nil {
return nil, err
}
symbols := map[string]rune{
"EOF": EOF,
}
for i, sym := range re.SubexpNames()[1:] {
if sym != "" {
symbols[sym] = EOF - 1 - rune(i)
}
}
return &regexpDefinition{re: re, symbols: symbols}, nil
}
func (d *regexpDefinition) Lex(r io.Reader) (Lexer, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
return &regexpLexer{
pos: Position{
Filename: NameOfReader(r),
Line: 1,
Column: 1,
},
b: b,
re: d.re,
names: d.re.SubexpNames(),
}, nil
}
func (d *regexpDefinition) Symbols() map[string]rune {
return d.symbols
}
type regexpLexer struct {
pos Position
b []byte
re *regexp.Regexp
names []string
}
func (r *regexpLexer) Next() (Token, error) {
nextToken:
for len(r.b) != 0 {
matches := r.re.FindSubmatchIndex(r.b)
if matches == nil || matches[0] != 0 {
rn, _ := utf8.DecodeRune(r.b)
return Token{}, Errorf(r.pos, "invalid token %q", rn)
}
match := r.b[:matches[1]]
token := Token{
Pos: r.pos,
Value: string(match),
}
// Update lexer state.
r.pos.Offset += matches[1]
lines := bytes.Count(match, eolBytes)
r.pos.Line += lines
// Update column.
if lines == 0 {
r.pos.Column += utf8.RuneCount(match)
} else {
r.pos.Column = utf8.RuneCount(match[bytes.LastIndex(match, eolBytes):])
}
// Move slice along.
r.b = r.b[matches[1]:]
// Finally, assign token type. If it is not a named group, we continue to the next token.
for i := 2; i < len(matches); i += 2 {
if matches[i] != -1 {
if r.names[i/2] == "" {
continue nextToken
}
token.Type = EOF - rune(i/2)
break
}
}
return token, nil
}
return EOFToken(r.pos), nil
}

View File

@@ -0,0 +1,125 @@
package lexer
import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
"text/scanner"
"unicode/utf8"
)
// TextScannerLexer is a lexer that uses the text/scanner module.
var (
TextScannerLexer Definition = &defaultDefinition{}
// DefaultDefinition defines properties for the default lexer.
DefaultDefinition = TextScannerLexer
)
type defaultDefinition struct{}
func (d *defaultDefinition) Lex(r io.Reader) (Lexer, error) {
return Lex(r), nil
}
func (d *defaultDefinition) Symbols() map[string]rune {
return map[string]rune{
"EOF": scanner.EOF,
"Char": scanner.Char,
"Ident": scanner.Ident,
"Int": scanner.Int,
"Float": scanner.Float,
"String": scanner.String,
"RawString": scanner.RawString,
"Comment": scanner.Comment,
}
}
// textScannerLexer is a Lexer based on text/scanner.Scanner
type textScannerLexer struct {
scanner *scanner.Scanner
filename string
err error
}
// Lex an io.Reader with text/scanner.Scanner.
//
// This provides very fast lexing of source code compatible with Go tokens.
//
// Note that this differs from text/scanner.Scanner in that string tokens will be unquoted.
func Lex(r io.Reader) Lexer {
lexer := lexWithScanner(r, &scanner.Scanner{})
lexer.scanner.Error = func(s *scanner.Scanner, msg string) {
// This is to support single quoted strings. Hacky.
if msg != "illegal char literal" {
lexer.err = Errorf(Position(lexer.scanner.Pos()), msg)
}
}
return lexer
}
// LexWithScanner creates a Lexer from a user-provided scanner.Scanner.
//
// Useful if you need to customise the Scanner.
func LexWithScanner(r io.Reader, scan *scanner.Scanner) Lexer {
return lexWithScanner(r, scan)
}
func lexWithScanner(r io.Reader, scan *scanner.Scanner) *textScannerLexer {
lexer := &textScannerLexer{
filename: NameOfReader(r),
scanner: scan,
}
lexer.scanner.Init(r)
return lexer
}
// LexBytes returns a new default lexer over bytes.
func LexBytes(b []byte) Lexer {
return Lex(bytes.NewReader(b))
}
// LexString returns a new default lexer over a string.
func LexString(s string) Lexer {
return Lex(strings.NewReader(s))
}
func (t *textScannerLexer) Next() (Token, error) {
typ := t.scanner.Scan()
text := t.scanner.TokenText()
pos := Position(t.scanner.Position)
pos.Filename = t.filename
if t.err != nil {
return Token{}, t.err
}
return textScannerTransform(Token{
Type: typ,
Value: text,
Pos: pos,
})
}
func textScannerTransform(token Token) (Token, error) {
// Unquote strings.
switch token.Type {
case scanner.Char:
// FIXME(alec): This is pretty hacky...we convert a single quoted char into a double
// quoted string in order to support single quoted strings.
token.Value = fmt.Sprintf("\"%s\"", token.Value[1:len(token.Value)-1])
fallthrough
case scanner.String:
s, err := strconv.Unquote(token.Value)
if err != nil {
return Token{}, Errorf(token.Pos, "%s: %q", err.Error(), token.Value)
}
token.Value = s
if token.Type == scanner.Char && utf8.RuneCountInString(s) > 1 {
token.Type = scanner.String
}
case scanner.RawString:
token.Value = token.Value[1 : len(token.Value)-1]
}
return token, nil
}

118
vendor/github.com/alecthomas/participle/map.go generated vendored Normal file
View File

@@ -0,0 +1,118 @@
package participle
import (
"errors"
"io"
"strconv"
"strings"
"github.com/alecthomas/participle/lexer"
)
type mapperByToken struct {
symbols []string
mapper Mapper
}
// DropToken can be returned by a Mapper to remove a token from the stream.
var DropToken = errors.New("drop token") // nolint: golint
// Mapper function for mutating tokens before being applied to the AST.
//
// If the Mapper func returns an error of DropToken, the token will be removed from the stream.
type Mapper func(token lexer.Token) (lexer.Token, error)
// Map is an Option that configures the Parser to apply a mapping function to each Token from the lexer.
//
// This can be useful to eg. upper-case all tokens of a certain type, or dequote strings.
//
// "symbols" specifies the token symbols that the Mapper will be applied to. If empty, all tokens will be mapped.
func Map(mapper Mapper, symbols ...string) Option {
return func(p *Parser) error {
p.mappers = append(p.mappers, mapperByToken{
mapper: mapper,
symbols: symbols,
})
return nil
}
}
// Unquote applies strconv.Unquote() to tokens of the given types.
//
// Tokens of type "String" will be unquoted if no other types are provided.
func Unquote(types ...string) Option {
if len(types) == 0 {
types = []string{"String"}
}
return Map(func(t lexer.Token) (lexer.Token, error) {
value, err := unquote(t.Value)
if err != nil {
return t, lexer.Errorf(t.Pos, "invalid quoted string %q: %s", t.Value, err.Error())
}
t.Value = value
return t, nil
}, types...)
}
func unquote(s string) (string, error) {
quote := s[0]
s = s[1 : len(s)-1]
out := ""
for s != "" {
value, _, tail, err := strconv.UnquoteChar(s, quote)
if err != nil {
return "", err
}
s = tail
out += string(value)
}
return out, nil
}
// Upper is an Option that upper-cases all tokens of the given type. Useful for case normalisation.
func Upper(types ...string) Option {
return Map(func(token lexer.Token) (lexer.Token, error) {
token.Value = strings.ToUpper(token.Value)
return token, nil
}, types...)
}
// Elide drops tokens of the specified types.
func Elide(types ...string) Option {
return Map(func(token lexer.Token) (lexer.Token, error) {
return lexer.Token{}, DropToken
}, types...)
}
// Apply a Mapping to all tokens coming out of a Lexer.
type mappingLexerDef struct {
lexer.Definition
mapper Mapper
}
func (m *mappingLexerDef) Lex(r io.Reader) (lexer.Lexer, error) {
lexer, err := m.Definition.Lex(r)
if err != nil {
return nil, err
}
return &mappingLexer{lexer, m.mapper}, nil
}
type mappingLexer struct {
lexer.Lexer
mapper Mapper
}
func (m *mappingLexer) Next() (lexer.Token, error) {
for {
t, err := m.Lexer.Next()
if err != nil {
return t, err
}
t, err = m.mapper(t)
if err == DropToken {
continue
}
return t, err
}
}

575
vendor/github.com/alecthomas/participle/nodes.go generated vendored Normal file
View File

@@ -0,0 +1,575 @@
package participle
import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/alecthomas/participle/lexer"
)
var (
// MaxIterations limits the number of elements capturable by {}.
MaxIterations = 1000000
positionType = reflect.TypeOf(lexer.Position{})
captureType = reflect.TypeOf((*Capture)(nil)).Elem()
parseableType = reflect.TypeOf((*Parseable)(nil)).Elem()
// NextMatch should be returned by Parseable.Parse() method implementations to indicate
// that the node did not match and that other matches should be attempted, if appropriate.
NextMatch = errors.New("no match") // nolint: golint
)
// A node in the grammar.
type node interface {
// Parse from scanner into value.
//
// Returned slice will be nil if the node does not match.
Parse(ctx *parseContext, parent reflect.Value) ([]reflect.Value, error)
// Return a decent string representation of the Node.
String() string
}
func decorate(err *error, name func() string) {
if *err == nil {
return
}
switch realError := (*err).(type) {
case *lexer.Error:
*err = &lexer.Error{Message: name() + ": " + realError.Message, Pos: realError.Pos}
default:
*err = fmt.Errorf("%s: %s", name(), realError)
}
}
// A node that proxies to an implementation that implements the Parseable interface.
type parseable struct {
t reflect.Type
}
func (p *parseable) String() string { return stringer(p) }
func (p *parseable) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
rv := reflect.New(p.t)
v := rv.Interface().(Parseable)
err = v.Parse(ctx)
if err != nil {
if err == NextMatch {
return nil, nil
}
return nil, err
}
return []reflect.Value{rv.Elem()}, nil
}
type strct struct {
typ reflect.Type
expr node
}
func (s *strct) String() string { return stringer(s) }
func (s *strct) maybeInjectPos(pos lexer.Position, v reflect.Value) {
if f := v.FieldByName("Pos"); f.IsValid() && f.Type() == positionType {
f.Set(reflect.ValueOf(pos))
}
}
func (s *strct) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
sv := reflect.New(s.typ).Elem()
t, err := ctx.Peek(0)
if err != nil {
return nil, err
}
s.maybeInjectPos(t.Pos, sv)
if out, err = s.expr.Parse(ctx, sv); err != nil {
_ = ctx.Apply()
return []reflect.Value{sv}, err
} else if out == nil {
return nil, nil
}
return []reflect.Value{sv}, ctx.Apply()
}
type groupMatchMode int
const (
groupMatchOnce groupMatchMode = iota
groupMatchZeroOrOne = iota
groupMatchZeroOrMore = iota
groupMatchOneOrMore = iota
groupMatchNonEmpty = iota
)
// ( <expr> ) - match once
// ( <expr> )* - match zero or more times
// ( <expr> )+ - match one or more times
// ( <expr> )? - match zero or once
// ( <expr> )! - must be a non-empty match
//
// The additional modifier "!" forces the content of the group to be non-empty if it does match.
type group struct {
expr node
mode groupMatchMode
}
func (g *group) String() string { return stringer(g) }
func (g *group) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
// Configure min/max matches.
min := 1
max := 1
switch g.mode {
case groupMatchNonEmpty:
out, err = g.expr.Parse(ctx, parent)
if err != nil {
return out, err
}
if len(out) == 0 {
t, _ := ctx.Peek(0)
return out, lexer.Errorf(t.Pos, "sub-expression %s cannot be empty", g)
}
return out, nil
case groupMatchOnce:
return g.expr.Parse(ctx, parent)
case groupMatchZeroOrOne:
min = 0
case groupMatchZeroOrMore:
min = 0
max = MaxIterations
case groupMatchOneOrMore:
min = 1
max = MaxIterations
}
matches := 0
for ; matches < max; matches++ {
branch := ctx.Branch()
v, err := g.expr.Parse(branch, parent)
out = append(out, v...)
if err != nil {
// Optional part failed to match.
if ctx.Stop(branch) {
return out, err
}
break
} else {
ctx.Accept(branch)
}
if v == nil {
break
}
}
// fmt.Printf("%d < %d < %d: out == nil? %v\n", min, matches, max, out == nil)
t, _ := ctx.Peek(0)
if matches >= MaxIterations {
panic(lexer.Errorf(t.Pos, "too many iterations of %s (> %d)", g, MaxIterations))
}
if matches < min {
return out, lexer.Errorf(t.Pos, "sub-expression %s must match at least once", g)
}
// The idea here is that something like "a"? is a successful match and that parsing should proceed.
if min == 0 && out == nil {
out = []reflect.Value{}
}
return out, nil
}
// <expr> {"|" <expr>}
type disjunction struct {
nodes []node
}
func (d *disjunction) String() string { return stringer(d) }
func (d *disjunction) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
var (
deepestError = 0
firstError error
firstValues []reflect.Value
)
for _, a := range d.nodes {
branch := ctx.Branch()
if value, err := a.Parse(branch, parent); err != nil {
// If this branch progressed too far and still didn't match, error out.
if ctx.Stop(branch) {
return value, err
}
// Show the closest error returned. The idea here is that the further the parser progresses
// without error, the more difficult it is to trace the error back to its root.
if err != nil && branch.cursor >= deepestError {
firstError = err
firstValues = value
deepestError = branch.cursor
}
} else if value != nil {
ctx.Accept(branch)
return value, nil
}
}
if firstError != nil {
return firstValues, firstError
}
return nil, nil
}
// <node> ...
type sequence struct {
head bool
node node
next *sequence
}
func (s *sequence) String() string { return stringer(s) }
func (s *sequence) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
for n := s; n != nil; n = n.next {
child, err := n.node.Parse(ctx, parent)
out = append(out, child...)
if err != nil {
return out, err
}
if child == nil {
// Early exit if first value doesn't match, otherwise all values must match.
if n == s {
return nil, nil
}
token, err := ctx.Peek(0)
if err != nil {
return nil, err
}
return out, lexer.Errorf(token.Pos, "unexpected %q (expected %s)", token, n)
}
}
return out, nil
}
// @<expr>
type capture struct {
field structLexerField
node node
}
func (c *capture) String() string { return stringer(c) }
func (c *capture) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
token, err := ctx.Peek(0)
if err != nil {
return nil, err
}
pos := token.Pos
v, err := c.node.Parse(ctx, parent)
if err != nil {
if v != nil {
ctx.Defer(pos, parent, c.field, v)
}
return []reflect.Value{parent}, err
}
if v == nil {
return nil, nil
}
ctx.Defer(pos, parent, c.field, v)
return []reflect.Value{parent}, nil
}
// <identifier> - named lexer token reference
type reference struct {
typ rune
identifier string // Used for informational purposes.
}
func (r *reference) String() string { return stringer(r) }
func (r *reference) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
token, err := ctx.Peek(0)
if err != nil {
return nil, err
}
if token.Type != r.typ {
return nil, nil
}
_, _ = ctx.Next()
return []reflect.Value{reflect.ValueOf(token.Value)}, nil
}
// [ <expr> ] <sequence>
type optional struct {
node node
}
func (o *optional) String() string { return stringer(o) }
func (o *optional) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
branch := ctx.Branch()
out, err = o.node.Parse(branch, parent)
if err != nil {
// Optional part failed to match.
if ctx.Stop(branch) {
return out, err
}
} else {
ctx.Accept(branch)
}
if out == nil {
out = []reflect.Value{}
}
return out, nil
}
// { <expr> } <sequence>
type repetition struct {
node node
}
func (r *repetition) String() string { return stringer(r) }
// Parse a repetition. Once a repetition is encountered it will always match, so grammars
// should ensure that branches are differentiated prior to the repetition.
func (r *repetition) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
i := 0
for ; i < MaxIterations; i++ {
branch := ctx.Branch()
v, err := r.node.Parse(branch, parent)
out = append(out, v...)
if err != nil {
// Optional part failed to match.
if ctx.Stop(branch) {
return out, err
}
break
} else {
ctx.Accept(branch)
}
if v == nil {
break
}
}
if i >= MaxIterations {
t, _ := ctx.Peek(0)
panic(lexer.Errorf(t.Pos, "too many iterations of %s (> %d)", r, MaxIterations))
}
if out == nil {
out = []reflect.Value{}
}
return out, nil
}
// Match a token literal exactly "..."[:<type>].
type literal struct {
s string
t rune
tt string // Used for display purposes - symbolic name of t.
}
func (l *literal) String() string { return stringer(l) }
func (l *literal) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) {
token, err := ctx.Peek(0)
if err != nil {
return nil, err
}
equal := false // nolint: ineffassign
if ctx.caseInsensitive[token.Type] {
equal = strings.EqualFold(token.Value, l.s)
} else {
equal = token.Value == l.s
}
if equal && (l.t == -1 || l.t == token.Type) {
next, err := ctx.Next()
if err != nil {
return nil, err
}
return []reflect.Value{reflect.ValueOf(next.Value)}, nil
}
return nil, nil
}
// Attempt to transform values to given type.
//
// This will dereference pointers, and attempt to parse strings into integer values, floats, etc.
func conform(t reflect.Type, values []reflect.Value) (out []reflect.Value, err error) {
for _, v := range values {
for t != v.Type() && t.Kind() == reflect.Ptr && v.Kind() != reflect.Ptr {
// This can occur during partial failure.
if !v.CanAddr() {
return
}
v = v.Addr()
}
// Already of the right kind, don't bother converting.
if v.Kind() == t.Kind() {
out = append(out, v)
continue
}
kind := t.Kind()
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(v.String(), 0, sizeOfKind(kind))
if err != nil {
return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err)
}
v = reflect.New(t).Elem()
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
n, err := strconv.ParseUint(v.String(), 0, sizeOfKind(kind))
if err != nil {
return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err)
}
v = reflect.New(t).Elem()
v.SetUint(n)
case reflect.Bool:
v = reflect.ValueOf(true)
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(v.String(), sizeOfKind(kind))
if err != nil {
return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err)
}
v = reflect.New(t).Elem()
v.SetFloat(n)
}
out = append(out, v)
}
return out, nil
}
func sizeOfKind(kind reflect.Kind) int {
switch kind {
case reflect.Int8, reflect.Uint8:
return 8
case reflect.Int16, reflect.Uint16:
return 16
case reflect.Int32, reflect.Uint32, reflect.Float32:
return 32
case reflect.Int64, reflect.Uint64, reflect.Float64:
return 64
case reflect.Int, reflect.Uint:
return strconv.IntSize
}
panic("unsupported kind " + kind.String())
}
// Set field.
//
// If field is a pointer the pointer will be set to the value. If field is a string, value will be
// appended. If field is a slice, value will be appended to slice.
//
// For all other types, an attempt will be made to convert the string to the corresponding
// type (int, float32, etc.).
func setField(pos lexer.Position, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) (err error) { // nolint: gocyclo
defer decorate(&err, func() string { return pos.String() + ": " + strct.Type().String() + "." + field.Name })
f := strct.FieldByIndex(field.Index)
switch f.Kind() {
case reflect.Slice:
fieldValue, err = conform(f.Type().Elem(), fieldValue)
if err != nil {
return err
}
f.Set(reflect.Append(f, fieldValue...))
return nil
case reflect.Ptr:
if f.IsNil() {
fv := reflect.New(f.Type().Elem()).Elem()
f.Set(fv.Addr())
f = fv
} else {
f = f.Elem()
}
}
if f.Kind() == reflect.Struct {
if pf := f.FieldByName("Pos"); pf.IsValid() && pf.Type() == positionType {
pf.Set(reflect.ValueOf(pos))
}
}
if f.CanAddr() {
if d, ok := f.Addr().Interface().(Capture); ok {
ifv := []string{}
for _, v := range fieldValue {
ifv = append(ifv, v.Interface().(string))
}
err := d.Capture(ifv)
if err != nil {
return err
}
return nil
}
}
// Strings concatenate all captured tokens.
if f.Kind() == reflect.String {
fieldValue, err = conform(f.Type(), fieldValue)
if err != nil {
return err
}
for _, v := range fieldValue {
f.Set(reflect.ValueOf(f.String() + v.String()).Convert(f.Type()))
}
return nil
}
// Coalesce multiple tokens into one. This allows eg. ["-", "10"] to be captured as separate tokens but
// parsed as a single string "-10".
if len(fieldValue) > 1 {
out := []string{}
for _, v := range fieldValue {
out = append(out, v.String())
}
fieldValue = []reflect.Value{reflect.ValueOf(strings.Join(out, ""))}
}
fieldValue, err = conform(f.Type(), fieldValue)
if err != nil {
return err
}
fv := fieldValue[0]
switch f.Kind() {
// Numeric types will increment if the token can not be coerced.
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if fv.Type() != f.Type() {
f.SetInt(f.Int() + 1)
} else {
f.Set(fv)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if fv.Type() != f.Type() {
f.SetUint(f.Uint() + 1)
} else {
f.Set(fv)
}
case reflect.Float32, reflect.Float64:
if fv.Type() != f.Type() {
f.SetFloat(f.Float() + 1)
} else {
f.Set(fv)
}
case reflect.Bool, reflect.Struct:
if fv.Type() != f.Type() {
return fmt.Errorf("value %q is not correct type %s", fv, f.Type())
}
f.Set(fv)
default:
return fmt.Errorf("unsupported field type %s for field %s", f.Type(), field.Name)
}
return nil
}
// Error is an error returned by the parser internally to differentiate from non-Participle errors.
type Error string
func (e Error) Error() string { return string(e) }

39
vendor/github.com/alecthomas/participle/options.go generated vendored Normal file
View File

@@ -0,0 +1,39 @@
package participle
import (
"github.com/alecthomas/participle/lexer"
)
// An Option to modify the behaviour of the Parser.
type Option func(p *Parser) error
// Lexer is an Option that sets the lexer to use with the given grammar.
func Lexer(def lexer.Definition) Option {
return func(p *Parser) error {
p.lex = def
return nil
}
}
// UseLookahead allows branch lookahead up to "n" tokens.
//
// If parsing cannot be disambiguated before "n" tokens of lookahead, parsing will fail.
//
// Note that increasing lookahead has a minor performance impact, but also
// reduces the accuracy of error reporting.
func UseLookahead(n int) Option {
return func(p *Parser) error {
p.useLookahead = n
return nil
}
}
// CaseInsensitive allows the specified token types to be matched case-insensitively.
func CaseInsensitive(tokens ...string) Option {
return func(p *Parser) error {
for _, token := range tokens {
p.caseInsensitive[token] = true
}
return nil
}
}

229
vendor/github.com/alecthomas/participle/parser.go generated vendored Normal file
View File

@@ -0,0 +1,229 @@
package participle
import (
"bytes"
"fmt"
"io"
"reflect"
"strings"
"github.com/alecthomas/participle/lexer"
)
// A Parser for a particular grammar and lexer.
type Parser struct {
root node
lex lexer.Definition
typ reflect.Type
useLookahead int
caseInsensitive map[string]bool
mappers []mapperByToken
}
// MustBuild calls Build(grammar, options...) and panics if an error occurs.
func MustBuild(grammar interface{}, options ...Option) *Parser {
parser, err := Build(grammar, options...)
if err != nil {
panic(err)
}
return parser
}
// Build constructs a parser for the given grammar.
//
// If "Lexer()" is not provided as an option, a default lexer based on text/scanner will be used. This scans typical Go-
// like tokens.
//
// See documentation for details
func Build(grammar interface{}, options ...Option) (parser *Parser, err error) {
// Configure Parser struct with defaults + options.
p := &Parser{
lex: lexer.TextScannerLexer,
caseInsensitive: map[string]bool{},
useLookahead: 1,
}
for _, option := range options {
if option == nil {
return nil, fmt.Errorf("nil Option passed, signature has changed; " +
"if you intended to provide a custom Lexer, try participle.Build(grammar, participle.Lexer(lexer))")
}
if err = option(p); err != nil {
return nil, err
}
}
if len(p.mappers) > 0 {
mappers := map[rune][]Mapper{}
symbols := p.lex.Symbols()
for _, mapper := range p.mappers {
if len(mapper.symbols) == 0 {
mappers[lexer.EOF] = append(mappers[lexer.EOF], mapper.mapper)
} else {
for _, symbol := range mapper.symbols {
if rn, ok := symbols[symbol]; !ok {
return nil, fmt.Errorf("mapper %#v uses unknown token %q", mapper, symbol)
} else { // nolint: golint
mappers[rn] = append(mappers[rn], mapper.mapper)
}
}
}
}
p.lex = &mappingLexerDef{p.lex, func(t lexer.Token) (lexer.Token, error) {
combined := make([]Mapper, 0, len(mappers[t.Type])+len(mappers[lexer.EOF]))
combined = append(combined, mappers[lexer.EOF]...)
combined = append(combined, mappers[t.Type]...)
var err error
for _, m := range combined {
t, err = m(t)
if err != nil {
return t, err
}
}
return t, nil
}}
}
context := newGeneratorContext(p.lex)
v := reflect.ValueOf(grammar)
if v.Kind() == reflect.Interface {
v = v.Elem()
}
p.typ = v.Type()
p.root, err = context.parseType(p.typ)
if err != nil {
return nil, err
}
return p, nil
}
// Lex uses the parser's lexer to tokenise input.
func (p *Parser) Lex(r io.Reader) ([]lexer.Token, error) {
lex, err := p.lex.Lex(r)
if err != nil {
return nil, err
}
return lexer.ConsumeAll(lex)
}
// Parse from r into grammar v which must be of the same type as the grammar passed to
// participle.Build().
func (p *Parser) Parse(r io.Reader, v interface{}) (err error) {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Interface {
rv = rv.Elem()
}
var stream reflect.Value
if rv.Kind() == reflect.Chan {
stream = rv
rt := rv.Type().Elem()
rv = reflect.New(rt).Elem()
}
rt := rv.Type()
if rt != p.typ {
return fmt.Errorf("must parse into value of type %s not %T", p.typ, v)
}
baseLexer, err := p.lex.Lex(r)
if err != nil {
return err
}
lex := lexer.Upgrade(baseLexer)
caseInsensitive := map[rune]bool{}
for sym, rn := range p.lex.Symbols() {
if p.caseInsensitive[sym] {
caseInsensitive[rn] = true
}
}
ctx, err := newParseContext(lex, p.useLookahead, caseInsensitive)
if err != nil {
return err
}
// If the grammar implements Parseable, use it.
if parseable, ok := v.(Parseable); ok {
return p.rootParseable(ctx, parseable)
}
if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Struct {
return fmt.Errorf("target must be a pointer to a struct, not %s", rt)
}
if stream.IsValid() {
return p.parseStreaming(ctx, stream)
}
return p.parseOne(ctx, rv)
}
func (p *Parser) parseStreaming(ctx *parseContext, rv reflect.Value) error {
t := rv.Type().Elem().Elem()
for {
if token, _ := ctx.Peek(0); token.EOF() {
rv.Close()
return nil
}
v := reflect.New(t)
if err := p.parseInto(ctx, v); err != nil {
return err
}
rv.Send(v)
}
}
func (p *Parser) parseOne(ctx *parseContext, rv reflect.Value) error {
err := p.parseInto(ctx, rv)
if err != nil {
return err
}
token, err := ctx.Peek(0)
if err != nil {
return err
} else if !token.EOF() {
return lexer.Errorf(token.Pos, "unexpected trailing token %q", token)
}
return nil
}
func (p *Parser) parseInto(ctx *parseContext, rv reflect.Value) error {
if rv.IsNil() {
return fmt.Errorf("target must be a non-nil pointer to a struct, but is a nil %s", rv.Type())
}
pv, err := p.root.Parse(ctx, rv.Elem())
if len(pv) > 0 && pv[0].Type() == rv.Elem().Type() {
rv.Elem().Set(reflect.Indirect(pv[0]))
}
if err != nil {
return err
}
if pv == nil {
token, _ := ctx.Peek(0)
return lexer.Errorf(token.Pos, "invalid syntax")
}
return nil
}
func (p *Parser) rootParseable(lex lexer.PeekingLexer, parseable Parseable) error {
peek, err := lex.Peek(0)
if err != nil {
return err
}
err = parseable.Parse(lex)
if err == NextMatch {
return lexer.Errorf(peek.Pos, "invalid syntax")
}
if err == nil && !peek.EOF() {
return lexer.Errorf(peek.Pos, "unexpected token %q", peek)
}
return err
}
// ParseString is a convenience around Parse().
func (p *Parser) ParseString(s string, v interface{}) error {
return p.Parse(strings.NewReader(s), v)
}
// ParseBytes is a convenience around Parse().
func (p *Parser) ParseBytes(b []byte, v interface{}) error {
return p.Parse(bytes.NewReader(b), v)
}
// String representation of the grammar.
func (p *Parser) String() string {
return stringern(p.root, 128)
}

118
vendor/github.com/alecthomas/participle/stringer.go generated vendored Normal file
View File

@@ -0,0 +1,118 @@
package participle
import (
"bytes"
"fmt"
"strings"
"github.com/alecthomas/participle/lexer"
)
type stringerVisitor struct {
bytes.Buffer
seen map[node]bool
}
func stringern(n node, depth int) string {
v := &stringerVisitor{seen: map[node]bool{}}
v.visit(n, depth, false)
return v.String()
}
func stringer(n node) string {
return stringern(n, 1)
}
func (s *stringerVisitor) visit(n node, depth int, disjunctions bool) {
if s.seen[n] || depth <= 0 {
fmt.Fprintf(s, "...")
return
}
s.seen[n] = true
switch n := n.(type) {
case *disjunction:
for i, c := range n.nodes {
if i > 0 {
fmt.Fprint(s, " | ")
}
s.visit(c, depth, disjunctions || len(n.nodes) > 1)
}
case *strct:
s.visit(n.expr, depth, disjunctions)
case *sequence:
c := n
for i := 0; c != nil && depth-i > 0; c, i = c.next, i+1 {
if c != n {
fmt.Fprint(s, " ")
}
s.visit(c.node, depth-i, disjunctions)
}
if c != nil {
fmt.Fprint(s, " ...")
}
case *parseable:
fmt.Fprintf(s, "<%s>", strings.ToLower(n.t.Name()))
case *capture:
if _, ok := n.node.(*parseable); ok {
fmt.Fprintf(s, "<%s>", strings.ToLower(n.field.Name))
} else {
if n.node == nil {
fmt.Fprintf(s, "<%s>", strings.ToLower(n.field.Name))
} else {
s.visit(n.node, depth, disjunctions)
}
}
case *reference:
fmt.Fprintf(s, "<%s>", strings.ToLower(n.identifier))
case *optional:
fmt.Fprint(s, "[ ")
s.visit(n.node, depth, disjunctions)
fmt.Fprint(s, " ]")
case *repetition:
fmt.Fprint(s, "{ ")
s.visit(n.node, depth, disjunctions)
fmt.Fprint(s, " }")
case *literal:
fmt.Fprintf(s, "%q", n.s)
if n.t != lexer.EOF && n.s == "" {
fmt.Fprintf(s, ":%s", n.tt)
}
case *group:
fmt.Fprint(s, "(")
if child, ok := n.expr.(*group); ok && child.mode == groupMatchOnce {
s.visit(child.expr, depth, disjunctions)
} else if child, ok := n.expr.(*capture); ok {
if grandchild, ok := child.node.(*group); ok && grandchild.mode == groupMatchOnce {
s.visit(grandchild.expr, depth, disjunctions)
} else {
s.visit(n.expr, depth, disjunctions)
}
} else {
s.visit(n.expr, depth, disjunctions)
}
fmt.Fprint(s, ")")
switch n.mode {
case groupMatchNonEmpty:
fmt.Fprintf(s, "!")
case groupMatchZeroOrOne:
fmt.Fprintf(s, "?")
case groupMatchZeroOrMore:
fmt.Fprintf(s, "*")
case groupMatchOneOrMore:
fmt.Fprintf(s, "+")
}
default:
panic("unsupported")
}
}

126
vendor/github.com/alecthomas/participle/struct.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package participle
import (
"fmt"
"reflect"
"github.com/alecthomas/participle/lexer"
)
// A structLexer lexes over the tags of struct fields while tracking the current field.
type structLexer struct {
s reflect.Type
field int
indexes [][]int
lexer lexer.PeekingLexer
}
func lexStruct(s reflect.Type) (*structLexer, error) {
indexes, err := collectFieldIndexes(s)
if err != nil {
return nil, err
}
slex := &structLexer{
s: s,
indexes: indexes,
}
if len(slex.indexes) > 0 {
tag := fieldLexerTag(slex.Field().StructField)
slex.lexer = lexer.Upgrade(lexer.LexString(tag))
}
return slex, nil
}
// NumField returns the number of fields in the struct associated with this structLexer.
func (s *structLexer) NumField() int {
return len(s.indexes)
}
type structLexerField struct {
reflect.StructField
Index []int
}
// Field returns the field associated with the current token.
func (s *structLexer) Field() structLexerField {
return s.GetField(s.field)
}
func (s *structLexer) GetField(field int) structLexerField {
if field >= len(s.indexes) {
field = len(s.indexes) - 1
}
return structLexerField{
StructField: s.s.FieldByIndex(s.indexes[field]),
Index: s.indexes[field],
}
}
func (s *structLexer) Peek() (lexer.Token, error) {
field := s.field
lex := s.lexer
for {
token, err := lex.Peek(0)
if err != nil {
return token, err
}
if !token.EOF() {
token.Pos.Line = field + 1
return token, nil
}
field++
if field >= s.NumField() {
return lexer.EOFToken(token.Pos), nil
}
tag := fieldLexerTag(s.GetField(field).StructField)
lex = lexer.Upgrade(lexer.LexString(tag))
}
}
func (s *structLexer) Next() (lexer.Token, error) {
token, err := s.lexer.Next()
if err != nil {
return token, err
}
if !token.EOF() {
token.Pos.Line = s.field + 1
return token, nil
}
if s.field+1 >= s.NumField() {
return lexer.EOFToken(token.Pos), nil
}
s.field++
tag := fieldLexerTag(s.Field().StructField)
s.lexer = lexer.Upgrade(lexer.LexString(tag))
return s.Next()
}
func fieldLexerTag(field reflect.StructField) string {
if tag, ok := field.Tag.Lookup("parser"); ok {
return tag
}
return string(field.Tag)
}
// Recursively collect flattened indices for top-level fields and embedded fields.
func collectFieldIndexes(s reflect.Type) (out [][]int, err error) {
if s.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected a struct but got %q", s)
}
defer decorate(&err, s.String)
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
if f.Anonymous {
children, err := collectFieldIndexes(f.Type)
if err != nil {
return nil, err
}
for _, idx := range children {
out = append(out, append(f.Index, idx...))
}
} else if fieldLexerTag(f) != "" {
out = append(out, f.Index)
}
}
return
}