16ea83ed2SMasatake YAMATO /*
26ea83ed2SMasatake YAMATO *
36ea83ed2SMasatake YAMATO * Copyright (c) 2011, Ivan Krasilnikov
46ea83ed2SMasatake YAMATO *
56ea83ed2SMasatake YAMATO * This source code is released for free distribution under the terms of the
66ea83ed2SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
76ea83ed2SMasatake YAMATO *
86ea83ed2SMasatake YAMATO * This module implements parsing of protocol buffers definition files
96ea83ed2SMasatake YAMATO * (http://code.google.com/apis/protocolbuffers/docs/proto.html)
106ea83ed2SMasatake YAMATO */
116ea83ed2SMasatake YAMATO
126ea83ed2SMasatake YAMATO /*
136ea83ed2SMasatake YAMATO Masatake YAMATO takes this from https://sourceforge.net/p/ctags/patches/74/
146ea83ed2SMasatake YAMATO after getting following approval:
156ea83ed2SMasatake YAMATO ===============================================================================
166ea83ed2SMasatake YAMATO Message-ID: <CALPttHe+hSa_kjwx6GoWS6CsDf_OG0bcmhmPahb4shnKb8tkWg@mail.gmail.com>
176ea83ed2SMasatake YAMATO Subject: Re: your protobuf.patch
186ea83ed2SMasatake YAMATO From: Ivan Krasilnikov <infnty@gmail.com>
196ea83ed2SMasatake YAMATO To: m_yamato@users.sf.net
206ea83ed2SMasatake YAMATO Date: Fri, 8 Jul 2016 15:37:07 +0200
216ea83ed2SMasatake YAMATO
226ea83ed2SMasatake YAMATO Hi, yes, it's fine, no problem.
236ea83ed2SMasatake YAMATO
246ea83ed2SMasatake YAMATO --
256ea83ed2SMasatake YAMATO Ivan
266ea83ed2SMasatake YAMATO
276ea83ed2SMasatake YAMATO On 8 July 2016 at 06:31, <m_yamato@users.sf.net> wrote:
286ea83ed2SMasatake YAMATO
296ea83ed2SMasatake YAMATO > Hi,
306ea83ed2SMasatake YAMATO >
316ea83ed2SMasatake YAMATO > I am a developer of universal ctags(http://ctags.io).
326ea83ed2SMasatake YAMATO >
336ea83ed2SMasatake YAMATO > I would like to merge your patch for protobuf in *GPL v2 or later*.
346ea83ed2SMasatake YAMATO >
356ea83ed2SMasatake YAMATO > Is it o.k.?
366ea83ed2SMasatake YAMATO > ------------------------------
376ea83ed2SMasatake YAMATO >
386ea83ed2SMasatake YAMATO > This message was sent to you via the SourceForge web mail form.
396ea83ed2SMasatake YAMATO > You may reply to this message directly, or at
406ea83ed2SMasatake YAMATO > https://sourceforge.net/u/userid-2121776/profile/send_message
416ea83ed2SMasatake YAMATO >
426ea83ed2SMasatake YAMATO ===============================================================================
436ea83ed2SMasatake YAMATO */
446ea83ed2SMasatake YAMATO
456ea83ed2SMasatake YAMATO /*
466ea83ed2SMasatake YAMATO * INCLUDE FILES
476ea83ed2SMasatake YAMATO */
486ea83ed2SMasatake YAMATO #include "general.h" /* must always come first */
496ea83ed2SMasatake YAMATO
506ea83ed2SMasatake YAMATO #include <string.h>
516ea83ed2SMasatake YAMATO #include <ctype.h>
526ea83ed2SMasatake YAMATO
5387214e15SMasatake YAMATO #include "cpreprocessor.h"
546ea83ed2SMasatake YAMATO
556ea83ed2SMasatake YAMATO #include "entry.h"
566ea83ed2SMasatake YAMATO #include "keyword.h"
576ea83ed2SMasatake YAMATO #include "parse.h"
5859b6f293SMasatake YAMATO #include "read.h"
596ea83ed2SMasatake YAMATO #include "vstring.h"
606ea83ed2SMasatake YAMATO
616ea83ed2SMasatake YAMATO /*
626ea83ed2SMasatake YAMATO * DATA DEFINITIONS
636ea83ed2SMasatake YAMATO */
646ea83ed2SMasatake YAMATO static langType Lang_protobuf;
656ea83ed2SMasatake YAMATO
666ea83ed2SMasatake YAMATO typedef enum {
67e09c310eSMasatake YAMATO SYNTAX_UNKNOWN,
68e09c310eSMasatake YAMATO SYNTAX_PROTO2,
69e09c310eSMasatake YAMATO SYNTAX_PROTO3,
70e09c310eSMasatake YAMATO } protobufSyntax;
71*2de665ecSMasatake YAMATO static protobufSyntax syntax = SYNTAX_UNKNOWN;
72e09c310eSMasatake YAMATO
73e09c310eSMasatake YAMATO typedef enum {
746ea83ed2SMasatake YAMATO PK_PACKAGE,
756ea83ed2SMasatake YAMATO PK_MESSAGE,
766ea83ed2SMasatake YAMATO PK_FIELD,
776ea83ed2SMasatake YAMATO PK_ENUMERATOR,
786ea83ed2SMasatake YAMATO PK_ENUM,
796ea83ed2SMasatake YAMATO PK_SERVICE,
80ac4a85f0SMasatake YAMATO PK_RPC,
81ac4a85f0SMasatake YAMATO PK_ONEOF,
82602d6ba1SMasatake YAMATO PK_GROUP,
831fa2993eSMasatake YAMATO PK_PROTODEF,
846ea83ed2SMasatake YAMATO } protobufKind;
856ea83ed2SMasatake YAMATO
86b2e1d739SMasatake YAMATO typedef enum {
87b2e1d739SMasatake YAMATO R_MESSAGE_EXTENSION,
88b2e1d739SMasatake YAMATO } protobufMessageRole;
89b2e1d739SMasatake YAMATO
901fa2993eSMasatake YAMATO typedef enum {
911fa2993eSMasatake YAMATO R_PROTODEF_IMPORTED,
921fa2993eSMasatake YAMATO } protobufProtodefRole;
931fa2993eSMasatake YAMATO
94b2e1d739SMasatake YAMATO static roleDefinition ProtobufMessageRoles [] = {
95b2e1d739SMasatake YAMATO { true, "extension", "extending the message" },
96b2e1d739SMasatake YAMATO };
97b2e1d739SMasatake YAMATO
981fa2993eSMasatake YAMATO static roleDefinition ProtobufProtodefRoles [] = {
991fa2993eSMasatake YAMATO { true, "imported", "imported" },
1001fa2993eSMasatake YAMATO };
1011fa2993eSMasatake YAMATO
102e112e8abSMasatake YAMATO static kindDefinition ProtobufKinds [] = {
103ce990805SThomas Braun { true, 'p', "package", "packages" },
104b2e1d739SMasatake YAMATO { true, 'm', "message", "messages",
105b2e1d739SMasatake YAMATO .referenceOnly = false, ATTACH_ROLES (ProtobufMessageRoles)},
106ce990805SThomas Braun { true, 'f', "field", "fields" },
107ce990805SThomas Braun { true, 'e', "enumerator", "enum constants" },
108ce990805SThomas Braun { true, 'g', "enum", "enum types" },
109ce990805SThomas Braun { true, 's', "service", "services" },
110f64240f4SMasatake YAMATO { true, 'r', "rpc", "RPC methods" },
111ac4a85f0SMasatake YAMATO { true, 'o', "oneof", "oneof names" },
112602d6ba1SMasatake YAMATO { true, 'G', "group", "groups" },
1131fa2993eSMasatake YAMATO { true, 'D', "protodef", ".proto definition",
1141fa2993eSMasatake YAMATO .referenceOnly = true, ATTACH_ROLES (ProtobufProtodefRoles)},
1156ea83ed2SMasatake YAMATO };
1166ea83ed2SMasatake YAMATO
1176ea83ed2SMasatake YAMATO typedef enum eKeywordId {
1186ea83ed2SMasatake YAMATO KEYWORD_OPTION,
1196ea83ed2SMasatake YAMATO KEYWORD_PACKAGE,
1206ea83ed2SMasatake YAMATO KEYWORD_MESSAGE,
1216ea83ed2SMasatake YAMATO KEYWORD_ENUM,
1226ea83ed2SMasatake YAMATO KEYWORD_REPEATED,
1236ea83ed2SMasatake YAMATO KEYWORD_OPTIONAL,
1246ea83ed2SMasatake YAMATO KEYWORD_REQUIRED,
1256ea83ed2SMasatake YAMATO KEYWORD_SERVICE,
1266ea83ed2SMasatake YAMATO KEYWORD_RPC,
127ccb2363fSMasatake YAMATO KEYWORD_STREAM,
128ccb2363fSMasatake YAMATO KEYWORD_RETURNS,
129b2e1d739SMasatake YAMATO KEYWORD_EXTEND,
130ac4a85f0SMasatake YAMATO KEYWORD_ONEOF,
1312fab7ad8SMasatake YAMATO KEYWORD_MAP,
132602d6ba1SMasatake YAMATO KEYWORD_GROUP,
1331fa2993eSMasatake YAMATO KEYWORD_IMPORT,
1341fa2993eSMasatake YAMATO KEYWORD_PUBLIC,
1351fa2993eSMasatake YAMATO KEYWORD_WEAK,
136e09c310eSMasatake YAMATO KEYWORD_SYNTAX,
1376ea83ed2SMasatake YAMATO } keywordId;
1386ea83ed2SMasatake YAMATO
1396ea83ed2SMasatake YAMATO static const keywordTable ProtobufKeywordTable [] = {
1406ea83ed2SMasatake YAMATO { "option", KEYWORD_OPTION },
1416ea83ed2SMasatake YAMATO { "package", KEYWORD_PACKAGE },
1426ea83ed2SMasatake YAMATO { "message", KEYWORD_MESSAGE },
1436ea83ed2SMasatake YAMATO { "enum", KEYWORD_ENUM },
1446ea83ed2SMasatake YAMATO { "repeated", KEYWORD_REPEATED },
1456ea83ed2SMasatake YAMATO { "optional", KEYWORD_OPTIONAL },
1466ea83ed2SMasatake YAMATO { "required", KEYWORD_REQUIRED },
1476ea83ed2SMasatake YAMATO { "service", KEYWORD_SERVICE },
1486ea83ed2SMasatake YAMATO { "rpc", KEYWORD_RPC },
149ccb2363fSMasatake YAMATO { "stream", KEYWORD_STREAM },
150ccb2363fSMasatake YAMATO { "returns", KEYWORD_RETURNS },
151b2e1d739SMasatake YAMATO { "extend", KEYWORD_EXTEND },
152ac4a85f0SMasatake YAMATO { "oneof", KEYWORD_ONEOF },
1532fab7ad8SMasatake YAMATO { "map", KEYWORD_MAP },
154602d6ba1SMasatake YAMATO { "group", KEYWORD_GROUP },
1551fa2993eSMasatake YAMATO { "import", KEYWORD_IMPORT },
1561fa2993eSMasatake YAMATO { "public", KEYWORD_PUBLIC },
1571fa2993eSMasatake YAMATO { "weak", KEYWORD_WEAK },
158e09c310eSMasatake YAMATO { "syntax", KEYWORD_SYNTAX },
1596ea83ed2SMasatake YAMATO };
1606ea83ed2SMasatake YAMATO
1616ea83ed2SMasatake YAMATO #define TOKEN_EOF 0
1626ea83ed2SMasatake YAMATO #define TOKEN_ID 'i'
1631fa2993eSMasatake YAMATO #define TOKEN_STR 's'
1646ea83ed2SMasatake YAMATO
1656ea83ed2SMasatake YAMATO static struct sTokenInfo {
1666ea83ed2SMasatake YAMATO int type; /* one of TOKEN_* constants or punctuation characters */
1676ea83ed2SMasatake YAMATO keywordId keyword;
1686ea83ed2SMasatake YAMATO vString *value;
1696ea83ed2SMasatake YAMATO } token;
1706ea83ed2SMasatake YAMATO
171602d6ba1SMasatake YAMATO
172602d6ba1SMasatake YAMATO /*
173602d6ba1SMasatake YAMATO * FUNCTION DECLARATIONS
174602d6ba1SMasatake YAMATO */
175602d6ba1SMasatake YAMATO static void findProtobufTags0 (bool oneshot, int originalScopeCorkIndex);
176602d6ba1SMasatake YAMATO
177602d6ba1SMasatake YAMATO
1786ea83ed2SMasatake YAMATO /*
1796ea83ed2SMasatake YAMATO * FUNCTION DEFINITIONS
1806ea83ed2SMasatake YAMATO */
1816ea83ed2SMasatake YAMATO
nextTokenFull(bool expectingStringLiteral)1821fa2993eSMasatake YAMATO static void nextTokenFull (bool expectingStringLiteral)
1836ea83ed2SMasatake YAMATO {
1846ea83ed2SMasatake YAMATO int c;
1856ea83ed2SMasatake YAMATO
1866ea83ed2SMasatake YAMATO repeat:
1876ea83ed2SMasatake YAMATO /*
1886ea83ed2SMasatake YAMATO * .proto files may contain C and C++ style comments and
1896ea83ed2SMasatake YAMATO * quoted strings. cppGetc() takes care of them.
1906ea83ed2SMasatake YAMATO */
1916ea83ed2SMasatake YAMATO c = cppGetc ();
1926ea83ed2SMasatake YAMATO
1936ea83ed2SMasatake YAMATO token.keyword = KEYWORD_NONE;
1946ea83ed2SMasatake YAMATO if (c <= 0)
1956ea83ed2SMasatake YAMATO token.type = TOKEN_EOF;
1962fab7ad8SMasatake YAMATO else if (c == '{' || c == '}' || c == ';' || c == '.' || c == '=' || c == ',' || c == '<' || c == '>')
1976ea83ed2SMasatake YAMATO token.type = c;
1984851a58bSMasatake YAMATO else if (cppIsalnum (c) || c == '_')
1996ea83ed2SMasatake YAMATO {
2006ea83ed2SMasatake YAMATO token.type = TOKEN_ID;
2016ea83ed2SMasatake YAMATO vStringClear (token.value);
2024851a58bSMasatake YAMATO while (c > 0 && (cppIsalnum (c) || c == '_')) {
2036ea83ed2SMasatake YAMATO vStringPut (token.value, c);
2046ea83ed2SMasatake YAMATO c = cppGetc ();
2056ea83ed2SMasatake YAMATO }
20631a85388SJiří Techet token.keyword = lookupCaseKeyword (vStringValue (token.value), Lang_protobuf);
2076ea83ed2SMasatake YAMATO cppUngetc (c);
2086ea83ed2SMasatake YAMATO }
2091fa2993eSMasatake YAMATO else if (expectingStringLiteral && c == STRING_SYMBOL)
2101fa2993eSMasatake YAMATO {
2111fa2993eSMasatake YAMATO token.type = TOKEN_STR;
2121fa2993eSMasatake YAMATO vStringCopy (token.value,
2131fa2993eSMasatake YAMATO cppGetLastCharOrStringContents ());
2141fa2993eSMasatake YAMATO }
2156ea83ed2SMasatake YAMATO else
2166ea83ed2SMasatake YAMATO goto repeat; /* anything else is not important for this parser */
2176ea83ed2SMasatake YAMATO }
2186ea83ed2SMasatake YAMATO
nextToken(void)2191fa2993eSMasatake YAMATO static void nextToken (void)
2201fa2993eSMasatake YAMATO {
2211fa2993eSMasatake YAMATO nextTokenFull (false);
2221fa2993eSMasatake YAMATO }
2231fa2993eSMasatake YAMATO
skipUntil(const char * punctuation)2246ea83ed2SMasatake YAMATO static void skipUntil (const char *punctuation)
2256ea83ed2SMasatake YAMATO {
2266ea83ed2SMasatake YAMATO while (token.type != TOKEN_EOF && strchr (punctuation, token.type) == NULL)
2276ea83ed2SMasatake YAMATO nextToken ();
2286ea83ed2SMasatake YAMATO }
2296ea83ed2SMasatake YAMATO
parseFullQualifiedId(vString * buf)23092491b0bSMasatake YAMATO static void parseFullQualifiedId (vString *buf)
23192491b0bSMasatake YAMATO {
23292491b0bSMasatake YAMATO while (true)
23392491b0bSMasatake YAMATO {
23492491b0bSMasatake YAMATO nextToken ();
23592491b0bSMasatake YAMATO
23692491b0bSMasatake YAMATO if (token.type == TOKEN_ID)
23792491b0bSMasatake YAMATO {
23892491b0bSMasatake YAMATO if (vStringIsEmpty (buf) || vStringLast (buf) == '.')
23992491b0bSMasatake YAMATO vStringCat (buf, token.value);
24092491b0bSMasatake YAMATO else
24192491b0bSMasatake YAMATO break;
24292491b0bSMasatake YAMATO }
24392491b0bSMasatake YAMATO else if (token.type == '.')
24492491b0bSMasatake YAMATO {
24592491b0bSMasatake YAMATO if (vStringIsEmpty (buf) || vStringLast (buf) != '.')
24692491b0bSMasatake YAMATO vStringPut (buf, '.');
24792491b0bSMasatake YAMATO else
24892491b0bSMasatake YAMATO break;
24992491b0bSMasatake YAMATO }
25092491b0bSMasatake YAMATO else
25192491b0bSMasatake YAMATO break;
25292491b0bSMasatake YAMATO }
25392491b0bSMasatake YAMATO }
25492491b0bSMasatake YAMATO
tokenIsKeyword(keywordId keyword)2556ea83ed2SMasatake YAMATO static int tokenIsKeyword(keywordId keyword)
2566ea83ed2SMasatake YAMATO {
2576ea83ed2SMasatake YAMATO return token.type == TOKEN_ID && token.keyword == keyword;
2586ea83ed2SMasatake YAMATO }
2596ea83ed2SMasatake YAMATO
createProtobufTagFull(const vString * name,int kind,int role,int scopeCorkIndex)26070e24df0SMasatake YAMATO static int createProtobufTagFull (const vString *name, int kind, int role, int scopeCorkIndex)
2616ea83ed2SMasatake YAMATO {
2626ea83ed2SMasatake YAMATO static tagEntryInfo tag;
263ccb2363fSMasatake YAMATO int corkIndex = CORK_NIL;
2646ea83ed2SMasatake YAMATO
2656ea83ed2SMasatake YAMATO if (ProtobufKinds [kind].enabled)
2666ea83ed2SMasatake YAMATO {
26770e24df0SMasatake YAMATO initRefTagEntry (&tag, vStringValue (name), kind, role);
26870e24df0SMasatake YAMATO tag.extensionFields.scopeIndex = scopeCorkIndex;
269ccb2363fSMasatake YAMATO corkIndex = makeTagEntry (&tag);
2706ea83ed2SMasatake YAMATO }
271ccb2363fSMasatake YAMATO
272ccb2363fSMasatake YAMATO return corkIndex;
2736ea83ed2SMasatake YAMATO }
2746ea83ed2SMasatake YAMATO
createProtobufTag(const vString * name,int kind,int scopeCorkIndex)27570e24df0SMasatake YAMATO static int createProtobufTag (const vString *name, int kind, int scopeCorkIndex)
27670e24df0SMasatake YAMATO {
27770e24df0SMasatake YAMATO return createProtobufTagFull (name, kind, ROLE_DEFINITION_INDEX, scopeCorkIndex);
27870e24df0SMasatake YAMATO }
27970e24df0SMasatake YAMATO
parseEnumConstants(int scopeCorkIndex)28070e24df0SMasatake YAMATO static void parseEnumConstants (int scopeCorkIndex)
2816ea83ed2SMasatake YAMATO {
2826ea83ed2SMasatake YAMATO if (token.type != '{')
2836ea83ed2SMasatake YAMATO return;
2846ea83ed2SMasatake YAMATO nextToken ();
2856ea83ed2SMasatake YAMATO
2866ea83ed2SMasatake YAMATO while (token.type != TOKEN_EOF && token.type != '}')
2876ea83ed2SMasatake YAMATO {
2886ea83ed2SMasatake YAMATO if (token.type == TOKEN_ID && !tokenIsKeyword (KEYWORD_OPTION))
2896ea83ed2SMasatake YAMATO {
2906ea83ed2SMasatake YAMATO nextToken (); /* doesn't clear token.value if it's punctuation */
2916ea83ed2SMasatake YAMATO if (token.type == '=')
29270e24df0SMasatake YAMATO createProtobufTag (token.value, PK_ENUMERATOR, scopeCorkIndex);
2936ea83ed2SMasatake YAMATO }
2946ea83ed2SMasatake YAMATO
2956ea83ed2SMasatake YAMATO skipUntil (";}");
2966ea83ed2SMasatake YAMATO
2976ea83ed2SMasatake YAMATO if (token.type == ';')
2986ea83ed2SMasatake YAMATO nextToken ();
2996ea83ed2SMasatake YAMATO }
30059b6f293SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
3013671ad72SMasatake YAMATO if (e)
30259b6f293SMasatake YAMATO e->extensionFields.endLine = getInputLineNumber ();
3036ea83ed2SMasatake YAMATO }
3046ea83ed2SMasatake YAMATO
parseOneofField(int scopeCorkIndex)305ac4a85f0SMasatake YAMATO static void parseOneofField (int scopeCorkIndex)
306ac4a85f0SMasatake YAMATO {
307602d6ba1SMasatake YAMATO if (tokenIsKeyword (KEYWORD_GROUP))
308602d6ba1SMasatake YAMATO {
309602d6ba1SMasatake YAMATO findProtobufTags0 (true, scopeCorkIndex);
310602d6ba1SMasatake YAMATO return;
311602d6ba1SMasatake YAMATO }
312602d6ba1SMasatake YAMATO
313ac4a85f0SMasatake YAMATO vString *type = vStringNewCopy (token.value);
314ac4a85f0SMasatake YAMATO parseFullQualifiedId (type);
315ac4a85f0SMasatake YAMATO
316ac4a85f0SMasatake YAMATO if (token.type == TOKEN_ID)
317ac4a85f0SMasatake YAMATO {
318ac4a85f0SMasatake YAMATO int corkIndex = createProtobufTag (token.value, PK_FIELD, scopeCorkIndex);
319ac4a85f0SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
320ac4a85f0SMasatake YAMATO if (e)
321ac4a85f0SMasatake YAMATO {
322ac4a85f0SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
323ac4a85f0SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (type);
324ac4a85f0SMasatake YAMATO type = NULL;
325ac4a85f0SMasatake YAMATO }
326ac4a85f0SMasatake YAMATO }
327ac4a85f0SMasatake YAMATO
328ac4a85f0SMasatake YAMATO skipUntil (";}");
329ac4a85f0SMasatake YAMATO vStringDelete (type); /* NULL is acceptable */
330ac4a85f0SMasatake YAMATO }
331ac4a85f0SMasatake YAMATO
parseOneofFields(int scopeCorkIndex)332ac4a85f0SMasatake YAMATO static void parseOneofFields (int scopeCorkIndex)
333ac4a85f0SMasatake YAMATO {
334ac4a85f0SMasatake YAMATO if (token.type != '{')
335ac4a85f0SMasatake YAMATO return;
336ac4a85f0SMasatake YAMATO nextToken ();
337ac4a85f0SMasatake YAMATO
338ac4a85f0SMasatake YAMATO while (token.type != TOKEN_EOF && token.type != '}')
339ac4a85f0SMasatake YAMATO {
340ac4a85f0SMasatake YAMATO if (token.type == TOKEN_ID || token.type == '.')
341ac4a85f0SMasatake YAMATO {
342ac4a85f0SMasatake YAMATO parseOneofField (scopeCorkIndex);
343ac4a85f0SMasatake YAMATO if (token.type == ';')
344ac4a85f0SMasatake YAMATO nextToken ();
345ac4a85f0SMasatake YAMATO }
346ac4a85f0SMasatake YAMATO else
347ac4a85f0SMasatake YAMATO break;
348ac4a85f0SMasatake YAMATO }
34959b6f293SMasatake YAMATO
35059b6f293SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
3513671ad72SMasatake YAMATO if (e)
35259b6f293SMasatake YAMATO e->extensionFields.endLine = getInputLineNumber ();
353ac4a85f0SMasatake YAMATO }
354ac4a85f0SMasatake YAMATO
355ccb2363fSMasatake YAMATO #define gatherTypeinfo(VSTRING,CONDITION) \
356ccb2363fSMasatake YAMATO while (CONDITION) \
357ccb2363fSMasatake YAMATO { \
358ccb2363fSMasatake YAMATO if (token.type == TOKEN_ID) \
359ccb2363fSMasatake YAMATO vStringCat (VSTRING, token.value); \
360ccb2363fSMasatake YAMATO else if (tokenIsKeyword (KEYWORD_STREAM)) \
361ccb2363fSMasatake YAMATO { \
362ccb2363fSMasatake YAMATO vStringCat (VSTRING, token.value); \
363ccb2363fSMasatake YAMATO vStringPut (VSTRING, ' '); \
364ccb2363fSMasatake YAMATO } \
365ccb2363fSMasatake YAMATO else \
366ccb2363fSMasatake YAMATO vStringPut (VSTRING, token.type); \
367ccb2363fSMasatake YAMATO nextToken (); \
368ccb2363fSMasatake YAMATO }
369ccb2363fSMasatake YAMATO
parseRPCTypeinfos(int corkIndex)370ccb2363fSMasatake YAMATO static void parseRPCTypeinfos (int corkIndex)
371ccb2363fSMasatake YAMATO {
372ccb2363fSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
3733671ad72SMasatake YAMATO if (!e)
3743671ad72SMasatake YAMATO return;
375ccb2363fSMasatake YAMATO
376ccb2363fSMasatake YAMATO vString *signature = vStringNew ();
377ccb2363fSMasatake YAMATO gatherTypeinfo(signature,
378ccb2363fSMasatake YAMATO (token.type != TOKEN_EOF
379ccb2363fSMasatake YAMATO && token.type != '{' && token.type != ';'
380ccb2363fSMasatake YAMATO && !tokenIsKeyword (KEYWORD_RETURNS)));
381ccb2363fSMasatake YAMATO if (!vStringIsEmpty(signature))
382ccb2363fSMasatake YAMATO e->extensionFields.signature = vStringDeleteUnwrap (signature);
383ccb2363fSMasatake YAMATO else
384ccb2363fSMasatake YAMATO vStringDelete (signature);
385ccb2363fSMasatake YAMATO
386ccb2363fSMasatake YAMATO if (!tokenIsKeyword (KEYWORD_RETURNS))
387ccb2363fSMasatake YAMATO return;
388ccb2363fSMasatake YAMATO nextToken ();
389ccb2363fSMasatake YAMATO
390ccb2363fSMasatake YAMATO vString *typeref = vStringNew ();
391ccb2363fSMasatake YAMATO gatherTypeinfo(typeref, (token.type != EOF
392ccb2363fSMasatake YAMATO && token.type != '{' && token.type != ';'));
393ccb2363fSMasatake YAMATO if (!vStringIsEmpty(typeref))
394ccb2363fSMasatake YAMATO {
395ccb2363fSMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
396ccb2363fSMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (typeref);
397ccb2363fSMasatake YAMATO }
398ccb2363fSMasatake YAMATO else
399ccb2363fSMasatake YAMATO vStringDelete (typeref);
400ccb2363fSMasatake YAMATO }
401ccb2363fSMasatake YAMATO
parseStatementFull(int kind,int role,int scopeCorkIndex)40270e24df0SMasatake YAMATO static int parseStatementFull (int kind, int role, int scopeCorkIndex)
4036ea83ed2SMasatake YAMATO {
4044549fa56SMasatake YAMATO int corkIndex = CORK_NIL;
405b2e1d739SMasatake YAMATO vString *fullName = NULL;
4064549fa56SMasatake YAMATO vString *fieldType = NULL;
4076ea83ed2SMasatake YAMATO
4086ea83ed2SMasatake YAMATO if (kind == PK_FIELD)
4096ea83ed2SMasatake YAMATO {
4104549fa56SMasatake YAMATO fieldType = vStringNew ();
41113522841SMasatake YAMATO
41213522841SMasatake YAMATO if (syntax == SYNTAX_PROTO3
41313522841SMasatake YAMATO && !tokenIsKeyword (KEYWORD_REPEATED))
41413522841SMasatake YAMATO {
41513522841SMasatake YAMATO if (token.type == TOKEN_ID)
41613522841SMasatake YAMATO vStringCat (fieldType, token.value);
41713522841SMasatake YAMATO else if (token.type == '.')
41813522841SMasatake YAMATO vStringPut (fieldType, '.');
41913522841SMasatake YAMATO }
42013522841SMasatake YAMATO
4214549fa56SMasatake YAMATO parseFullQualifiedId (fieldType);
4224549fa56SMasatake YAMATO if (vStringIsEmpty (fieldType) || vStringLast (fieldType) == '.')
4234549fa56SMasatake YAMATO goto out;
4246ea83ed2SMasatake YAMATO }
4254549fa56SMasatake YAMATO else
4264549fa56SMasatake YAMATO nextToken ();
4276ea83ed2SMasatake YAMATO
428b2e1d739SMasatake YAMATO /* When extending message defined in the external package, the name
429b2e1d739SMasatake YAMATO * becomes longer. */
430b2e1d739SMasatake YAMATO if (kind == PK_MESSAGE && role == R_MESSAGE_EXTENSION)
431b2e1d739SMasatake YAMATO {
4326ea83ed2SMasatake YAMATO if (token.type != TOKEN_ID)
4334549fa56SMasatake YAMATO goto out;
4346ea83ed2SMasatake YAMATO
435b2e1d739SMasatake YAMATO fullName = vStringNewCopy (token.value);
43692491b0bSMasatake YAMATO parseFullQualifiedId (fullName);
437b2e1d739SMasatake YAMATO }
438b2e1d739SMasatake YAMATO else if (token.type != TOKEN_ID)
4394549fa56SMasatake YAMATO goto out;
440b2e1d739SMasatake YAMATO
4414549fa56SMasatake YAMATO corkIndex = createProtobufTagFull (fullName? fullName: token.value,
442b2e1d739SMasatake YAMATO kind, role, scopeCorkIndex);
443b2e1d739SMasatake YAMATO
444b2e1d739SMasatake YAMATO if (!fullName)
445b2e1d739SMasatake YAMATO nextToken ();
4464549fa56SMasatake YAMATO
4474549fa56SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
4483671ad72SMasatake YAMATO if (fieldType && e)
4493671ad72SMasatake YAMATO {
4504549fa56SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
4514549fa56SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (fieldType);
4524549fa56SMasatake YAMATO fieldType = NULL;
4534549fa56SMasatake YAMATO }
454b2e1d739SMasatake YAMATO
455ccb2363fSMasatake YAMATO if (kind == PK_RPC && corkIndex != CORK_NIL)
456ccb2363fSMasatake YAMATO parseRPCTypeinfos (corkIndex);
457ccb2363fSMasatake YAMATO
4586ea83ed2SMasatake YAMATO if (kind == PK_ENUM)
45970e24df0SMasatake YAMATO parseEnumConstants (corkIndex);
460ac4a85f0SMasatake YAMATO else if (kind == PK_ONEOF)
461ac4a85f0SMasatake YAMATO parseOneofFields (corkIndex);
46270e24df0SMasatake YAMATO
4634549fa56SMasatake YAMATO out:
4644549fa56SMasatake YAMATO vStringDelete (fieldType); /* NULL is acceptable. */
4654549fa56SMasatake YAMATO vStringDelete (fullName); /* NULL is acceptable. */
46670e24df0SMasatake YAMATO return corkIndex;
4676ea83ed2SMasatake YAMATO }
4686ea83ed2SMasatake YAMATO
parseStatement(int kind,int scopeCorkIndex)46970e24df0SMasatake YAMATO static int parseStatement (int kind, int scopeCorkIndex)
470f203b714SMasatake YAMATO {
47170e24df0SMasatake YAMATO return parseStatementFull (kind, ROLE_DEFINITION_INDEX, scopeCorkIndex);
47270e24df0SMasatake YAMATO }
47370e24df0SMasatake YAMATO
parsePackage(void)47470e24df0SMasatake YAMATO static int parsePackage (void)
47570e24df0SMasatake YAMATO {
47670e24df0SMasatake YAMATO int corkIndex = CORK_NIL;
47770e24df0SMasatake YAMATO
478f203b714SMasatake YAMATO vString *pkg = vStringNew ();
47992491b0bSMasatake YAMATO parseFullQualifiedId (pkg);
480f203b714SMasatake YAMATO if (vStringLength (pkg) > 0)
48170e24df0SMasatake YAMATO corkIndex = createProtobufTag (pkg, PK_PACKAGE, CORK_NIL);
482f203b714SMasatake YAMATO vStringDelete (pkg);
48392491b0bSMasatake YAMATO
48470e24df0SMasatake YAMATO return corkIndex;
485f203b714SMasatake YAMATO }
486f203b714SMasatake YAMATO
parseMap(int scopeCorkIndex)4872fab7ad8SMasatake YAMATO static void parseMap (int scopeCorkIndex)
4882fab7ad8SMasatake YAMATO {
4892fab7ad8SMasatake YAMATO nextToken ();
4902fab7ad8SMasatake YAMATO if (token.type != '<')
4912fab7ad8SMasatake YAMATO return;
4922fab7ad8SMasatake YAMATO
4932fab7ad8SMasatake YAMATO vString *typeref = vStringNewInit ("map<");
4942fab7ad8SMasatake YAMATO
4952fab7ad8SMasatake YAMATO nextToken ();
4962fab7ad8SMasatake YAMATO if (token.type != TOKEN_ID)
4972fab7ad8SMasatake YAMATO goto out;
4982fab7ad8SMasatake YAMATO
4992fab7ad8SMasatake YAMATO vStringCat (typeref, token.value);
5002fab7ad8SMasatake YAMATO
5012fab7ad8SMasatake YAMATO nextToken ();
5022fab7ad8SMasatake YAMATO if (token.type != ',')
5032fab7ad8SMasatake YAMATO goto out;
5042fab7ad8SMasatake YAMATO vStringPut (typeref, ',');
5052fab7ad8SMasatake YAMATO
5062fab7ad8SMasatake YAMATO vString *vtyperef = vStringNew ();
5072fab7ad8SMasatake YAMATO parseFullQualifiedId (vtyperef);
5082fab7ad8SMasatake YAMATO vStringCat (typeref, vtyperef);
5092fab7ad8SMasatake YAMATO vStringDelete (vtyperef);
5102fab7ad8SMasatake YAMATO if (vStringLast (typeref) == ',')
5112fab7ad8SMasatake YAMATO goto out;
5122fab7ad8SMasatake YAMATO
5132fab7ad8SMasatake YAMATO if (token.type != '>')
5142fab7ad8SMasatake YAMATO goto out;
5152fab7ad8SMasatake YAMATO vStringPut (typeref, '>');
5162fab7ad8SMasatake YAMATO
5172fab7ad8SMasatake YAMATO nextToken ();
5182fab7ad8SMasatake YAMATO if (token.type != TOKEN_ID)
5192fab7ad8SMasatake YAMATO goto out;
5202fab7ad8SMasatake YAMATO
5212fab7ad8SMasatake YAMATO int corkIndex = createProtobufTag (token.value, PK_FIELD, scopeCorkIndex);
5222fab7ad8SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
5232fab7ad8SMasatake YAMATO if (e)
5242fab7ad8SMasatake YAMATO {
5252fab7ad8SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
5262fab7ad8SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (typeref);
5272fab7ad8SMasatake YAMATO typeref = NULL;
5282fab7ad8SMasatake YAMATO }
5292fab7ad8SMasatake YAMATO
5302fab7ad8SMasatake YAMATO out:
5312fab7ad8SMasatake YAMATO vStringDelete (typeref);
5322fab7ad8SMasatake YAMATO }
5332fab7ad8SMasatake YAMATO
parseImport(int scopeCorkIndex)5341fa2993eSMasatake YAMATO static int parseImport (int scopeCorkIndex)
5351fa2993eSMasatake YAMATO {
5361fa2993eSMasatake YAMATO nextTokenFull (true);
5371fa2993eSMasatake YAMATO if (token.type == TOKEN_ID)
5381fa2993eSMasatake YAMATO {
5391fa2993eSMasatake YAMATO if (tokenIsKeyword (KEYWORD_PUBLIC)
5401fa2993eSMasatake YAMATO || tokenIsKeyword (KEYWORD_WEAK))
5411fa2993eSMasatake YAMATO nextTokenFull (true);
5421fa2993eSMasatake YAMATO else
5431fa2993eSMasatake YAMATO return CORK_NIL; /* Unexpected */
5441fa2993eSMasatake YAMATO }
5451fa2993eSMasatake YAMATO
5461fa2993eSMasatake YAMATO if (token.type == TOKEN_STR)
5471fa2993eSMasatake YAMATO return createProtobufTagFull (token.value,
5481fa2993eSMasatake YAMATO PK_PROTODEF, R_PROTODEF_IMPORTED,
5491fa2993eSMasatake YAMATO /* TODO: whether the package scope should be specified or not. */
5501fa2993eSMasatake YAMATO scopeCorkIndex
5511fa2993eSMasatake YAMATO );
5521fa2993eSMasatake YAMATO
5531fa2993eSMasatake YAMATO return CORK_NIL;
5541fa2993eSMasatake YAMATO }
555602d6ba1SMasatake YAMATO
parseSyntax(void)556e09c310eSMasatake YAMATO static void parseSyntax (void)
557e09c310eSMasatake YAMATO {
558e09c310eSMasatake YAMATO nextToken ();
559e09c310eSMasatake YAMATO if (token.type != '=')
560e09c310eSMasatake YAMATO return;
561e09c310eSMasatake YAMATO
562e09c310eSMasatake YAMATO nextTokenFull (true);
563e09c310eSMasatake YAMATO if (token.type == TOKEN_STR)
564e09c310eSMasatake YAMATO {
565e09c310eSMasatake YAMATO const vString *proto = cppGetLastCharOrStringContents ();
566e09c310eSMasatake YAMATO if (strcmp (vStringValue (proto), "proto2") == 0)
567e09c310eSMasatake YAMATO syntax = SYNTAX_PROTO2;
568e09c310eSMasatake YAMATO else if (strcmp (vStringValue (proto), "proto3") == 0)
569e09c310eSMasatake YAMATO syntax = SYNTAX_PROTO3;
570e09c310eSMasatake YAMATO else
571e09c310eSMasatake YAMATO syntax = SYNTAX_UNKNOWN;
572e09c310eSMasatake YAMATO }
573e09c310eSMasatake YAMATO }
574e09c310eSMasatake YAMATO
findProtobufTags0(bool oneshot,int originalScopeCorkIndex)575602d6ba1SMasatake YAMATO static void findProtobufTags0 (bool oneshot, int originalScopeCorkIndex)
5766ea83ed2SMasatake YAMATO {
577602d6ba1SMasatake YAMATO int scopeCorkIndex = originalScopeCorkIndex;
5786ea83ed2SMasatake YAMATO while (token.type != TOKEN_EOF)
5796ea83ed2SMasatake YAMATO {
58070e24df0SMasatake YAMATO int corkIndex = CORK_NIL;
58170e24df0SMasatake YAMATO bool dontChangeScope = false;
582e09c310eSMasatake YAMATO
583e09c310eSMasatake YAMATO if (tokenIsKeyword (KEYWORD_SYNTAX) && originalScopeCorkIndex == CORK_NIL)
584e09c310eSMasatake YAMATO {
585e09c310eSMasatake YAMATO parseSyntax ();
586e09c310eSMasatake YAMATO dontChangeScope = true;
587e09c310eSMasatake YAMATO }
588e09c310eSMasatake YAMATO else if (tokenIsKeyword (KEYWORD_PACKAGE))
58970e24df0SMasatake YAMATO {
59070e24df0SMasatake YAMATO corkIndex = parsePackage ();
59170e24df0SMasatake YAMATO scopeCorkIndex = corkIndex;
59270e24df0SMasatake YAMATO }
5936ea83ed2SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_MESSAGE))
59470e24df0SMasatake YAMATO corkIndex = parseStatement (PK_MESSAGE, scopeCorkIndex);
5956ea83ed2SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_ENUM))
59670e24df0SMasatake YAMATO {
59770e24df0SMasatake YAMATO corkIndex = parseStatement (PK_ENUM, scopeCorkIndex);
59870e24df0SMasatake YAMATO dontChangeScope = true;
59970e24df0SMasatake YAMATO }
6006ea83ed2SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_REPEATED) || tokenIsKeyword (KEYWORD_OPTIONAL) || tokenIsKeyword (KEYWORD_REQUIRED))
60170e24df0SMasatake YAMATO corkIndex = parseStatement (PK_FIELD, scopeCorkIndex);
6026ea83ed2SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_SERVICE))
60370e24df0SMasatake YAMATO corkIndex = parseStatement (PK_SERVICE, scopeCorkIndex);
6046ea83ed2SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_RPC))
60570e24df0SMasatake YAMATO corkIndex = parseStatement (PK_RPC, scopeCorkIndex);
606b2e1d739SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_EXTEND))
607b2e1d739SMasatake YAMATO corkIndex = parseStatementFull (PK_MESSAGE, R_MESSAGE_EXTENSION, scopeCorkIndex);
608ac4a85f0SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_ONEOF))
609ac4a85f0SMasatake YAMATO {
610ac4a85f0SMasatake YAMATO corkIndex = parseStatement (PK_ONEOF, scopeCorkIndex);
611ac4a85f0SMasatake YAMATO dontChangeScope = true;
612ac4a85f0SMasatake YAMATO }
6132fab7ad8SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_MAP))
6142fab7ad8SMasatake YAMATO parseMap (scopeCorkIndex);
615602d6ba1SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_GROUP))
616602d6ba1SMasatake YAMATO corkIndex = parseStatement (PK_GROUP, scopeCorkIndex);
6171fa2993eSMasatake YAMATO else if (tokenIsKeyword (KEYWORD_IMPORT))
6181fa2993eSMasatake YAMATO {
6191fa2993eSMasatake YAMATO corkIndex = parseImport (scopeCorkIndex);
6201fa2993eSMasatake YAMATO dontChangeScope = true;
6211fa2993eSMasatake YAMATO }
62213522841SMasatake YAMATO else if (tokenIsKeyword (KEYWORD_OPTION))
62313522841SMasatake YAMATO dontChangeScope = true;
62413522841SMasatake YAMATO else if (syntax == SYNTAX_PROTO3
6253671ad72SMasatake YAMATO && (token.type == '.' || token.type == TOKEN_ID))
62613522841SMasatake YAMATO {
62713522841SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
6283671ad72SMasatake YAMATO if (e && e->kindIndex == PK_MESSAGE)
62913522841SMasatake YAMATO corkIndex = parseStatement (PK_FIELD, scopeCorkIndex);
63013522841SMasatake YAMATO }
6316ea83ed2SMasatake YAMATO
6326ea83ed2SMasatake YAMATO skipUntil (";{}");
63370e24df0SMasatake YAMATO if (!dontChangeScope && token.type == '{' && corkIndex != CORK_NIL)
63470e24df0SMasatake YAMATO {
63570e24df0SMasatake YAMATO /* Enter the new scope. */
63670e24df0SMasatake YAMATO scopeCorkIndex = corkIndex;
63770e24df0SMasatake YAMATO }
6383671ad72SMasatake YAMATO else if (!dontChangeScope && token.type == '}')
63970e24df0SMasatake YAMATO {
64070e24df0SMasatake YAMATO /* Return to the parent scope. */
64170e24df0SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
6423671ad72SMasatake YAMATO if (e)
6433671ad72SMasatake YAMATO {
64470e24df0SMasatake YAMATO scopeCorkIndex = e->extensionFields.scopeIndex;
64559b6f293SMasatake YAMATO e->extensionFields.endLine = getInputLineNumber ();
64670e24df0SMasatake YAMATO }
6473671ad72SMasatake YAMATO }
6486ea83ed2SMasatake YAMATO nextToken ();
649602d6ba1SMasatake YAMATO
650602d6ba1SMasatake YAMATO if (oneshot && scopeCorkIndex == originalScopeCorkIndex)
651602d6ba1SMasatake YAMATO break;
6526ea83ed2SMasatake YAMATO }
653602d6ba1SMasatake YAMATO }
654602d6ba1SMasatake YAMATO
findProtobufTags(void)655602d6ba1SMasatake YAMATO static void findProtobufTags (void)
656602d6ba1SMasatake YAMATO {
657602d6ba1SMasatake YAMATO cppInit (false, false, false, false,
658d00bddf9SMasatake YAMATO KIND_GHOST_INDEX, 0, 0,
659d00bddf9SMasatake YAMATO KIND_GHOST_INDEX,
660602d6ba1SMasatake YAMATO KIND_GHOST_INDEX, 0, 0,
661602d6ba1SMasatake YAMATO FIELD_UNKNOWN);
662602d6ba1SMasatake YAMATO token.value = vStringNew ();
663602d6ba1SMasatake YAMATO
6642cc84b9fSChris Wendt syntax = SYNTAX_UNKNOWN;
6652cc84b9fSChris Wendt
666602d6ba1SMasatake YAMATO nextToken ();
667602d6ba1SMasatake YAMATO findProtobufTags0 (false, CORK_NIL);
6686ea83ed2SMasatake YAMATO
6696ea83ed2SMasatake YAMATO vStringDelete (token.value);
6706ea83ed2SMasatake YAMATO cppTerminate ();
6716ea83ed2SMasatake YAMATO }
6726ea83ed2SMasatake YAMATO
initialize(const langType language)6736ea83ed2SMasatake YAMATO static void initialize (const langType language)
6746ea83ed2SMasatake YAMATO {
6756ea83ed2SMasatake YAMATO Lang_protobuf = language;
6766ea83ed2SMasatake YAMATO }
6776ea83ed2SMasatake YAMATO
ProtobufParser(void)6786ea83ed2SMasatake YAMATO extern parserDefinition* ProtobufParser (void)
6796ea83ed2SMasatake YAMATO {
6806ea83ed2SMasatake YAMATO static const char *const extensions [] = { "proto", NULL };
6816ea83ed2SMasatake YAMATO parserDefinition* def = parserNew ("Protobuf");
6826ea83ed2SMasatake YAMATO
6836ea83ed2SMasatake YAMATO def->extensions = extensions;
68409ae690fSMasatake YAMATO def->kindTable = ProtobufKinds;
6856ea83ed2SMasatake YAMATO def->initialize = initialize;
6866ea83ed2SMasatake YAMATO def->kindCount = ARRAY_SIZE (ProtobufKinds);
6876ea83ed2SMasatake YAMATO def->parser = findProtobufTags;
6886ea83ed2SMasatake YAMATO def->keywordTable = ProtobufKeywordTable;
6896ea83ed2SMasatake YAMATO def->keywordCount = ARRAY_SIZE (ProtobufKeywordTable);
6906ea83ed2SMasatake YAMATO
691e484fe2eSMasatake YAMATO /* cpreprocessor wants corkQueue. */
6926b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
693e484fe2eSMasatake YAMATO
6946ea83ed2SMasatake YAMATO return def;
6956ea83ed2SMasatake YAMATO }
696