959 lines
21 KiB
Plaintext
959 lines
21 KiB
Plaintext
|
%{
|
||
|
package protoparse
|
||
|
|
||
|
//lint:file-ignore SA4006 generated parser has unused values
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
|
||
|
"github.com/jhump/protoreflect/desc/protoparse/ast"
|
||
|
)
|
||
|
|
||
|
%}
|
||
|
|
||
|
// fields inside this union end up as the fields in a structure known
|
||
|
// as ${PREFIX}SymType, of which a reference is passed to the lexer.
|
||
|
%union{
|
||
|
file *ast.FileNode
|
||
|
syn *ast.SyntaxNode
|
||
|
fileDecl ast.FileElement
|
||
|
fileDecls []ast.FileElement
|
||
|
pkg *ast.PackageNode
|
||
|
imprt *ast.ImportNode
|
||
|
msg *ast.MessageNode
|
||
|
msgDecl ast.MessageElement
|
||
|
msgDecls []ast.MessageElement
|
||
|
fld *ast.FieldNode
|
||
|
mapFld *ast.MapFieldNode
|
||
|
mapType *ast.MapTypeNode
|
||
|
grp *ast.GroupNode
|
||
|
oo *ast.OneOfNode
|
||
|
ooDecl ast.OneOfElement
|
||
|
ooDecls []ast.OneOfElement
|
||
|
ext *ast.ExtensionRangeNode
|
||
|
resvd *ast.ReservedNode
|
||
|
en *ast.EnumNode
|
||
|
enDecl ast.EnumElement
|
||
|
enDecls []ast.EnumElement
|
||
|
env *ast.EnumValueNode
|
||
|
extend *ast.ExtendNode
|
||
|
extDecl ast.ExtendElement
|
||
|
extDecls []ast.ExtendElement
|
||
|
svc *ast.ServiceNode
|
||
|
svcDecl ast.ServiceElement
|
||
|
svcDecls []ast.ServiceElement
|
||
|
mtd *ast.RPCNode
|
||
|
rpcType *ast.RPCTypeNode
|
||
|
rpcDecl ast.RPCElement
|
||
|
rpcDecls []ast.RPCElement
|
||
|
opt *ast.OptionNode
|
||
|
opts *compactOptionList
|
||
|
ref *ast.FieldReferenceNode
|
||
|
optNms *fieldRefList
|
||
|
cmpctOpts *ast.CompactOptionsNode
|
||
|
rng *ast.RangeNode
|
||
|
rngs *rangeList
|
||
|
names *nameList
|
||
|
cid *identList
|
||
|
tid ast.IdentValueNode
|
||
|
sl *valueList
|
||
|
msgField *ast.MessageFieldNode
|
||
|
msgEntry *messageFieldEntry
|
||
|
msgLit *messageFieldList
|
||
|
v ast.ValueNode
|
||
|
il ast.IntValueNode
|
||
|
str *stringList
|
||
|
s *ast.StringLiteralNode
|
||
|
i *ast.UintLiteralNode
|
||
|
f *ast.FloatLiteralNode
|
||
|
id *ast.IdentNode
|
||
|
b *ast.RuneNode
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
// any non-terminal which returns a value needs a type, which is
|
||
|
// really a field name in the above union struct
|
||
|
%type <file> file
|
||
|
%type <syn> syntax
|
||
|
%type <fileDecl> fileDecl
|
||
|
%type <fileDecls> fileDecls
|
||
|
%type <imprt> import
|
||
|
%type <pkg> package
|
||
|
%type <opt> option compactOption
|
||
|
%type <opts> compactOptionDecls
|
||
|
%type <rpcDecl> rpcDecl
|
||
|
%type <rpcDecls> rpcDecls
|
||
|
%type <ref> optionNameComponent aggName
|
||
|
%type <optNms> optionName
|
||
|
%type <cmpctOpts> compactOptions
|
||
|
%type <v> constant scalarConstant aggregate numLit
|
||
|
%type <il> intLit
|
||
|
%type <id> name keyType
|
||
|
%type <cid> ident
|
||
|
%type <tid> typeIdent
|
||
|
%type <sl> constantList
|
||
|
%type <msgField> aggFieldEntry
|
||
|
%type <msgEntry> aggField
|
||
|
%type <msgLit> aggFields
|
||
|
%type <fld> field oneofField
|
||
|
%type <oo> oneof
|
||
|
%type <grp> group oneofGroup
|
||
|
%type <mapFld> mapField
|
||
|
%type <mapType> mapType
|
||
|
%type <msg> message
|
||
|
%type <msgDecl> messageDecl
|
||
|
%type <msgDecls> messageDecls
|
||
|
%type <ooDecl> ooDecl
|
||
|
%type <ooDecls> ooDecls
|
||
|
%type <names> fieldNames
|
||
|
%type <resvd> msgReserved enumReserved reservedNames
|
||
|
%type <rng> tagRange enumRange
|
||
|
%type <rngs> tagRanges enumRanges
|
||
|
%type <ext> extensions
|
||
|
%type <en> enum
|
||
|
%type <enDecl> enumDecl
|
||
|
%type <enDecls> enumDecls
|
||
|
%type <env> enumValue
|
||
|
%type <extend> extend
|
||
|
%type <extDecl> extendDecl
|
||
|
%type <extDecls> extendDecls
|
||
|
%type <str> stringLit
|
||
|
%type <svc> service
|
||
|
%type <svcDecl> serviceDecl
|
||
|
%type <svcDecls> serviceDecls
|
||
|
%type <mtd> rpc
|
||
|
%type <rpcType> rpcType
|
||
|
|
||
|
// same for terminals
|
||
|
%token <s> _STRING_LIT
|
||
|
%token <i> _INT_LIT
|
||
|
%token <f> _FLOAT_LIT
|
||
|
%token <id> _NAME
|
||
|
%token <id> _SYNTAX _IMPORT _WEAK _PUBLIC _PACKAGE _OPTION _TRUE _FALSE _INF _NAN _REPEATED _OPTIONAL _REQUIRED
|
||
|
%token <id> _DOUBLE _FLOAT _INT32 _INT64 _UINT32 _UINT64 _SINT32 _SINT64 _FIXED32 _FIXED64 _SFIXED32 _SFIXED64
|
||
|
%token <id> _BOOL _STRING _BYTES _GROUP _ONEOF _MAP _EXTENSIONS _TO _MAX _RESERVED _ENUM _MESSAGE _EXTEND
|
||
|
%token <id> _SERVICE _RPC _STREAM _RETURNS
|
||
|
%token <err> _ERROR
|
||
|
// we define all of these, even ones that aren't used, to improve error messages
|
||
|
// so it shows the unexpected symbol instead of showing "$unk"
|
||
|
%token <b> '=' ';' ':' '{' '}' '\\' '/' '?' '.' ',' '>' '<' '+' '-' '(' ')' '[' ']' '*' '&' '^' '%' '$' '#' '@' '!' '~' '`'
|
||
|
|
||
|
%%
|
||
|
|
||
|
file : syntax {
|
||
|
$$ = ast.NewFileNode($1, nil)
|
||
|
protolex.(*protoLex).res = $$
|
||
|
}
|
||
|
| fileDecls {
|
||
|
$$ = ast.NewFileNode(nil, $1)
|
||
|
protolex.(*protoLex).res = $$
|
||
|
}
|
||
|
| syntax fileDecls {
|
||
|
$$ = ast.NewFileNode($1, $2)
|
||
|
protolex.(*protoLex).res = $$
|
||
|
}
|
||
|
| {
|
||
|
}
|
||
|
|
||
|
fileDecls : fileDecls fileDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| fileDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.FileElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fileDecl : import {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| package {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| message {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| enum {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| extend {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| service {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
syntax : _SYNTAX '=' stringLit ';' {
|
||
|
$$ = ast.NewSyntaxNode($1.ToKeyword(), $2, $3.toStringValueNode(), $4)
|
||
|
}
|
||
|
|
||
|
import : _IMPORT stringLit ';' {
|
||
|
$$ = ast.NewImportNode($1.ToKeyword(), nil, nil, $2.toStringValueNode(), $3)
|
||
|
}
|
||
|
| _IMPORT _WEAK stringLit ';' {
|
||
|
$$ = ast.NewImportNode($1.ToKeyword(), nil, $2.ToKeyword(), $3.toStringValueNode(), $4)
|
||
|
}
|
||
|
| _IMPORT _PUBLIC stringLit ';' {
|
||
|
$$ = ast.NewImportNode($1.ToKeyword(), $2.ToKeyword(), nil, $3.toStringValueNode(), $4)
|
||
|
}
|
||
|
|
||
|
package : _PACKAGE ident ';' {
|
||
|
$$ = ast.NewPackageNode($1.ToKeyword(), $2.toIdentValueNode(nil), $3)
|
||
|
}
|
||
|
|
||
|
ident : name {
|
||
|
$$ = &identList{$1, nil, nil}
|
||
|
}
|
||
|
| name '.' ident {
|
||
|
$$ = &identList{$1, $2, $3}
|
||
|
}
|
||
|
|
||
|
option : _OPTION optionName '=' constant ';' {
|
||
|
refs, dots := $2.toNodes()
|
||
|
optName := ast.NewOptionNameNode(refs, dots)
|
||
|
$$ = ast.NewOptionNode($1.ToKeyword(), optName, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
optionName : optionNameComponent {
|
||
|
$$ = &fieldRefList{$1, nil, nil}
|
||
|
}
|
||
|
| optionNameComponent '.' optionName {
|
||
|
$$ = &fieldRefList{$1, $2, $3}
|
||
|
}
|
||
|
|
||
|
optionNameComponent : name {
|
||
|
$$ = ast.NewFieldReferenceNode($1)
|
||
|
}
|
||
|
| '(' typeIdent ')' {
|
||
|
$$ = ast.NewExtensionFieldReferenceNode($1, $2, $3)
|
||
|
}
|
||
|
|
||
|
constant : scalarConstant
|
||
|
| aggregate
|
||
|
|
||
|
scalarConstant : stringLit {
|
||
|
$$ = $1.toStringValueNode()
|
||
|
}
|
||
|
| numLit
|
||
|
| name {
|
||
|
if $1.Val == "true" || $1.Val == "false" {
|
||
|
$$ = ast.NewBoolLiteralNode($1.ToKeyword())
|
||
|
} else if $1.Val == "inf" || $1.Val == "nan" {
|
||
|
$$ = ast.NewSpecialFloatLiteralNode($1.ToKeyword())
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
numLit : _FLOAT_LIT {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| '-' _FLOAT_LIT {
|
||
|
$$ = ast.NewSignedFloatLiteralNode($1, $2)
|
||
|
}
|
||
|
| '+' _FLOAT_LIT {
|
||
|
$$ = ast.NewSignedFloatLiteralNode($1, $2)
|
||
|
}
|
||
|
| '+' _INF {
|
||
|
f := ast.NewSpecialFloatLiteralNode($2.ToKeyword())
|
||
|
$$ = ast.NewSignedFloatLiteralNode($1, f)
|
||
|
}
|
||
|
| '-' _INF {
|
||
|
f := ast.NewSpecialFloatLiteralNode($2.ToKeyword())
|
||
|
$$ = ast.NewSignedFloatLiteralNode($1, f)
|
||
|
}
|
||
|
| _INT_LIT {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| '+' _INT_LIT {
|
||
|
$$ = ast.NewPositiveUintLiteralNode($1, $2)
|
||
|
}
|
||
|
| '-' _INT_LIT {
|
||
|
if $2.Val > math.MaxInt64 + 1 {
|
||
|
// can't represent as int so treat as float literal
|
||
|
$$ = ast.NewSignedFloatLiteralNode($1, $2)
|
||
|
} else {
|
||
|
$$ = ast.NewNegativeIntLiteralNode($1, $2)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
stringLit : _STRING_LIT {
|
||
|
$$ = &stringList{$1, nil}
|
||
|
}
|
||
|
| _STRING_LIT stringLit {
|
||
|
$$ = &stringList{$1, $2}
|
||
|
}
|
||
|
|
||
|
aggregate : '{' aggFields '}' {
|
||
|
fields, delims := $2.toNodes()
|
||
|
$$ = ast.NewMessageLiteralNode($1, fields, delims, $3)
|
||
|
}
|
||
|
|
||
|
aggFields : aggField {
|
||
|
if $1 != nil {
|
||
|
$$ = &messageFieldList{$1, nil}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggField aggFields {
|
||
|
if $1 != nil {
|
||
|
$$ = &messageFieldList{$1, $2}
|
||
|
} else {
|
||
|
$$ = $2
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
aggField : aggFieldEntry {
|
||
|
if $1 != nil {
|
||
|
$$ = &messageFieldEntry{$1, nil}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggFieldEntry ',' {
|
||
|
if $1 != nil {
|
||
|
$$ = &messageFieldEntry{$1, $2}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggFieldEntry ';' {
|
||
|
if $1 != nil {
|
||
|
$$ = &messageFieldEntry{$1, $2}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| error ',' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
aggFieldEntry : aggName ':' scalarConstant {
|
||
|
if $1 != nil {
|
||
|
$$ = ast.NewMessageFieldNode($1, $2, $3)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName ':' '[' ']' {
|
||
|
if $1 != nil {
|
||
|
val := ast.NewArrayLiteralNode($3, nil, nil, $4)
|
||
|
$$ = ast.NewMessageFieldNode($1, $2, val)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName ':' '[' constantList ']' {
|
||
|
if $1 != nil {
|
||
|
vals, commas := $4.toNodes()
|
||
|
val := ast.NewArrayLiteralNode($3, vals, commas, $5)
|
||
|
$$ = ast.NewMessageFieldNode($1, $2, val)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName ':' '[' error ']' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| aggName ':' aggregate {
|
||
|
if $1 != nil {
|
||
|
$$ = ast.NewMessageFieldNode($1, $2, $3)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName aggregate {
|
||
|
if $1 != nil {
|
||
|
$$ = ast.NewMessageFieldNode($1, nil, $2)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName ':' '<' aggFields '>' {
|
||
|
if $1 != nil {
|
||
|
fields, delims := $4.toNodes()
|
||
|
msg := ast.NewMessageLiteralNode($3, fields, delims, $5)
|
||
|
$$ = ast.NewMessageFieldNode($1, $2, msg)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName '<' aggFields '>' {
|
||
|
if $1 != nil {
|
||
|
fields, delims := $3.toNodes()
|
||
|
msg := ast.NewMessageLiteralNode($2, fields, delims, $4)
|
||
|
$$ = ast.NewMessageFieldNode($1, nil, msg)
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| aggName ':' '<' error '>' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| aggName '<' error '>' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
aggName : name {
|
||
|
$$ = ast.NewFieldReferenceNode($1)
|
||
|
}
|
||
|
| '[' typeIdent ']' {
|
||
|
$$ = ast.NewExtensionFieldReferenceNode($1, $2, $3)
|
||
|
}
|
||
|
| '[' error ']' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
constantList : constant {
|
||
|
$$ = &valueList{$1, nil, nil}
|
||
|
}
|
||
|
| constant ',' constantList {
|
||
|
$$ = &valueList{$1, $2, $3}
|
||
|
}
|
||
|
| '<' aggFields '>' {
|
||
|
fields, delims := $2.toNodes()
|
||
|
msg := ast.NewMessageLiteralNode($1, fields, delims, $3)
|
||
|
$$ = &valueList{msg, nil, nil}
|
||
|
}
|
||
|
| '<' aggFields '>' ',' constantList {
|
||
|
fields, delims := $2.toNodes()
|
||
|
msg := ast.NewMessageLiteralNode($1, fields, delims, $3)
|
||
|
$$ = &valueList{msg, $4, $5}
|
||
|
}
|
||
|
| '<' error '>' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| '<' error '>' ',' constantList {
|
||
|
$$ = $5
|
||
|
}
|
||
|
|
||
|
typeIdent : ident {
|
||
|
$$ = $1.toIdentValueNode(nil)
|
||
|
}
|
||
|
| '.' ident {
|
||
|
$$ = $2.toIdentValueNode($1)
|
||
|
}
|
||
|
|
||
|
field : _REQUIRED typeIdent name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
|
||
|
}
|
||
|
| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
|
||
|
}
|
||
|
| _REPEATED typeIdent name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
|
||
|
}
|
||
|
| typeIdent name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, nil, $5)
|
||
|
}
|
||
|
| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
|
||
|
}
|
||
|
| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
|
||
|
}
|
||
|
| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
|
||
|
}
|
||
|
| typeIdent name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, $5, $6)
|
||
|
}
|
||
|
|
||
|
compactOptions: '[' compactOptionDecls ']' {
|
||
|
opts, commas := $2.toNodes()
|
||
|
$$ = ast.NewCompactOptionsNode($1, opts, commas, $3)
|
||
|
}
|
||
|
|
||
|
compactOptionDecls : compactOption {
|
||
|
$$ = &compactOptionList{$1, nil, nil}
|
||
|
}
|
||
|
| compactOption ',' compactOptionDecls {
|
||
|
$$ = &compactOptionList{$1, $2, $3}
|
||
|
}
|
||
|
|
||
|
compactOption: optionName '=' constant {
|
||
|
refs, dots := $1.toNodes()
|
||
|
optName := ast.NewOptionNameNode(refs, dots)
|
||
|
$$ = ast.NewCompactOptionNode(optName, $2, $3)
|
||
|
}
|
||
|
|
||
|
group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
|
||
|
}
|
||
|
| _OPTIONAL _GROUP name '=' _INT_LIT '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
|
||
|
}
|
||
|
| _REPEATED _GROUP name '=' _INT_LIT '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
|
||
|
}
|
||
|
| _REQUIRED _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
|
||
|
}
|
||
|
| _OPTIONAL _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
|
||
|
}
|
||
|
| _REPEATED _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
|
||
|
}
|
||
|
|
||
|
oneof : _ONEOF name '{' ooDecls '}' {
|
||
|
$$ = ast.NewOneOfNode($1.ToKeyword(), $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
ooDecls : ooDecls ooDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| ooDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.OneOfElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
ooDecl : option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| oneofField {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| oneofGroup {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
oneofField : typeIdent name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, nil, $5)
|
||
|
}
|
||
|
| typeIdent name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, $5, $6)
|
||
|
}
|
||
|
|
||
|
oneofGroup : _GROUP name '=' _INT_LIT '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode(nil, $1.ToKeyword(), $2, $3, $4, nil, $5, $6, $7)
|
||
|
}
|
||
|
| _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
|
||
|
$$ = ast.NewGroupNode(nil, $1.ToKeyword(), $2, $3, $4, $5, $6, $7, $8)
|
||
|
}
|
||
|
|
||
|
mapField : mapType name '=' _INT_LIT ';' {
|
||
|
$$ = ast.NewMapFieldNode($1, $2, $3, $4, nil, $5)
|
||
|
}
|
||
|
| mapType name '=' _INT_LIT compactOptions ';' {
|
||
|
$$ = ast.NewMapFieldNode($1, $2, $3, $4, $5, $6)
|
||
|
}
|
||
|
|
||
|
mapType : _MAP '<' keyType ',' typeIdent '>' {
|
||
|
$$ = ast.NewMapTypeNode($1.ToKeyword(), $2, $3, $4, $5, $6)
|
||
|
}
|
||
|
|
||
|
keyType : _INT32
|
||
|
| _INT64
|
||
|
| _UINT32
|
||
|
| _UINT64
|
||
|
| _SINT32
|
||
|
| _SINT64
|
||
|
| _FIXED32
|
||
|
| _FIXED64
|
||
|
| _SFIXED32
|
||
|
| _SFIXED64
|
||
|
| _BOOL
|
||
|
| _STRING
|
||
|
|
||
|
extensions : _EXTENSIONS tagRanges ';' {
|
||
|
ranges, commas := $2.toNodes()
|
||
|
$$ = ast.NewExtensionRangeNode($1.ToKeyword(), ranges, commas, nil, $3)
|
||
|
}
|
||
|
| _EXTENSIONS tagRanges compactOptions ';' {
|
||
|
ranges, commas := $2.toNodes()
|
||
|
$$ = ast.NewExtensionRangeNode($1.ToKeyword(), ranges, commas, $3, $4)
|
||
|
}
|
||
|
|
||
|
tagRanges : tagRange {
|
||
|
$$ = &rangeList{$1, nil, nil}
|
||
|
}
|
||
|
| tagRange ',' tagRanges {
|
||
|
$$ = &rangeList{$1, $2, $3}
|
||
|
}
|
||
|
|
||
|
tagRange : _INT_LIT {
|
||
|
$$ = ast.NewRangeNode($1, nil, nil, nil)
|
||
|
}
|
||
|
| _INT_LIT _TO _INT_LIT {
|
||
|
$$ = ast.NewRangeNode($1, $2.ToKeyword(), $3, nil)
|
||
|
}
|
||
|
| _INT_LIT _TO _MAX {
|
||
|
$$ = ast.NewRangeNode($1, $2.ToKeyword(), nil, $3.ToKeyword())
|
||
|
}
|
||
|
|
||
|
enumRanges : enumRange {
|
||
|
$$ = &rangeList{$1, nil, nil}
|
||
|
}
|
||
|
| enumRange ',' enumRanges {
|
||
|
$$ = &rangeList{$1, $2, $3}
|
||
|
}
|
||
|
|
||
|
enumRange : intLit {
|
||
|
$$ = ast.NewRangeNode($1, nil, nil, nil)
|
||
|
}
|
||
|
| intLit _TO intLit {
|
||
|
$$ = ast.NewRangeNode($1, $2.ToKeyword(), $3, nil)
|
||
|
}
|
||
|
| intLit _TO _MAX {
|
||
|
$$ = ast.NewRangeNode($1, $2.ToKeyword(), nil, $3.ToKeyword())
|
||
|
}
|
||
|
|
||
|
intLit : _INT_LIT {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| '-' _INT_LIT {
|
||
|
$$ = ast.NewNegativeIntLiteralNode($1, $2)
|
||
|
}
|
||
|
|
||
|
msgReserved : _RESERVED tagRanges ';' {
|
||
|
ranges, commas := $2.toNodes()
|
||
|
$$ = ast.NewReservedRangesNode($1.ToKeyword(), ranges, commas, $3)
|
||
|
}
|
||
|
| reservedNames
|
||
|
|
||
|
enumReserved : _RESERVED enumRanges ';' {
|
||
|
ranges, commas := $2.toNodes()
|
||
|
$$ = ast.NewReservedRangesNode($1.ToKeyword(), ranges, commas, $3)
|
||
|
}
|
||
|
| reservedNames
|
||
|
|
||
|
reservedNames : _RESERVED fieldNames ';' {
|
||
|
names, commas := $2.toNodes()
|
||
|
$$ = ast.NewReservedNamesNode($1.ToKeyword(), names, commas, $3)
|
||
|
}
|
||
|
|
||
|
fieldNames : stringLit {
|
||
|
$$ = &nameList{$1.toStringValueNode(), nil, nil}
|
||
|
}
|
||
|
| stringLit ',' fieldNames {
|
||
|
$$ = &nameList{$1.toStringValueNode(), $2, $3}
|
||
|
}
|
||
|
|
||
|
enum : _ENUM name '{' enumDecls '}' {
|
||
|
$$ = ast.NewEnumNode($1.ToKeyword(), $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
enumDecls : enumDecls enumDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| enumDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.EnumElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
enumDecl : option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| enumValue {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| enumReserved {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
enumValue : name '=' intLit ';' {
|
||
|
$$ = ast.NewEnumValueNode($1, $2, $3, nil, $4)
|
||
|
}
|
||
|
| name '=' intLit compactOptions ';' {
|
||
|
$$ = ast.NewEnumValueNode($1, $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
message : _MESSAGE name '{' messageDecls '}' {
|
||
|
$$ = ast.NewMessageNode($1.ToKeyword(), $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
messageDecls : messageDecls messageDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| messageDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.MessageElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
messageDecl : field {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| enum {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| message {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| extend {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| extensions {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| group {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| oneof {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| mapField {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| msgReserved {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
extend : _EXTEND typeIdent '{' extendDecls '}' {
|
||
|
$$ = ast.NewExtendNode($1.ToKeyword(), $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
extendDecls : extendDecls extendDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| extendDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.ExtendElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
extendDecl : field {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| group {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
service : _SERVICE name '{' serviceDecls '}' {
|
||
|
$$ = ast.NewServiceNode($1.ToKeyword(), $2, $3, $4, $5)
|
||
|
}
|
||
|
|
||
|
serviceDecls : serviceDecls serviceDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| serviceDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.ServiceElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
// NB: doc suggests support for "stream" declaration, separate from "rpc", but
|
||
|
// it does not appear to be supported in protoc (doc is likely from grammar for
|
||
|
// Google-internal version of protoc, with support for streaming stubby)
|
||
|
serviceDecl : option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| rpc {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
rpc : _RPC name rpcType _RETURNS rpcType ';' {
|
||
|
$$ = ast.NewRPCNode($1.ToKeyword(), $2, $3, $4.ToKeyword(), $5, $6)
|
||
|
}
|
||
|
| _RPC name rpcType _RETURNS rpcType '{' rpcDecls '}' {
|
||
|
$$ = ast.NewRPCNodeWithBody($1.ToKeyword(), $2, $3, $4.ToKeyword(), $5, $6, $7, $8)
|
||
|
}
|
||
|
|
||
|
rpcType : '(' _STREAM typeIdent ')' {
|
||
|
$$ = ast.NewRPCTypeNode($1, $2.ToKeyword(), $3, $4)
|
||
|
}
|
||
|
| '(' typeIdent ')' {
|
||
|
$$ = ast.NewRPCTypeNode($1, nil, $2, $3)
|
||
|
}
|
||
|
|
||
|
rpcDecls : rpcDecls rpcDecl {
|
||
|
if $2 != nil {
|
||
|
$$ = append($1, $2)
|
||
|
} else {
|
||
|
$$ = $1
|
||
|
}
|
||
|
}
|
||
|
| rpcDecl {
|
||
|
if $1 != nil {
|
||
|
$$ = []ast.RPCElement{$1}
|
||
|
} else {
|
||
|
$$ = nil
|
||
|
}
|
||
|
}
|
||
|
| {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
rpcDecl : option {
|
||
|
$$ = $1
|
||
|
}
|
||
|
| ';' {
|
||
|
$$ = ast.NewEmptyDeclNode($1)
|
||
|
}
|
||
|
| error ';' {
|
||
|
$$ = nil
|
||
|
}
|
||
|
| error {
|
||
|
$$ = nil
|
||
|
}
|
||
|
|
||
|
name : _NAME
|
||
|
| _SYNTAX
|
||
|
| _IMPORT
|
||
|
| _WEAK
|
||
|
| _PUBLIC
|
||
|
| _PACKAGE
|
||
|
| _OPTION
|
||
|
| _TRUE
|
||
|
| _FALSE
|
||
|
| _INF
|
||
|
| _NAN
|
||
|
| _REPEATED
|
||
|
| _OPTIONAL
|
||
|
| _REQUIRED
|
||
|
| _DOUBLE
|
||
|
| _FLOAT
|
||
|
| _INT32
|
||
|
| _INT64
|
||
|
| _UINT32
|
||
|
| _UINT64
|
||
|
| _SINT32
|
||
|
| _SINT64
|
||
|
| _FIXED32
|
||
|
| _FIXED64
|
||
|
| _SFIXED32
|
||
|
| _SFIXED64
|
||
|
| _BOOL
|
||
|
| _STRING
|
||
|
| _BYTES
|
||
|
| _GROUP
|
||
|
| _ONEOF
|
||
|
| _MAP
|
||
|
| _EXTENSIONS
|
||
|
| _TO
|
||
|
| _MAX
|
||
|
| _RESERVED
|
||
|
| _ENUM
|
||
|
| _MESSAGE
|
||
|
| _EXTEND
|
||
|
| _SERVICE
|
||
|
| _RPC
|
||
|
| _STREAM
|
||
|
| _RETURNS
|
||
|
|
||
|
%%
|