alecthomas / alecthomas/participle

EBNF for Parsable interface

Aperta
#444 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Go
Stelle
3.9k
Fork
213
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

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!

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.