13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2014, Colomban Wendling <colomban@geany.org>
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO */
73ae02089SMasatake YAMATO /*
83ae02089SMasatake YAMATO * This module contains functions for generating tags for JSON files.
93ae02089SMasatake YAMATO *
103ae02089SMasatake YAMATO * http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
113ae02089SMasatake YAMATO *
123ae02089SMasatake YAMATO * This implementation is forgiving and allows many constructs that are not
133ae02089SMasatake YAMATO * actually valid but that don't conflict with the format. This is intend to
143ae02089SMasatake YAMATO * better support partly broken or unfinished files.
153ae02089SMasatake YAMATO */
163ae02089SMasatake YAMATO
173ae02089SMasatake YAMATO #include "general.h"
183ae02089SMasatake YAMATO
193ae02089SMasatake YAMATO #include <string.h>
203ae02089SMasatake YAMATO #include "debug.h"
213ae02089SMasatake YAMATO #include "entry.h"
223ae02089SMasatake YAMATO #include "keyword.h"
23844ef580SMasatake YAMATO #include "options.h"
243ae02089SMasatake YAMATO #include "parse.h"
253ae02089SMasatake YAMATO #include "read.h"
263ae02089SMasatake YAMATO #include "routines.h"
273ae02089SMasatake YAMATO #include "vstring.h"
283ae02089SMasatake YAMATO
292b28d0e0SJiří Techet #define isIdentChar(c) \
302b28d0e0SJiří Techet (isalnum (c) || (c) == '+' || (c) == '-' || (c) == '.')
312b28d0e0SJiří Techet
323ae02089SMasatake YAMATO typedef enum {
333ae02089SMasatake YAMATO TOKEN_EOF,
343ae02089SMasatake YAMATO TOKEN_UNDEFINED,
353ae02089SMasatake YAMATO TOKEN_OPEN_SQUARE,
363ae02089SMasatake YAMATO TOKEN_CLOSE_SQUARE,
373ae02089SMasatake YAMATO TOKEN_OPEN_CURLY,
383ae02089SMasatake YAMATO TOKEN_CLOSE_CURLY,
393ae02089SMasatake YAMATO TOKEN_COLON,
403ae02089SMasatake YAMATO TOKEN_COMMA,
413ae02089SMasatake YAMATO TOKEN_TRUE,
423ae02089SMasatake YAMATO TOKEN_FALSE,
433ae02089SMasatake YAMATO TOKEN_NULL,
443ae02089SMasatake YAMATO TOKEN_NUMBER,
453ae02089SMasatake YAMATO TOKEN_STRING
463ae02089SMasatake YAMATO } tokenType;
473ae02089SMasatake YAMATO
483ae02089SMasatake YAMATO typedef enum {
493ae02089SMasatake YAMATO TAG_NONE = -1,
503ae02089SMasatake YAMATO TAG_OBJECT,
513ae02089SMasatake YAMATO TAG_ARRAY,
523ae02089SMasatake YAMATO TAG_NUMBER,
533ae02089SMasatake YAMATO TAG_STRING,
543ae02089SMasatake YAMATO TAG_BOOLEAN,
553ae02089SMasatake YAMATO TAG_NULL,
563ae02089SMasatake YAMATO TAG_COUNT
573ae02089SMasatake YAMATO } jsonKind;
583ae02089SMasatake YAMATO
593ae02089SMasatake YAMATO typedef struct {
603ae02089SMasatake YAMATO tokenType type;
613ae02089SMasatake YAMATO jsonKind scopeKind;
623ae02089SMasatake YAMATO vString *string;
633ae02089SMasatake YAMATO vString *scope;
643ae02089SMasatake YAMATO unsigned long lineNumber;
65509a47dbSJiří Techet MIOPos filePosition;
663ae02089SMasatake YAMATO } tokenInfo;
673ae02089SMasatake YAMATO
683ae02089SMasatake YAMATO typedef enum {
693ae02089SMasatake YAMATO KEYWORD_true,
703ae02089SMasatake YAMATO KEYWORD_false,
713ae02089SMasatake YAMATO KEYWORD_null
723ae02089SMasatake YAMATO } keywordId;
733ae02089SMasatake YAMATO
743ae02089SMasatake YAMATO static langType Lang_json;
753ae02089SMasatake YAMATO
76e112e8abSMasatake YAMATO static kindDefinition JsonKinds [] = {
77ce990805SThomas Braun { true, 'o', "object", "objects" },
78ce990805SThomas Braun { true, 'a', "array", "arrays" },
79ce990805SThomas Braun { true, 'n', "number", "numbers" },
80ce990805SThomas Braun { true, 's', "string", "strings" },
8143630fd5SMasatake YAMATO { true, 'b', "boolean", "booleans" },
82ce990805SThomas Braun { true, 'z', "null", "nulls" }
833ae02089SMasatake YAMATO };
843ae02089SMasatake YAMATO
8582c11d8cSRich Siegel static const keywordTable JsonKeywordTable [] = {
86c379c5d2SMasatake YAMATO {"true", KEYWORD_true },
87c379c5d2SMasatake YAMATO {"false", KEYWORD_false},
88c379c5d2SMasatake YAMATO {"null", KEYWORD_null },
89c379c5d2SMasatake YAMATO };
90c379c5d2SMasatake YAMATO
newToken(void)913ae02089SMasatake YAMATO static tokenInfo *newToken (void)
923ae02089SMasatake YAMATO {
933ae02089SMasatake YAMATO tokenInfo *const token = xMalloc (1, tokenInfo);
943ae02089SMasatake YAMATO
953ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
963ae02089SMasatake YAMATO token->scopeKind = TAG_NONE;
973ae02089SMasatake YAMATO token->string = vStringNew ();
983ae02089SMasatake YAMATO token->scope = vStringNew ();
99a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
1003ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
1013ae02089SMasatake YAMATO
1023ae02089SMasatake YAMATO return token;
1033ae02089SMasatake YAMATO }
1043ae02089SMasatake YAMATO
deleteToken(tokenInfo * const token)1053ae02089SMasatake YAMATO static void deleteToken (tokenInfo *const token)
1063ae02089SMasatake YAMATO {
1073ae02089SMasatake YAMATO vStringDelete (token->string);
1083ae02089SMasatake YAMATO vStringDelete (token->scope);
1093ae02089SMasatake YAMATO eFree (token);
1103ae02089SMasatake YAMATO }
1113ae02089SMasatake YAMATO
copyToken(tokenInfo * const dest,tokenInfo * const src)1123ae02089SMasatake YAMATO static void copyToken (tokenInfo *const dest, tokenInfo *const src)
1133ae02089SMasatake YAMATO {
1143ae02089SMasatake YAMATO dest->type = src->type;
1153ae02089SMasatake YAMATO dest->scopeKind = src->scopeKind;
1163ae02089SMasatake YAMATO vStringCopy (dest->string, src->string);
1173ae02089SMasatake YAMATO vStringCopy (dest->scope, src->scope);
1183ae02089SMasatake YAMATO dest->lineNumber = src->lineNumber;
1193ae02089SMasatake YAMATO dest->filePosition = src->filePosition;
1203ae02089SMasatake YAMATO }
1213ae02089SMasatake YAMATO
makeJsonTag(tokenInfo * const token,const jsonKind kind)1223ae02089SMasatake YAMATO static void makeJsonTag (tokenInfo *const token, const jsonKind kind)
1233ae02089SMasatake YAMATO {
1243ae02089SMasatake YAMATO tagEntryInfo e;
1253ae02089SMasatake YAMATO
1263ae02089SMasatake YAMATO if (! JsonKinds[kind].enabled)
1273ae02089SMasatake YAMATO return;
1283ae02089SMasatake YAMATO
12916a2541cSMasatake YAMATO initTagEntry (&e, vStringValue (token->string), kind);
1303ae02089SMasatake YAMATO
1313ae02089SMasatake YAMATO e.lineNumber = token->lineNumber;
1323ae02089SMasatake YAMATO e.filePosition = token->filePosition;
1333ae02089SMasatake YAMATO
1343ae02089SMasatake YAMATO if (vStringLength (token->scope) > 0)
1353ae02089SMasatake YAMATO {
1363ae02089SMasatake YAMATO Assert (token->scopeKind > TAG_NONE && token->scopeKind < TAG_COUNT);
1373ae02089SMasatake YAMATO
138f92e6bf2SMasatake YAMATO e.extensionFields.scopeKindIndex = token->scopeKind;
139015ab54cSMasatake YAMATO e.extensionFields.scopeName = vStringValue (token->scope);
1403ae02089SMasatake YAMATO }
1413ae02089SMasatake YAMATO
1423ae02089SMasatake YAMATO makeTagEntry (&e);
1433ae02089SMasatake YAMATO }
1443ae02089SMasatake YAMATO
145844ef580SMasatake YAMATO #define DEPTH_LIMIT 512
146844ef580SMasatake YAMATO static int depth_counter;
147844ef580SMasatake YAMATO
readTokenFull(tokenInfo * const token,bool includeStringRepr)1483ae02089SMasatake YAMATO static void readTokenFull (tokenInfo *const token,
149ce990805SThomas Braun bool includeStringRepr)
1503ae02089SMasatake YAMATO {
1513ae02089SMasatake YAMATO int c;
1523ae02089SMasatake YAMATO
153844ef580SMasatake YAMATO if (depth_counter > DEPTH_LIMIT)
154844ef580SMasatake YAMATO {
155844ef580SMasatake YAMATO token->type = TOKEN_EOF;
156844ef580SMasatake YAMATO
157844ef580SMasatake YAMATO /* Not to repeat warnings. */
158844ef580SMasatake YAMATO if (depth_counter == (DEPTH_LIMIT + 1))
159844ef580SMasatake YAMATO {
160844ef580SMasatake YAMATO notice ("Terminate parsing: too deep brackets recursion in %s at %ld",
161844ef580SMasatake YAMATO getInputFileName(), getInputLineNumber());
162844ef580SMasatake YAMATO depth_counter++;
163844ef580SMasatake YAMATO }
164844ef580SMasatake YAMATO return;
165844ef580SMasatake YAMATO }
166844ef580SMasatake YAMATO
1673ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
1683ae02089SMasatake YAMATO vStringClear (token->string);
1693ae02089SMasatake YAMATO
1703ae02089SMasatake YAMATO do
171018bce0bSMasatake YAMATO c = getcFromInputFile ();
1723ae02089SMasatake YAMATO while (c == '\t' || c == ' ' || c == '\r' || c == '\n');
1733ae02089SMasatake YAMATO
174a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
1753ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
1763ae02089SMasatake YAMATO
1773ae02089SMasatake YAMATO switch (c)
1783ae02089SMasatake YAMATO {
1793ae02089SMasatake YAMATO case EOF: token->type = TOKEN_EOF; break;
180844ef580SMasatake YAMATO case '[':
181*2ec6b03eSMasatake YAMATO depth_counter++;
182844ef580SMasatake YAMATO token->type = TOKEN_OPEN_SQUARE; break;
183844ef580SMasatake YAMATO case ']':
184*2ec6b03eSMasatake YAMATO depth_counter--;
185844ef580SMasatake YAMATO token->type = TOKEN_CLOSE_SQUARE; break;
186844ef580SMasatake YAMATO case '{':
187*2ec6b03eSMasatake YAMATO depth_counter++;
188844ef580SMasatake YAMATO token->type = TOKEN_OPEN_CURLY; break;
189844ef580SMasatake YAMATO case '}':
190*2ec6b03eSMasatake YAMATO depth_counter--;
191844ef580SMasatake YAMATO token->type = TOKEN_CLOSE_CURLY; break;
1923ae02089SMasatake YAMATO case ':': token->type = TOKEN_COLON; break;
1933ae02089SMasatake YAMATO case ',': token->type = TOKEN_COMMA; break;
1943ae02089SMasatake YAMATO
1953ae02089SMasatake YAMATO case '"':
1963ae02089SMasatake YAMATO {
197ce990805SThomas Braun bool escaped = false;
1983ae02089SMasatake YAMATO token->type = TOKEN_STRING;
199ce990805SThomas Braun while (true)
2003ae02089SMasatake YAMATO {
201018bce0bSMasatake YAMATO c = getcFromInputFile ();
2023ae02089SMasatake YAMATO /* we don't handle unicode escapes but they are safe */
2033ae02089SMasatake YAMATO if (escaped)
204ce990805SThomas Braun escaped = false;
2053ae02089SMasatake YAMATO else if (c == '\\')
206ce990805SThomas Braun escaped = true;
2073ae02089SMasatake YAMATO else if (c >= 0x00 && c <= 0x1F)
2083ae02089SMasatake YAMATO break; /* break on invalid, unescaped, control characters */
2093ae02089SMasatake YAMATO else if (c == '"' || c == EOF)
2103ae02089SMasatake YAMATO break;
2113ae02089SMasatake YAMATO if (includeStringRepr)
2123ae02089SMasatake YAMATO vStringPut (token->string, c);
2133ae02089SMasatake YAMATO }
2143ae02089SMasatake YAMATO break;
2153ae02089SMasatake YAMATO }
2163ae02089SMasatake YAMATO
2173ae02089SMasatake YAMATO default:
2183ae02089SMasatake YAMATO if (! isIdentChar (c))
2193ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
2203ae02089SMasatake YAMATO else
2213ae02089SMasatake YAMATO {
2223ae02089SMasatake YAMATO do
2233ae02089SMasatake YAMATO {
2243ae02089SMasatake YAMATO vStringPut (token->string, c);
225018bce0bSMasatake YAMATO c = getcFromInputFile ();
2263ae02089SMasatake YAMATO }
2273ae02089SMasatake YAMATO while (c != EOF && isIdentChar (c));
22861f14fa5SMasatake YAMATO ungetcToInputFile (c);
2293ae02089SMasatake YAMATO switch (lookupKeyword (vStringValue (token->string), Lang_json))
2303ae02089SMasatake YAMATO {
2313ae02089SMasatake YAMATO case KEYWORD_true: token->type = TOKEN_TRUE; break;
2323ae02089SMasatake YAMATO case KEYWORD_false: token->type = TOKEN_FALSE; break;
2333ae02089SMasatake YAMATO case KEYWORD_null: token->type = TOKEN_NULL; break;
2343ae02089SMasatake YAMATO default: token->type = TOKEN_NUMBER; break;
2353ae02089SMasatake YAMATO }
2363ae02089SMasatake YAMATO }
2373ae02089SMasatake YAMATO break;
2383ae02089SMasatake YAMATO }
2393ae02089SMasatake YAMATO }
2403ae02089SMasatake YAMATO
241ce990805SThomas Braun #define readToken(t) (readTokenFull ((t), false))
2423ae02089SMasatake YAMATO
pushScope(tokenInfo * const token,const tokenInfo * const parent,const jsonKind parentKind)2433ae02089SMasatake YAMATO static void pushScope (tokenInfo *const token,
2443ae02089SMasatake YAMATO const tokenInfo *const parent,
2453ae02089SMasatake YAMATO const jsonKind parentKind)
2463ae02089SMasatake YAMATO {
2473ae02089SMasatake YAMATO if (vStringLength (token->scope) > 0)
2483ae02089SMasatake YAMATO vStringPut (token->scope, '.');
2493ae02089SMasatake YAMATO vStringCat (token->scope, parent->string);
2503ae02089SMasatake YAMATO token->scopeKind = parentKind;
2513ae02089SMasatake YAMATO }
2523ae02089SMasatake YAMATO
popScope(tokenInfo * const token,const tokenInfo * const parent)2533ae02089SMasatake YAMATO static void popScope (tokenInfo *const token,
2543ae02089SMasatake YAMATO const tokenInfo *const parent)
2553ae02089SMasatake YAMATO {
2567ae28a3dSColomban Wendling vStringTruncate (token->scope, vStringLength (parent->scope));
2573ae02089SMasatake YAMATO token->scopeKind = parent->scopeKind;
2583ae02089SMasatake YAMATO }
2593ae02089SMasatake YAMATO
2603ae02089SMasatake YAMATO #define skipToOneOf2(token, type1, type2) \
2613ae02089SMasatake YAMATO (skipToOneOf3 (token, type1, type2, TOKEN_EOF /* dummy */))
2623ae02089SMasatake YAMATO
2633ae02089SMasatake YAMATO #define skipTo(token, type) \
2643ae02089SMasatake YAMATO (skipToOneOf3 (token, type, /* dummies */ TOKEN_EOF, TOKEN_EOF))
2653ae02089SMasatake YAMATO
skipToOneOf3(tokenInfo * const token,const tokenType type1,const tokenType type2,const tokenType type3)2663ae02089SMasatake YAMATO static void skipToOneOf3 (tokenInfo *const token,
2673ae02089SMasatake YAMATO const tokenType type1,
2683ae02089SMasatake YAMATO const tokenType type2,
2693ae02089SMasatake YAMATO const tokenType type3)
2703ae02089SMasatake YAMATO {
2713ae02089SMasatake YAMATO while (token->type != TOKEN_EOF &&
2723ae02089SMasatake YAMATO token->type != type1 &&
2733ae02089SMasatake YAMATO token->type != type2 &&
2743ae02089SMasatake YAMATO token->type != type3)
2753ae02089SMasatake YAMATO {
2763ae02089SMasatake YAMATO readToken (token);
2773ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
2783ae02089SMasatake YAMATO {
2793ae02089SMasatake YAMATO skipTo (token, TOKEN_CLOSE_CURLY);
2803ae02089SMasatake YAMATO readToken (token);
2813ae02089SMasatake YAMATO }
2823ae02089SMasatake YAMATO else if (token->type == TOKEN_OPEN_SQUARE)
2833ae02089SMasatake YAMATO {
2843ae02089SMasatake YAMATO skipTo (token, TOKEN_CLOSE_SQUARE);
2853ae02089SMasatake YAMATO readToken (token);
2863ae02089SMasatake YAMATO }
2873ae02089SMasatake YAMATO }
2883ae02089SMasatake YAMATO }
2893ae02089SMasatake YAMATO
tokenToKind(const tokenType type)2903ae02089SMasatake YAMATO static jsonKind tokenToKind (const tokenType type)
2913ae02089SMasatake YAMATO {
2923ae02089SMasatake YAMATO switch (type)
2933ae02089SMasatake YAMATO {
2943ae02089SMasatake YAMATO case TOKEN_OPEN_CURLY: return TAG_OBJECT;
2953ae02089SMasatake YAMATO case TOKEN_OPEN_SQUARE: return TAG_ARRAY;
2963ae02089SMasatake YAMATO case TOKEN_STRING: return TAG_STRING;
2973ae02089SMasatake YAMATO case TOKEN_TRUE:
2983ae02089SMasatake YAMATO case TOKEN_FALSE: return TAG_BOOLEAN;
2993ae02089SMasatake YAMATO case TOKEN_NUMBER: return TAG_NUMBER;
3003ae02089SMasatake YAMATO default: return TAG_NULL;
3013ae02089SMasatake YAMATO }
3023ae02089SMasatake YAMATO }
3033ae02089SMasatake YAMATO
parseValue(tokenInfo * const token)3043ae02089SMasatake YAMATO static void parseValue (tokenInfo *const token)
3053ae02089SMasatake YAMATO {
3063ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
3073ae02089SMasatake YAMATO {
3083ae02089SMasatake YAMATO tokenInfo *name = newToken ();
3093ae02089SMasatake YAMATO
3103ae02089SMasatake YAMATO do
3113ae02089SMasatake YAMATO {
312ce990805SThomas Braun readTokenFull (token, true);
3133ae02089SMasatake YAMATO if (token->type == TOKEN_STRING)
3143ae02089SMasatake YAMATO {
3153ae02089SMasatake YAMATO jsonKind tagKind = TAG_NULL; /* default in case of invalid value */
3163ae02089SMasatake YAMATO
3173ae02089SMasatake YAMATO copyToken (name, token);
3183ae02089SMasatake YAMATO
3193ae02089SMasatake YAMATO /* skip any possible garbage before the value */
3203ae02089SMasatake YAMATO skipToOneOf3 (token, TOKEN_CLOSE_CURLY, TOKEN_COLON, TOKEN_COMMA);
3213ae02089SMasatake YAMATO
3223ae02089SMasatake YAMATO if (token->type == TOKEN_COLON)
3233ae02089SMasatake YAMATO {
3243ae02089SMasatake YAMATO readToken (token);
3253ae02089SMasatake YAMATO tagKind = tokenToKind (token->type);
3263ae02089SMasatake YAMATO
3273ae02089SMasatake YAMATO pushScope (token, name, tagKind);
3283ae02089SMasatake YAMATO parseValue (token);
3293ae02089SMasatake YAMATO popScope (token, name);
3303ae02089SMasatake YAMATO }
3313ae02089SMasatake YAMATO
3323ae02089SMasatake YAMATO makeJsonTag (name, tagKind);
3333ae02089SMasatake YAMATO }
3343ae02089SMasatake YAMATO /* skip to the end of the construct */
3353ae02089SMasatake YAMATO skipToOneOf2 (token, TOKEN_CLOSE_CURLY, TOKEN_COMMA);
3363ae02089SMasatake YAMATO }
3373ae02089SMasatake YAMATO while (token->type != TOKEN_EOF &&
3383ae02089SMasatake YAMATO token->type != TOKEN_CLOSE_CURLY);
3393ae02089SMasatake YAMATO
3403ae02089SMasatake YAMATO if (token->type == TOKEN_CLOSE_CURLY)
3413ae02089SMasatake YAMATO readToken (token);
3423ae02089SMasatake YAMATO
3433ae02089SMasatake YAMATO deleteToken (name);
3443ae02089SMasatake YAMATO }
3453ae02089SMasatake YAMATO else if (token->type == TOKEN_OPEN_SQUARE)
3463ae02089SMasatake YAMATO {
3473ae02089SMasatake YAMATO tokenInfo *name = newToken ();
3483ae02089SMasatake YAMATO char buf[32];
3493ae02089SMasatake YAMATO unsigned int nth = 0;
3503ae02089SMasatake YAMATO
3513ae02089SMasatake YAMATO readToken (token);
3523ae02089SMasatake YAMATO while (token->type != TOKEN_EOF &&
3533ae02089SMasatake YAMATO token->type != TOKEN_CLOSE_SQUARE)
3543ae02089SMasatake YAMATO {
3553ae02089SMasatake YAMATO jsonKind tagKind;
3563ae02089SMasatake YAMATO
3573ae02089SMasatake YAMATO tagKind = tokenToKind (token->type);
3583ae02089SMasatake YAMATO
3593ae02089SMasatake YAMATO copyToken (name, token);
3603ae02089SMasatake YAMATO snprintf (buf, sizeof buf, "%u", nth++);
3613ae02089SMasatake YAMATO vStringCopyS (name->string, buf);
3623ae02089SMasatake YAMATO
3633ae02089SMasatake YAMATO makeJsonTag (name, tagKind);
3643ae02089SMasatake YAMATO pushScope (token, name, tagKind);
3653ae02089SMasatake YAMATO parseValue (token);
3663ae02089SMasatake YAMATO popScope (token, name);
3673ae02089SMasatake YAMATO
3683ae02089SMasatake YAMATO /* skip to the end of the construct */
3693ae02089SMasatake YAMATO skipToOneOf2 (token, TOKEN_CLOSE_SQUARE, TOKEN_COMMA);
3703ae02089SMasatake YAMATO if (token->type != TOKEN_CLOSE_SQUARE)
3713ae02089SMasatake YAMATO readToken (token);
3723ae02089SMasatake YAMATO }
3733ae02089SMasatake YAMATO
3743ae02089SMasatake YAMATO if (token->type == TOKEN_CLOSE_SQUARE)
3753ae02089SMasatake YAMATO readToken (token);
3763ae02089SMasatake YAMATO
3773ae02089SMasatake YAMATO deleteToken (name);
3783ae02089SMasatake YAMATO }
3793ae02089SMasatake YAMATO }
3803ae02089SMasatake YAMATO
findJsonTags(void)3813ae02089SMasatake YAMATO static void findJsonTags (void)
3823ae02089SMasatake YAMATO {
3833ae02089SMasatake YAMATO tokenInfo *const token = newToken ();
3843ae02089SMasatake YAMATO
385*2ec6b03eSMasatake YAMATO depth_counter = 0;
386844ef580SMasatake YAMATO
3873ae02089SMasatake YAMATO /* We allow multiple top-level elements, although it's not actually valid
3883ae02089SMasatake YAMATO * JSON. An interesting side effect of this is that we allow a leading
3893ae02089SMasatake YAMATO * Unicode BOM mark -- even though ok, many JSON parsers will choke on it */
3903ae02089SMasatake YAMATO do
3913ae02089SMasatake YAMATO {
3923ae02089SMasatake YAMATO readToken (token);
3933ae02089SMasatake YAMATO parseValue (token);
3943ae02089SMasatake YAMATO }
3953ae02089SMasatake YAMATO while (token->type != TOKEN_EOF);
3963ae02089SMasatake YAMATO
3973ae02089SMasatake YAMATO deleteToken (token);
3983ae02089SMasatake YAMATO }
3993ae02089SMasatake YAMATO
initialize(const langType language)4003ae02089SMasatake YAMATO static void initialize (const langType language)
4013ae02089SMasatake YAMATO {
4023ae02089SMasatake YAMATO Lang_json = language;
4033ae02089SMasatake YAMATO }
4043ae02089SMasatake YAMATO
405137eb990SK.Takata /* Create parser definition structure */
JsonParser(void)4063ae02089SMasatake YAMATO extern parserDefinition* JsonParser (void)
4073ae02089SMasatake YAMATO {
4083ae02089SMasatake YAMATO static const char *const extensions [] = { "json", NULL };
4093ae02089SMasatake YAMATO parserDefinition *const def = parserNew ("JSON");
4103ae02089SMasatake YAMATO def->extensions = extensions;
41109ae690fSMasatake YAMATO def->kindTable = JsonKinds;
4123db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (JsonKinds);
4133ae02089SMasatake YAMATO def->parser = findJsonTags;
4143ae02089SMasatake YAMATO def->initialize = initialize;
415c379c5d2SMasatake YAMATO def->keywordTable = JsonKeywordTable;
4163db72c21SMasatake YAMATO def->keywordCount = ARRAY_SIZE (JsonKeywordTable);
417ce990805SThomas Braun def->allowNullTag = true;
4183ae02089SMasatake YAMATO
4193ae02089SMasatake YAMATO return def;
4203ae02089SMasatake YAMATO }
421