alecthomas / alecthomas/participle
EBNF for Parsable interface
- Linguagem predominante
- Go
- Estrelas
- 3.9k
- Forks
- 213
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Descrição
Hello 👋 . I'm debugging why a grammar I'm working on no longer produces a railroad diagram and think I've noticed it deals with the `*parseable` interface. For demonstration here's an example with [langx](https://github.com/alecthomas/langx/compare/master...obj-p:langx:obj-p/railroad), of which, I've used as a reference for implementing operator precedence. With the demo we can see that printing the Grammar results in:
```sh
$ go run cmd/langx/main.go
AST = RootDecl* .
RootDecl = * ((ClassDecl ";"?) | (ImportDecl ";"?) | (EnumDecl ";"?) | (VarDecl ";") | (FuncDecl ";"?)) .
ClassDecl = "class" NamedTypeDecl "{" (ClassMember (";" ClassMember)* ";"?)? "}" .
NamedTypeDecl = ("<" TypeParamDecl ("," TypeParamDecl)* ","? ">")? .
TypeParamDecl = (":" Reference ("," Reference)*)? .
Reference = Terminal ReferenceNext? "?"? .
Terminal = ("(" Expr ("," Expr)* ")") | NewExpr | Literal | .
NewExpr = "new" Reference ("(" (InitParameter ("," InitParameter)* ","?)? ")")? .
InitParameter = "=" Expr .
Literal = | String | | ("true" | "false") | DictOrSetLiteral | ArrayLiteral .
String = "\"" StringFragment* "\"" .
StringFragment = ( | ("{" Expr "}") | ) .
DictOrSetLiteral = "{" DictOrSetEntryLiteral ("," DictOrSetEntryLiteral)* ","? "}" .
DictOrSetEntryLiteral = Expr (":" Expr)? .
ArrayLiteral = "[" (Expr ("," Expr)*)? ","? "]" .
ReferenceNext = (("[" Expr "]") | ("." Terminal) | ("<" Reference ("," Reference)* ","? ">" (?= "(" | ";" | "=" | ".")) | Call) ReferenceNext? .
Call = "(" (Expr ("," Expr)*)? ","? ")" .
ClassMember = * (VarDecl | FuncDecl | ClassDecl | EnumDecl | InitialiserDecl) .
VarDecl = "let" VarDeclAsgn ("," VarDeclAsgn)* .
VarDeclAsgn = (":" Expr)? ("=" Expr)? .
FuncDecl = "fn" "(" (Parameters ("," Parameters)*)? ","? ")" "throws"? (":" Expr)? Block .
Parameters = ("," )* ":" Reference .
Block = "{" (Stmt (";" Stmt)* ";"?)? "}" .
Stmt = ReturnStmt | IfStmt | ForStmt | SwitchStmt | Block | VarDecl | FuncDecl | ClassDecl | EnumDecl | ExprStmt .
ReturnStmt = "return" Expr? .
IfStmt = "if" Expr Block ("else" Block)? .
ForStmt = "for" Reference "in" Expr Block .
SwitchStmt = "switch" Expr "{" CaseStmt* "}" .
CaseStmt = ("default" | ("case" CaseSelect)) ":" (Stmt (";" Stmt)* ";"?)? .
CaseSelect = EnumCase | Expr .
EnumCase = "." ("(" ")")? .
EnumDecl = "enum" NamedTypeDecl "{" (EnumMember (";" EnumMember)* ";"?)? "}" .
EnumMember = * (CaseDecl | FuncDecl) .
CaseDecl = "case" ("(" TypeDecl ")")? .
TypeDecl = NamedTypeDecl | ArrayTypeDecl | DictOrSetTypeDecl .
ArrayTypeDecl = "[" TypeDecl "]" .
DictOrSetTypeDecl = "{" TypeDecl (":" TypeDecl)? "}" .
ExprStmt = Expr ( Expr)? .
InitialiserDecl = "init" "(" (Parameters ("," Parameters)*)? ","? ")" "throws"? Block .
ImportDecl = "import" ? String .
```
Notice that in the above `Expr` is not listed as an element in the Grammar (i.e. `Expr = ...`). When we feed this into the railroad we will panic due to this.
```sh
$ go run cmd/langx/main.go | scripts/railroad.sh
Generates railroad diagrams from a Participle EBNF grammar on stdin.
(EBNF is available from .String() on your parser)
(Use control-D to end input)
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x8 pc=0x104e1cd08]
goroutine 1 [running]:
main.countProductions(0x14000143ef0, {0x104ea8fe8?, 0x1400016def0})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:164 +0xb8
main.countProductions(0x14000143ef0, {0x104ea8fa8?, 0x14000163b00})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:160 +0x1a8
main.countProductions(0x14000143ef0, {0x104ea8f88?, 0x14000176318})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:154 +0x228
main.countProductions(0x14000143ef0, {0x104ea8fc8?, 0x14000097cb0})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:157 +0x64
main.countProductions(0x14000143ef0, {0x104ea8fe8?, 0x1400016d950})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:167 +0x9c
main.countProductions(0x14000143ef0, {0x104ea8fa8?, 0x14000163aa0})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:160 +0x1a8
main.countProductions(0x14000143ef0, {0x104ea8f88?, 0x14000176a68})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:154 +0x228
main.countProductions(0x14000143ef0, {0x104ea8f68?, 0x14000163a10})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:151 +0xec
main.countProductions(0x14000143ef0, {0x104ea8f48?, 0x140000aeac8})
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:143 +0x320
main.main()
/Users/jasonprasad/go/pkg/mod/github.com/alecthomas/participle/v2@v2.0.0-alpha10/cmd/railroad/main.go:199 +0x268
exit status 2
mv: rename railroad-diagrams.* to /var/folders/3r/6r38j2b12g1ccg_f9617szwm0000gn/T/railroad-diagrams.*: No such file or directory
```
I think I see that the `*parsable` branch in the [ebnf.go](https://github.com/alecthomas/participle/blob/ad7a080fb4fae0d6d10e320d4125c1713b50a8d9/ebnf.go#L106) doesn't add the Expr to the `outp` which makes sense given the custom handling; however, I wonder if it's an opportunity to add members to the interface such that it returns the needed information to construct the EBNF?
I'm still getting my bearings on it all but will dig deeper to see if I'm going down the right path and figure out a solution. Thank you!
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Avaliação
Esta issue ainda não foi avaliada.