Skip to content

Instantly share code, notes, and snippets.

@alecthomas
Created September 28, 2018 04:01
Show Gist options
  • Save alecthomas/6bbd5ed6e9d22a46ac73ec0ed4ef42cf to your computer and use it in GitHub Desktop.
Save alecthomas/6bbd5ed6e9d22a46ac73ec0ed4ef42cf to your computer and use it in GitHub Desktop.
// nolint: golint
package main
import (
"os"
"github.com/alecthomas/participle"
"github.com/alecthomas/participle/lexer"
"github.com/alecthomas/repr"
)
var fieldLexer = lexer.Must(lexer.Regexp(
`(?m)` +
`(\s+)` +
`|(?P<Semicolon>;)` +
`|(?P<Comma>,)` +
`|(?P<At>@)` +
`|(?P<Unaryop>[!])` +
`|(?P<Equals>[=])` +
`|(?P<Ident>[a-zA-Z][a-zA-Z_\d]*)` +
`|(?P<String>"(?:\\.|[^"])*")` +
`|(?P<Float>\d+(?:\.\d+)?)` +
`|(?P<Lparen>[\(])` +
`|(?P<Rparen>[\)])`,
))
// field2(1, 2); field1; f3 = foo(1,2);
type FieldExprs struct {
Exprs []*FieldExpr `{ @@ ";" }`
}
type FieldExpr struct {
Assignment *Assignment ` @@`
Expr *Expr `| @@`
}
type Assignment struct {
Variable string `@Ident "="`
Expr *Expr `@@`
}
type Expr struct {
Function *Function ` @@`
Term *Term `| @@`
}
type Function struct {
Name *string `@Ident`
Args []*Term `"(" [ @@ { "," @@ } ] ")"`
}
type Term struct {
Variable *string `@Ident`
String *string `| @String`
Number *float64 `| @Float`
}
func main() {
parser, err := participle.Build(
&FieldExprs{},
participle.Lexer(fieldLexer),
participle.Unquote(fieldLexer, "String"),
participle.UseLookahead(),
)
if err != nil {
panic(err)
}
myAST := &FieldExprs{}
err = parser.Parse(os.Stdin, myAST)
if err != nil {
panic(err)
}
repr.Println(myAST, repr.Indent(" "), repr.OmitEmpty(true))
}
Currently, it works.
```
➤ echo 'field2; field1; @f3 = foo(1,2);' | go run main.go
&main.FieldExprs{
Exprs: []*main.FieldExpr{
&main.FieldExpr{
Field: &"field2",
},
&main.FieldExpr{
Field: &"field1",
},
&main.FieldExpr{
Expr: &main.Expr{
Field: &1,
Function: &main.Function{
Name: &"foo",
Args: []*main.Args{
&main.Args{
Arg: &main.Arg{
Number: &1,
},
},
&main.Args{
Arg: &main.Arg{
Number: &2,
},
},
},
},
},
},
},
}
```
But, I don't like the `@` sign. If I try to remove `@` token from Line 36 `Field *float64 `"@"@Ident "="``, then,
try to parse a token like:- `field2; field1; f3 = foo(1,2);`, I get errors like this:-
```
➤ echo 'field2; field1; f3 = foo(1,2);' | go run main.go
panic: /dev/stdin:1:20: unexpected "=" (expected ";")
goroutine 1 [running]:
main.main()
/home/arastogi/playground/golang/participle_example/fresh_start_fields/main.go:63 +0x292
exit status 2
```
What it really means is, it matches my first `FieldExpr.Field` and never really goes to the optional/alternative Line 32, FieldExpr.Expr.
Is there a way to fix it?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment