Skip to content

Commit

Permalink
Tolerate missing ';' after package, imports, file options, and method…
Browse files Browse the repository at this point in the history
… options (#212)

While still producing an error. See
#200
  • Loading branch information
Alfus authored Dec 4, 2023
1 parent ec8c634 commit e79e10e
Show file tree
Hide file tree
Showing 6 changed files with 717 additions and 622 deletions.
15 changes: 10 additions & 5 deletions ast/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ func NewImportNode(keyword *KeywordNode, public *KeywordNode, weak *KeywordNode,
if name == nil {
panic("name is nil")
}
numChildren := 2
if semicolon == nil {
panic("semicolon is nil")
numChildren++
}
numChildren := 3
if public != nil || weak != nil {
numChildren++
}
Expand All @@ -289,7 +289,10 @@ func NewImportNode(keyword *KeywordNode, public *KeywordNode, weak *KeywordNode,
} else if weak != nil {
children = append(children, weak)
}
children = append(children, name, semicolon)
children = append(children, name)
if semicolon != nil {
children = append(children, semicolon)
}

return &ImportNode{
compositeNode: compositeNode{
Expand Down Expand Up @@ -328,10 +331,12 @@ func NewPackageNode(keyword *KeywordNode, name IdentValueNode, semicolon *RuneNo
if name == nil {
panic("name is nil")
}
var children []Node
if semicolon == nil {
panic("semicolon is nil")
children = []Node{keyword, name}
} else {
children = []Node{keyword, name, semicolon}
}
children := []Node{keyword, name, semicolon}
return &PackageNode{
compositeNode: compositeNode{
children: children,
Expand Down
44 changes: 40 additions & 4 deletions parser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ func newServiceElements(semicolons []*ast.RuneNode, elements []ast.ServiceElemen
return elems
}

func newMethodElements(semicolons []*ast.RuneNode, elements []ast.RPCElement) []ast.RPCElement {
elems := make([]ast.RPCElement, 0, len(semicolons)+len(elements))
for _, semicolon := range semicolons {
elems = append(elems, ast.NewEmptyDeclNode(semicolon))
}
elems = append(elems, elements...)
return elems
}

func newFileElements(semicolons []*ast.RuneNode, elements []ast.FileElement) []ast.FileElement {
elems := make([]ast.FileElement, 0, len(semicolons)+len(elements))
for _, semicolon := range semicolons {
elems = append(elems, ast.NewEmptyDeclNode(semicolon))
}
elems = append(elems, elements...)
return elems
}

type nodeWithEmptyDecls[T ast.Node] struct {
Node T
EmptyDecls []*ast.EmptyDeclNode
Expand All @@ -121,10 +139,28 @@ func newNodeWithEmptyDecls[T ast.Node](node T, extraSemicolons []*ast.RuneNode)
}

func toServiceElements[T ast.ServiceElement](nodes nodeWithEmptyDecls[T]) []ast.ServiceElement {
serviceElements := make([]ast.ServiceElement, 1+len(nodes.EmptyDecls))
serviceElements[0] = nodes.Node
elements := make([]ast.ServiceElement, 1+len(nodes.EmptyDecls))
elements[0] = nodes.Node
for i, emptyDecl := range nodes.EmptyDecls {
elements[i+1] = emptyDecl
}
return elements
}

func toMethodElements[T ast.RPCElement](nodes nodeWithEmptyDecls[T]) []ast.RPCElement {
elements := make([]ast.RPCElement, 1+len(nodes.EmptyDecls))
elements[0] = nodes.Node
for i, emptyDecl := range nodes.EmptyDecls {
elements[i+1] = emptyDecl
}
return elements
}

func toFileElements[T ast.FileElement](nodes nodeWithEmptyDecls[T]) []ast.FileElement {
elements := make([]ast.FileElement, 1+len(nodes.EmptyDecls))
elements[0] = nodes.Node
for i, emptyDecl := range nodes.EmptyDecls {
serviceElements[i+1] = emptyDecl
elements[i+1] = emptyDecl
}
return serviceElements
return elements
}
40 changes: 40 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,30 @@ func TestLenientParse_SemicolonLess(t *testing.T) {
Error string
NoError string
}{
"package": {
Error: `syntax = "proto3";
package foo
message Foo {}`,
NoError: `syntax = "proto3";
package foo;
message Foo {};`,
},
"import": {
Error: `syntax = "proto3";
import "foo.proto"
message Foo {}`,
NoError: `syntax = "proto3";
import "foo.proto";;
message Foo {};`,
},
"file-options": {
Error: `syntax = "proto3";
option (foo) = 1
message Foo {}`,
NoError: `syntax = "proto3";
option (foo) = 1;;
message Foo {};`,
},
"method": {
Error: `syntax = "proto3";
service Foo {
Expand All @@ -112,6 +136,22 @@ func TestLenientParse_SemicolonLess(t *testing.T) {
option (foo) = { bar: 1 };
}`,
},
"method-options": {
Error: `syntax = "proto3";
service Foo {
rpc Bar (Baz) returns (Qux) {
;
option (foo) = { bar: 1 }
}
}`,
NoError: `syntax = "proto3";
service Foo {
rpc Bar (Baz) returns (Qux) {
;
option (foo) = { bar: 1 };;
}
}`,
},
}
for name, input := range inputs {
name, input := name, input
Expand Down
Loading

0 comments on commit e79e10e

Please sign in to comment.