alecthomas / alecthomas/participle

EBNF for Parsable interface

Aberta
#444 2 comentários 0 reações 0 responsáveis Ver no GitHub
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.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.