xref: /Universal-ctags/peg/thrift.peg (revision 243bfd56d3e6ce287995c1fff534e20047e1babc)
1#
2# This file is derived from
3# https://raw.githubusercontent.com/samuel/go-thrift/master/parser/grammar.peg
4# (commit id: 586f6174a55deba8cbe982f15ecc28a901e44f4a)
5#
6# Reference:
7#     - https://thrift.apache.org/docs/idl
8#     - https://diwakergupta.github.io/thrift-missing-guide/
9#
10#
11# Copyright (c) 2012, Samuel Stauffer <samuel@descolada.com>
12# All rights reserved.
13#
14# Redistribution and use in source and binary forms, with or without
15# modification, are permitted provided that the following conditions are met:
16#
17# * Redistributions of source code must retain the above copyright
18#   notice, this list of conditions and the following disclaimer.
19# * Redistributions in binary form must reproduce the above copyright
20#   notice, this list of conditions and the following disclaimer in the
21#   documentation and/or other materials provided with the distribution.
22# * Neither the name of the author nor the
23#   names of its contributors may be used to endorse or promote products
24#   derived from this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
30# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36#
37%prefix "pthrift"
38
39%auxil "struct parserCtx *"
40
41%earlysource {
42    #include "general.h"
43}
44
45%header {
46    struct parserCtx;
47}
48
49%source {
50#include "thrift_pre.h"
51#include "routines.h"
52}
53
54Grammar <- __ ( Statement __ )* (EOF / SyntaxError)
55SyntaxError <- .
56
57# MODIFIED
58Include <- <( "include" / "cpp_include" )> _ <Literal> EOS {
59    vString *f = unliteral ($2);
60    if (vStringLength(f) > 0)
61    {
62        if ($1[0] == 'i')
63            makeThriftTagFull (auxil, vStringValue (f), $2s, K_THRIFTFILE, THRIFT_THRIFT_FILE_INCLUDED, false);
64        else
65        {
66            tagEntryInfo e;
67            initForeignRefTagEntry (&e, vStringValue(f), getNamedLanguage ("C++", 0), CXXTagKindINCLUDE, CR_HEADER_LOCAL);
68            e.lineNumber = getInputLineNumberForFileOffset ($2s);
69            e.filePosition = getInputFilePositionForLine (e.lineNumber);
70            makeTagEntry (&e);
71        }
72    }
73    vStringDelete (f);
74}
75
76Statement <- Include / Namespace / Const / Enum / TypeDef / Struct / Exception / Union / Service
77
78Namespace <- "namespace" _ <[-*a-z.]+> _ <Identifier> {
79    int r = makeThriftTag (auxil, $2, $2s, K_NAMESPACE, false);
80    attachParserFieldToCorkEntry (r, ThriftFields[F_TARGET].ftype, $1);
81} EOS
82
83Const <- "const" _ <FieldType> _ <Identifier> {
84    int r = makeThriftTag (auxil, $2, $2s, K_CONST, false);
85    tagEntryInfo *e = getEntryInCorkQueue (r);
86    if (e)
87    {
88        e->extensionFields.typeRef[0] = eStrdup ("typename");
89        e->extensionFields.typeRef[1] = eStrdup ($1);
90    }
91} __ "=" __ ConstValue _ ListSeparator? EOS
92# MODIFIED
93
94Enum <- "enum" { PUSH_KIND (auxil, K_ENUM); } _ <Identifier> {
95    makeThriftTag (auxil, $1, $1s, USE_KIND_STACK, true);
96} __ '{' __ (EnumValue __)* '}' _ TypeAnnotations? EOS { POP_KIND (auxil, true); }
97
98EnumValue <- <Identifier> {
99    makeThriftTag (auxil, $1, $1s, K_ENUMERATOR, false);
100} _ ('=' _ IntConstant)? _ TypeAnnotations? ListSeparator?
101
102
103TypeDef <- "typedef" _ <FieldType> _ <Identifier> {
104    int r = makeThriftTag (auxil, $2, $2s, K_TYPEDEF, false);
105    tagEntryInfo *e = getEntryInCorkQueue (r);
106    if (e)
107    {
108        e->extensionFields.typeRef[0] = eStrdup ("typename");
109        e->extensionFields.typeRef[1] = eStrdup ($1);
110    }
111} _ TypeAnnotations? EOS
112
113Struct <- "struct" { PUSH_KIND (auxil, K_STRUCT); }_ StructLike { POP_KIND (auxil, true); }
114Exception <- "exception" { PUSH_KIND (auxil, K_EXCEPTION); } _ StructLike { POP_KIND (auxil, true); }
115Union <- "union" { PUSH_KIND (auxil, K_UNION); }  _ StructLike { POP_KIND (auxil, true); }
116StructLike <- <Identifier> {
117    makeThriftTag (auxil, $1, $1s, USE_KIND_STACK, true);
118    PUSH_KIND (auxil, K_MEMBER);
119} __ '{' __ FieldList '}' _ TypeAnnotations? EOS { POP_KIND (auxil, false); }
120
121FieldList <- (Field __)*
122
123Field <- IntConstant _ ':' _ FieldReq? _ <FieldType> _ <Identifier> {
124    int r = makeThriftTag (auxil, $2, $2s, USE_KIND_STACK, false);
125    tagEntryInfo *e = getEntryInCorkQueue (r);
126    if (e)
127    {
128        e->extensionFields.typeRef[0] = eStrdup ("typename");
129        e->extensionFields.typeRef[1] = eStrdup ($1);
130    }
131} __ ('=' _ ConstValue)? _ TypeAnnotations? ListSeparator?
132
133FieldReq <- ("required" / "optional")
134
135Service <- "service" _ <Identifier> {
136    makeThriftTag (auxil, $1, $1s, K_SERVICE, true);
137} _ ("extends" __ <Identifier> {
138        int r = BASE_SCOPE (auxil);
139        tagEntryInfo *e = getEntryInCorkQueue (r);
140        if (e)
141            e->extensionFields.inheritance = eStrdup ($2);
142} __)? __ '{' __ (Function __)* ('}' / EndOfServiceError) _ TypeAnnotations?  EOS {
143    POP_SCOPE (auxil);
144}
145EndOfServiceError <- .
146
147Function <- ("oneway" __)? <FunctionType> __ <Identifier> {
148    int r = makeThriftTag (auxil, $2, $2s, K_FUNCTION, true);
149    tagEntryInfo *e = getEntryInCorkQueue (r);
150    if (e)
151    {
152        e->extensionFields.typeRef[0] = eStrdup ("typename");
153        e->extensionFields.typeRef[1] = eStrdup ($1);
154    }
155    PUSH_KIND (auxil, K_PARAMETER);
156} _ <'(' __ FieldList ')'> {
157    int r = BASE_SCOPE (auxil);
158    tagEntryInfo *e = getEntryInCorkQueue (r);
159    if (e)
160         e->extensionFields.signature = eStrdup ($3);
161} __ Throws? _ TypeAnnotations? ListSeparator? { POP_KIND (auxil, true); }
162
163FunctionType <- ("void" / FieldType)
164
165Throws <- "throws" { PUSH_KIND (auxil, K_THROWSPARAM); } __ < '(' __ FieldList ')' > {
166    int r = BASE_SCOPE (auxil);
167    attachParserFieldToCorkEntry (r, ThriftFields[F_THROWS].ftype, $1);
168    POP_KIND (auxil, false);
169}
170
171FieldType <- (BaseType / ContainerType / Identifier)
172
173# DefinitionType <- (BaseType / ContainerType)
174
175BaseType <- BaseTypeName _ TypeAnnotations?
176
177BaseTypeName <- ("bool" / "byte" / "i16" / "i32" / "i64" / "double" / "string" / "binary" )
178
179ContainerType <- (MapType / SetType / ListType)
180
181MapType <- CppType? "map" WS "<" WS FieldType WS "," WS FieldType WS ">" _ TypeAnnotations?
182
183SetType <- CppType? "set" WS "<" WS FieldType WS ">" _ TypeAnnotations?
184
185ListType <- "list" WS "<" WS FieldType WS ">" _ TypeAnnotations?
186
187CppType <- "cpp_type" Literal
188
189ConstValue <- Literal / DoubleConstant / IntConstant / ConstMap / ConstList / Identifier
190
191TypeAnnotations <- '(' __ TypeAnnotation* ')'
192
193TypeAnnotation <- Identifier _ ('=' __ Literal)? ListSeparator? __
194
195IntConstant <- [-+]? Digit+
196
197DoubleConstant <- [-+]? Digit* '.' Digit* ( ['Ee'] IntConstant )?
198
199ConstList <- '[' __ (ConstValue __ ListSeparator? __)* __ ']'
200
201# MODIFIED
202ConstMap <- '{' __ (ConstValue __ ':' __ ConstValue __ (ListSeparator? / &'}') __)* '}'
203
204# ...
205Literal <- (('"' ("\\\"" / [^"])* '"') / ("'" ("\\'" / [^'])* "'"))
206# '"
207
208Identifier <- (Letter / '_')+ (Letter / Digit / [._])*
209
210ListSeparator <- [,;]
211Letter <- [A-Za-z]
212Digit <- [0-9]
213
214# //
215
216SourceChar <- .
217Comment <- MultiLineComment / SingleLineComment
218MultiLineComment <- "/*" ( !"*/" SourceChar )* "*/"
219MultiLineCommentNoLineTerminator <- "/*" ( !( "*/" / EOL ) SourceChar )* "*/"
220SingleLineComment <- ("//" ( !EOL SourceChar )*) / ("#" ( !EOL SourceChar )*)
221
222__ <- ( Whitespace / EOL / Comment )*
223_ <- ( Whitespace / MultiLineCommentNoLineTerminator )*
224WS <- Whitespace*
225
226Whitespace <- [ \t\r]
227EOL <- '\n'
228EOS <- __ ';' / _ SingleLineComment? EOL / __ EOF
229
230EOF <- !.
231
232%%
233#include "thrift_post.h"
234