Update all parsers and related files to ctags p6.1.20240421.0
[geany-mirror.git] / ctags / parsers / typescript.c
blob0e04b1b695d0ce1292c74ed8ec7d9bee0b294535
1 /*
2 * Copyright (c) 2019, Karol Samborski
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for generating tags for TypeScript language
8 * files.
10 * Reference: https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf
15 * INCLUDE FILES
17 #include "general.h" /* must always come first */
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
23 #include "parse.h"
24 #include "objpool.h"
25 #include "keyword.h"
26 #include "read.h"
27 #include "numarray.h"
28 #include "routines.h"
29 #include "entry.h"
30 #include "inline.h"
31 #include "unwindi.h"
33 #define isType(token,t) (bool) ((token)->type == (t))
34 #define isKeyword(token,k) (bool) ((token)->keyword == (k))
35 #define newToken() (objPoolGet (TokenPool))
36 #define deleteToken(t) (objPoolPut (TokenPool, (t)))
37 #define isIdentChar(c) \
38 (isalpha (c) || isdigit (c) || (c) == '$' || \
39 (c) == '@' || (c) == '_' || (c) == '#' || \
40 (c) >= 0x80)
42 #define PARSER_DEF(fname, pfun, word, stateField) \
43 CTAGS_INLINE void parse ## fname (const int c, tokenInfo * const token, parserState *state, parserResult * const result) \
44 { \
45 pfun (c, token, word, &state->stateField, result); \
48 #define SINGLE_CHAR_PARSER_DEF(fname, ch, ttype) \
49 CTAGS_INLINE void parse ## fname (const int c, tokenInfo * const token, parserState *state, parserResult * const result) \
50 { \
51 parseOneChar (c, token, ch, ttype, result); \
54 #define MULTI_CHAR_PARSER_DEF(fname, chs, ...) \
55 CTAGS_INLINE void parse ## fname (const int c, tokenInfo * const token, parserState *state, parserResult * const result) \
56 { \
57 tokenType types[] = { __VA_ARGS__ }; \
58 parseChar (c, token, state, result, chs, types); \
61 #define WORD_TOKEN_PARSER_DEF(fname, w, ttype) \
62 CTAGS_INLINE void parse ## fname (const int c, tokenInfo * const token, parserState *state, parserResult * const result) \
63 { \
64 parseWordToken (c, token, w, ttype, &state->num, result); \
67 #define BLOCK_PARSER_DEF(fname, start, end, ttype) \
68 CTAGS_INLINE void parse ## fname (const int c, tokenInfo * const token, parserState *state, parserResult * const result) \
69 { \
70 parseBlock (c, token, ttype, start, end, &state->block, result); \
74 * DATA DEFINITIONS
76 static langType Lang_ts;
77 static objPool *TokenPool = NULL;
79 /* Used to specify type of keyword.
81 enum eKeywordId {
82 KEYWORD_as,
83 KEYWORD_async,
84 KEYWORD_await,
85 KEYWORD_class,
86 KEYWORD_constructor,
87 KEYWORD_const,
88 KEYWORD_enum,
89 KEYWORD_extends,
90 KEYWORD_for,
91 KEYWORD_function,
92 KEYWORD_instanceof,
93 KEYWORD_in,
94 KEYWORD_interface,
95 KEYWORD_implements,
96 KEYWORD_let,
97 KEYWORD_namespace,
98 KEYWORD_new,
99 KEYWORD_of,
100 KEYWORD_private,
101 KEYWORD_protected,
102 KEYWORD_public,
103 KEYWORD_return,
104 KEYWORD_readonly,
105 KEYWORD_static,
106 KEYWORD_this,
107 KEYWORD_type,
108 KEYWORD_typeof,
109 KEYWORD_var,
110 KEYWORD_while
112 typedef int keywordId; /* to allow KEYWORD_NONE */
114 typedef enum eTokenType {
115 TOKEN_UNDEFINED,
116 TOKEN_EOF,
117 TOKEN_CHARACTER,
118 TOKEN_SEMICOLON,
119 TOKEN_COLON,
120 TOKEN_QUESTION_MARK,
121 TOKEN_COMMA,
122 TOKEN_KEYWORD,
123 TOKEN_IDENTIFIER,
124 TOKEN_STRING,
125 TOKEN_TEMPLATE,
126 TOKEN_PERIOD,
127 TOKEN_OPEN_CURLY,
128 TOKEN_CLOSE_CURLY,
129 TOKEN_OPEN_PAREN,
130 TOKEN_CLOSE_PAREN,
131 TOKEN_OPEN_SQUARE,
132 TOKEN_CLOSE_SQUARE,
133 TOKEN_EQUAL_SIGN,
134 TOKEN_STAR,
135 TOKEN_NL,
136 TOKEN_COMMENT_BLOCK,
137 TOKEN_PARENS,
138 TOKEN_SQUARES,
139 TOKEN_CURLIES,
140 TOKEN_PIPE,
141 TOKEN_AMPERSAND,
142 TOKEN_ARROW,
143 TOKEN_NUMBER,
144 TOKEN_AT,
145 TOKEN_MINUS,
146 TOKEN_PLUS,
147 TOKEN_DIV,
148 TOKEN_POWER,
149 TOKEN_GREATER,
150 TOKEN_LOWER
151 } tokenType;
153 typedef enum {
154 TSTAG_FUNCTION,
155 TSTAG_CLASS,
156 TSTAG_INTERFACE,
157 TSTAG_ENUM,
158 TSTAG_ENUMERATOR,
159 TSTAG_METHOD,
160 TSTAG_NAMESPACE,
161 TSTAG_PARAMETER,
162 TSTAG_PROPERTY,
163 TSTAG_VARIABLE,
164 TSTAG_LOCAL,
165 TSTAG_CONSTANT,
166 TSTAG_GENERATOR,
167 TSTAG_ALIAS
168 } tsKind;
170 typedef struct sTokenInfo {
171 tokenType type;
172 keywordId keyword;
173 vString *string;
174 int scope;
175 unsigned long lineNumber;
176 MIOPos filePosition;
177 keywordId accessKeyword;
178 } tokenInfo;
180 typedef struct sCommentState {
181 int parsed;
182 int blockParsed;
183 bool isBlock;
184 } commentState;
186 typedef struct sBlockState {
187 int parsed;
188 int nestLevel;
189 int curlyLevel;
190 } blockState;
192 static const keywordTable TsKeywordTable [] = {
193 /* keyword keyword ID */
194 { "as" , KEYWORD_as },
195 { "async" , KEYWORD_async },
196 { "await" , KEYWORD_await },
197 { "class" , KEYWORD_class },
198 { "const" , KEYWORD_const },
199 { "constructor" , KEYWORD_constructor },
200 { "enum" , KEYWORD_enum },
201 { "extends" , KEYWORD_extends },
202 { "for" , KEYWORD_for },
203 { "function" , KEYWORD_function },
204 { "in" , KEYWORD_in },
205 { "interface" , KEYWORD_interface },
206 { "implements" , KEYWORD_implements },
207 { "let" , KEYWORD_let },
208 { "namespace" , KEYWORD_namespace },
209 { "new" , KEYWORD_new },
210 { "of" , KEYWORD_of },
211 { "private" , KEYWORD_private },
212 { "protected" , KEYWORD_protected },
213 { "public" , KEYWORD_public },
214 { "static" , KEYWORD_static },
215 { "this" , KEYWORD_this },
216 { "type" , KEYWORD_type },
217 { "typeof" , KEYWORD_typeof },
218 { "var" , KEYWORD_var },
219 { "while" , KEYWORD_while }
222 static kindDefinition TsKinds [] = {
223 { true, 'f', "function", "functions" },
224 { true, 'c', "class", "classes" },
225 { true, 'i', "interface", "interfaces" },
226 { true, 'g', "enum", "enums" },
227 { true, 'e', "enumerator", "enumerators (values inside an enumeration)" },
228 { true, 'm', "method", "methods" },
229 { true, 'n', "namespace", "namespaces" },
230 { false, 'z', "parameter", "function parameters inside function definitions" },
231 { true, 'p', "property", "properties" },
232 { true, 'v', "variable", "variables" },
233 { false, 'l', "local", "local variables" },
234 { true, 'C', "constant", "constants" },
235 { true, 'G', "generator", "generators" },
236 { true, 'a', "alias", "aliases", }
239 typedef enum eParserResult {
240 PARSER_FINISHED,
241 PARSER_NEEDS_MORE_INPUT,
242 PARSER_FAILED
243 } parserResultStatus;
245 typedef struct sParserResult {
246 parserResultStatus status;
247 unsigned int unusedChars;
248 } parserResult;
250 typedef union uParserState {
251 int num;
252 blockState block;
253 commentState comment;
254 char ch;
255 } parserState;
257 static struct sUwiStats tsUwiStats;
259 typedef void (*Parser)(const int c, tokenInfo *const, parserState *state, parserResult *const);
261 static bool tryParser(Parser parser, tokenInfo *const token, bool skipWhite);
262 CTAGS_INLINE void parseStringRegex(const int c, tokenInfo * const token, parserState *state, parserResult * const result);
263 CTAGS_INLINE void parseStringSQuote(const int c, tokenInfo * const token, parserState *state, parserResult * const result);
264 CTAGS_INLINE void parseStringDQuote(const int c, tokenInfo * const token, parserState *state, parserResult * const result);
265 CTAGS_INLINE void parseStringTemplate(const int c, tokenInfo * const token, parserState *state, parserResult * const result);
267 static int emitTag(const tokenInfo *const token, const tsKind kind)
269 if (! TsKinds [kind].enabled) return CORK_NIL;
271 static const char *const access [3] = {
272 "private",
273 "protected",
274 "public"
277 const char *name = vStringValue (token->string);
278 tagEntryInfo e;
280 initTagEntry (&e, name, kind);
281 updateTagLine (&e, token->lineNumber, token->filePosition);
282 e.extensionFields.scopeIndex = token->scope;
284 switch (token->accessKeyword)
286 case KEYWORD_public:
287 e.extensionFields.access = access [2];
288 break;
289 case KEYWORD_protected:
290 e.extensionFields.access = access [1];
291 break;
292 case KEYWORD_private:
293 e.extensionFields.access = access [0];
294 break;
297 return makeTagEntry (&e);
300 static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
302 tokenInfo *token = xMalloc (1, tokenInfo);
303 token->scope = CORK_NIL;
304 token->string = NULL;
306 return token;
309 static void clearPoolToken (void *data)
311 tokenInfo *token = data;
313 token->type = TOKEN_UNDEFINED;
314 token->keyword = KEYWORD_NONE;
315 token->lineNumber = uwiGetLineNumber ();
316 token->filePosition = uwiGetFilePosition ();
318 token->scope = CORK_NIL;
320 token->accessKeyword = KEYWORD_NONE;
322 token->string = vStringNewOrClear (token->string);
325 static void deletePoolToken (void *data)
327 tokenInfo *token = data;
328 vStringDelete (token->string); /* NULL is acceptable */
329 eFree (token);
332 static void copyToken (tokenInfo *const dest, const tokenInfo *const src,
333 bool scope)
335 dest->lineNumber = src->lineNumber;
336 dest->filePosition = src->filePosition;
337 dest->type = src->type;
338 dest->keyword = src->keyword;
339 vStringCopy (dest->string, src->string);
340 if (scope) dest->scope = src->scope;
343 static void initToken (tokenInfo *const token, tokenType type)
345 token->type = type;
346 token->keyword = KEYWORD_NONE;
347 token->lineNumber = uwiGetLineNumber ();
348 token->filePosition = uwiGetFilePosition ();
351 CTAGS_INLINE bool whiteChar(const int c)
353 return c == ' ' || c == '\r' || c == '\t';
356 CTAGS_INLINE void parseWhiteChars(const int c, tokenInfo *const token, parserState *state, parserResult * const result)
358 if (whiteChar (c))
360 result->status = PARSER_NEEDS_MORE_INPUT;
361 state->num += 1;
362 return;
365 if (state->num == 0)
367 result->status = PARSER_FAILED;
368 return;
371 result->status = PARSER_FINISHED;
372 result->unusedChars = 1;
375 CTAGS_INLINE void parseOneChar(const int c, tokenInfo *const token, const char expected, const tokenType type, parserResult *const result)
377 if (c != expected)
379 result->status = PARSER_FAILED;
380 return;
383 initToken (token, type);
384 result->status = PARSER_FINISHED;
387 CTAGS_INLINE void parseChar(const int c, tokenInfo *const token, void *state, parserResult *const result, const char *chars, const tokenType *types)
389 const char *pos = strchr (chars, c);
391 if (pos)
393 result->status = PARSER_FINISHED;
394 initToken (token, types[pos - chars]);
395 return;
398 result->status = PARSER_FAILED;
401 CTAGS_INLINE void parseWord(const int c, tokenInfo *const token, const char *word, int *parsed, parserResult *const result)
403 if (word [*parsed] == '\0')
405 if (isIdentChar (c))
407 result->status = PARSER_FAILED;
408 return;
411 vStringCatS (token->string, word);
412 initToken (token, TOKEN_KEYWORD);
413 token->keyword = lookupKeyword (vStringValue (token->string), Lang_ts);
415 result->unusedChars = 1;
416 result->status = PARSER_FINISHED;
417 return;
420 if (c == word [*parsed])
422 *parsed += 1;
424 result->status = PARSER_NEEDS_MORE_INPUT;
425 return;
428 result->status = PARSER_FAILED;
431 CTAGS_INLINE void parseNumber(const int c, tokenInfo *const token, int *parsed, parserResult *const result)
433 if (*parsed == 0)
435 if (c == '-')
437 result->status = PARSER_NEEDS_MORE_INPUT;
438 *parsed += 1;
439 return;
443 if (isdigit (c))
445 result->status = PARSER_NEEDS_MORE_INPUT;
446 *parsed += 1;
447 return;
449 else if (*parsed == 0)
451 result->status = PARSER_FAILED;
452 return;
455 initToken (token, TOKEN_NUMBER);
457 result->unusedChars = 1;
458 result->status = PARSER_FINISHED;
461 CTAGS_INLINE void parseWordToken(const int c, tokenInfo *const token, const char *word, const tokenType type, int *parsed, parserResult *const result)
463 if (c == word [*parsed])
465 *parsed += 1;
467 if (word [*parsed] == '\0')
469 initToken (token, type);
470 result->status = PARSER_FINISHED;
471 return;
474 result->status = PARSER_NEEDS_MORE_INPUT;
475 return;
478 result->status = PARSER_FAILED;
481 CTAGS_INLINE void parseComment(const int c, tokenInfo *const token, parserState *state, parserResult *const result)
483 if (state->comment.parsed < 2)
485 parseWordToken (c, token, "//", TOKEN_COMMENT_BLOCK, &state->comment.parsed, result);
487 if (result->status == PARSER_FAILED)
489 parseWordToken (c, token, "/*", TOKEN_COMMENT_BLOCK, &state->comment.parsed, result);
490 if (result->status == PARSER_FINISHED)
492 result->status = PARSER_NEEDS_MORE_INPUT;
493 state->comment.isBlock = true;
496 else if (result->status == PARSER_FINISHED)
498 result->status = PARSER_NEEDS_MORE_INPUT;
499 state->comment.isBlock = false;
502 return;
505 state->comment.parsed += 1;
507 if (c == EOF) result->status = PARSER_FINISHED;
508 else if (state->comment.isBlock)
510 parseWordToken (c, token, "*/", TOKEN_COMMENT_BLOCK, &state->comment.blockParsed, result);
512 if (result->status == PARSER_FAILED)
514 state->comment.blockParsed = c == '*' ? 1 : 0;
515 result->status = PARSER_NEEDS_MORE_INPUT;
518 else if (c == '\n')
520 result->status = PARSER_FINISHED;
521 result->unusedChars = 1;
524 if (result->status == PARSER_FINISHED)
526 initToken (token, TOKEN_COMMENT_BLOCK);
527 return;
530 result->status = PARSER_NEEDS_MORE_INPUT;
533 CTAGS_INLINE void parseString(const int c, tokenInfo *const token, const char quote, char *prev, parserResult *const result)
535 if (*prev == '\0')
537 if (c == quote)
539 *prev = c;
540 result->status = PARSER_NEEDS_MORE_INPUT;
542 else result->status = PARSER_FAILED;
544 return;
546 else if (c == EOF)
548 result->status = PARSER_FAILED;
550 return;
553 if (c == '\\' && *prev == '\\')
555 *prev = '\1';
556 result->status = PARSER_NEEDS_MORE_INPUT;
558 return;
560 else if (c == quote && *prev != '\\')
562 result->status = PARSER_FINISHED;
563 initToken (token, TOKEN_STRING);
565 return;
567 else if (quote == '/' && c == '\n') // regex cannot contain new lines
569 result->status = PARSER_FAILED;
571 return;
574 *prev = c;
575 result->status = PARSER_NEEDS_MORE_INPUT;
579 CTAGS_INLINE void parseBlock(const int c, tokenInfo *const token, tokenType const ttype, const char start, const char end, blockState *state, parserResult *const result)
581 if (state->parsed == 0)
583 if (c != start)
585 result->status = PARSER_FAILED;
586 return;
589 state->parsed = 1;
592 if (c == '{') state->curlyLevel += 1;
593 else if (c == '}') state->curlyLevel -= 1;
595 if (c == start) state->nestLevel += 1;
596 else if (c == end) state->nestLevel -= 1;
597 else if ((state->curlyLevel < 1 && c == ';') || c == EOF)
599 result->status = PARSER_FAILED;
600 return;
603 if (state->nestLevel <= 0)
605 initToken (token, ttype);
606 result->status = PARSER_FINISHED;
608 return;
611 //skip comments:
612 tryParser ((Parser) parseComment, token, false);
613 //skip strings:
614 tryParser ((Parser) parseStringRegex, token, false);
615 tryParser ((Parser) parseStringSQuote, token, false);
616 tryParser ((Parser) parseStringDQuote, token, false);
617 tryParser ((Parser) parseStringTemplate, token, false);
619 result->status = PARSER_NEEDS_MORE_INPUT;
623 CTAGS_INLINE void parseIdentifierCommon(const int c, tokenInfo *const token, int *parsed, parserResult *const result,
624 bool acceptFqName)
626 if (isIdentChar (c) || (acceptFqName && c == '.'))
628 vStringPut (token->string, c);
629 *parsed = *parsed + 1;
630 result->status = PARSER_NEEDS_MORE_INPUT;
632 return;
635 if (*parsed > 0)
637 initToken (token, TOKEN_IDENTIFIER);
638 result->status = PARSER_FINISHED;
639 result->unusedChars = 1;
640 return;
643 result->status = PARSER_FAILED;
646 CTAGS_INLINE void parseIdentifier(const int c, tokenInfo *const token, int *parsed, parserResult *const result)
648 parseIdentifierCommon (c, token, parsed, result, false);
651 CTAGS_INLINE void parseFQIdentifier(const int c, tokenInfo *const token, int *parsed, parserResult *const result)
653 parseIdentifierCommon (c, token, parsed, result, true);
656 PARSER_DEF (AsKeyword, parseWord, "as", num)
657 PARSER_DEF (AsyncKeyword, parseWord, "async", num)
658 PARSER_DEF (AwaitKeyword, parseWord, "await", num)
659 PARSER_DEF (ClassKeyword, parseWord, "class", num)
660 PARSER_DEF (ConstKeyword, parseWord, "const", num)
661 PARSER_DEF (ConstructorKeyword, parseWord, "constructor", num)
662 PARSER_DEF (EnumKeyword, parseWord, "enum", num)
663 PARSER_DEF (ExtendsKeyword, parseWord, "extends", num)
664 PARSER_DEF (ForKeyword, parseWord, "for", num)
665 PARSER_DEF (FunctionKeyword, parseWord, "function", num)
666 PARSER_DEF (InKeyword, parseWord, "in", num)
667 PARSER_DEF (InterfaceKeyword, parseWord, "interface", num)
668 PARSER_DEF (ImplementsKeyword, parseWord, "implements", num)
669 PARSER_DEF (LetKeyword, parseWord, "let", num)
670 PARSER_DEF (NamespaceKeyword, parseWord, "namespace", num)
671 PARSER_DEF (NewKeyword, parseWord, "new", num)
672 PARSER_DEF (OfKeyword, parseWord, "of", num)
673 PARSER_DEF (PrivateKeyword, parseWord, "private", num)
674 PARSER_DEF (ProtectedKeyword, parseWord, "protected", num)
675 PARSER_DEF (PublicKeyword, parseWord, "public", num)
676 PARSER_DEF (ReadonlyKeyword, parseWord, "readonly", num)
677 PARSER_DEF (StaticKeyword, parseWord, "static", num)
678 PARSER_DEF (ThisKeyword, parseWord, "this", num)
679 PARSER_DEF (TypeKeyword, parseWord, "type", num)
680 PARSER_DEF (TypeofKeyword, parseWord, "typeof", num)
681 PARSER_DEF (VarKeyword, parseWord, "var", num)
682 PARSER_DEF (WhileKeyword, parseWord, "while", num)
684 SINGLE_CHAR_PARSER_DEF (Colon, ':', TOKEN_COLON)
685 SINGLE_CHAR_PARSER_DEF (Period, '.', TOKEN_PERIOD)
686 SINGLE_CHAR_PARSER_DEF (OpenCurly, '{', TOKEN_OPEN_CURLY)
687 SINGLE_CHAR_PARSER_DEF (Star, '*', TOKEN_STAR)
688 SINGLE_CHAR_PARSER_DEF (At, '@', TOKEN_AT)
689 SINGLE_CHAR_PARSER_DEF (NewLine, '\n', TOKEN_NL)
691 WORD_TOKEN_PARSER_DEF (Arrow, "=>", TOKEN_ARROW)
693 PARSER_DEF (StringSQuote, parseString, '\'', ch)
694 PARSER_DEF (StringDQuote, parseString, '"', ch)
695 PARSER_DEF (StringTemplate, parseString, '`', ch)
696 PARSER_DEF (StringRegex, parseString, '/', ch)
698 BLOCK_PARSER_DEF (Parens, '(', ')', TOKEN_PARENS)
699 BLOCK_PARSER_DEF (Squares, '[', ']', TOKEN_SQUARES)
700 BLOCK_PARSER_DEF (Template, '<', '>', TOKEN_TEMPLATE)
701 BLOCK_PARSER_DEF (Curlies, '{', '}', TOKEN_CURLIES)
703 CTAGS_INLINE bool tryParser(Parser parser, tokenInfo *const token, bool skipWhite)
705 parserState currentState;
706 parserResult result;
707 int c;
709 result.status = PARSER_NEEDS_MORE_INPUT;
710 result.unusedChars = 0;
711 memset(&currentState, 0, sizeof (currentState));
713 uwiPushMarker();
715 c = uwiGetC ();
716 if (skipWhite && whiteChar (c))
718 do {
719 c = uwiGetC ();
720 } while (whiteChar (c));
722 parser (c, token, &currentState, &result);
724 while (result.status == PARSER_NEEDS_MORE_INPUT)
726 c = uwiGetC ();
727 parser (c, token, &currentState, &result);
730 if (result.status == PARSER_FAILED) uwiPopMarker (-1, true);
731 else if (result.unusedChars > 0) uwiPopMarker (result.unusedChars, true);
732 else uwiDropMaker ();
734 return result.status == PARSER_FINISHED;
737 static bool tryInSequence(tokenInfo *const token, bool skipUnparsed, Parser parser, ...)
739 Parser currentParser = NULL;
740 bool result = false;
742 tryParser (parseWhiteChars, token, false);
744 va_list args;
745 va_start (args, parser);
747 currentParser = parser;
748 while (! result && currentParser)
750 result = tryParser (currentParser, token, false);
751 currentParser = va_arg (args, Parser);
754 va_end (args);
756 if (skipUnparsed && ! result)
758 bool skippedNextWord = false;
759 int c = uwiGetC ();
761 while (c != EOF && isIdentChar(c))
763 c = uwiGetC ();
764 skippedNextWord = true;
767 if (c != EOF && skippedNextWord) uwiUngetC (c);
769 return c != EOF;
772 return result;
775 MULTI_CHAR_PARSER_DEF (DecoratorChars, "@\n", TOKEN_AT, TOKEN_NL)
776 static void parseDecorator (tokenInfo *const token)
778 bool parsed = false;
782 clearPoolToken (token);
783 parsed = tryInSequence (token, false, parseDecoratorChars, parseComment, NULL);
784 } while (parsed && token->type != TOKEN_PARENS);
788 clearPoolToken (token);
790 parsed = tryInSequence (token, false, parseNewLine, parseComment, parseIdentifier, NULL);
791 } while (parsed && (token->type != TOKEN_IDENTIFIER || tryParser ((Parser) parsePeriod, token, true)));
793 //parse optional parens block
794 tryParser ((Parser) parseParens, token, true);
797 MULTI_CHAR_PARSER_DEF (InterfaceBodyChars, "}:;.,|&",
798 TOKEN_CLOSE_CURLY, TOKEN_COLON,
799 TOKEN_SEMICOLON, TOKEN_PERIOD, TOKEN_COMMA,
800 TOKEN_PIPE, TOKEN_AMPERSAND)
801 static void parseInterfaceBody (const int scope, tokenInfo *const token)
803 bool parsed;
807 parsed = tryInSequence (token, true,
808 parseComment,
809 parseTemplate,
810 parseStringSQuote,
811 parseStringDQuote,
812 parseStringTemplate,
813 parseStringRegex,
814 parseParens,
815 parseSquares,
816 parseOpenCurly,
817 NULL);
818 } while (parsed && ! isType (token, TOKEN_OPEN_CURLY));
820 if (! parsed) return;
822 tokenInfo *member = NULL;
823 bool parsingType = false;
824 int visibility = 0;
828 clearPoolToken (token);
830 parsed = tryInSequence (token, true,
831 parseTemplate,
832 parseComment,
833 parseStringSQuote,
834 parseStringDQuote,
835 parseStringTemplate,
836 parseStringRegex,
837 parseParens,
838 parseSquares,
839 parseCurlies,
840 parseNumber,
841 parsePrivateKeyword,
842 parseProtectedKeyword,
843 parsePublicKeyword,
844 parseReadonlyKeyword,
845 parseStaticKeyword,
846 parseArrow,
847 parseTypeofKeyword,
848 parseInterfaceBodyChars,
849 parseIdentifier,
850 NULL);
852 if (parsed)
854 switch (token->type)
856 case TOKEN_KEYWORD:
857 switch (token->keyword)
859 case KEYWORD_private:
860 case KEYWORD_public:
861 case KEYWORD_protected:
862 if (member)
864 emitTag (member, TSTAG_PROPERTY);
865 deleteToken (member);
866 member = NULL;
868 visibility = token->keyword;
869 parsingType = false;
870 break;
871 case KEYWORD_typeof:
872 parsingType = true;
873 break;
875 break;
876 case TOKEN_COLON:
877 case TOKEN_PERIOD:
878 case TOKEN_PIPE:
879 case TOKEN_AMPERSAND:
880 case TOKEN_ARROW:
881 parsingType = true;
882 break;
883 case TOKEN_IDENTIFIER:
884 if (member)
886 emitTag (member, TSTAG_PROPERTY);
887 deleteToken (member);
888 member = NULL;
889 visibility = 0;
892 if (!parsingType)
894 member = newToken ();
895 copyToken (member, token, false);
896 member->scope = scope;
897 if (visibility) member->accessKeyword = visibility;
898 else member->accessKeyword = KEYWORD_public;
900 parsingType = false;
901 break;
902 case TOKEN_PARENS:
903 if (!parsingType && member)
905 emitTag (member, TSTAG_METHOD);
906 deleteToken (member);
907 member = NULL;
908 visibility = 0;
910 case TOKEN_SQUARES:
911 case TOKEN_CURLIES:
912 case TOKEN_TEMPLATE:
913 case TOKEN_SEMICOLON:
914 case TOKEN_COMMA:
915 case TOKEN_STRING:
916 case TOKEN_NUMBER:
917 parsingType = false;
918 break;
919 default:
920 break;
923 } while (parsed && ! isType (token, TOKEN_CLOSE_CURLY));
925 if (member)
927 emitTag (member, TSTAG_PROPERTY);
928 deleteToken (member);
932 static void parseInterface (const int scope, tokenInfo *const token)
934 bool parsed;
938 clearPoolToken (token);
939 parsed = tryInSequence (token, false,
940 parseNewLine,
941 parseComment,
942 parseIdentifier,
943 NULL);
944 } while (parsed && token->type != TOKEN_IDENTIFIER);
946 if (! parsed) return;
948 token->scope = scope;
950 const int nscope = emitTag (token, TSTAG_INTERFACE);
952 parseInterfaceBody (nscope, token);
955 MULTI_CHAR_PARSER_DEF (TypeChars, ":;,=|&",
956 TOKEN_COLON, TOKEN_SEMICOLON, TOKEN_COMMA,
957 TOKEN_EQUAL_SIGN, TOKEN_PIPE, TOKEN_AMPERSAND)
958 static void parseType (const int scope, tokenInfo *const token)
960 bool parsed;
961 bool parsingType = false;
962 bool shouldEnd = false;
966 clearPoolToken (token);
967 parsed = tryInSequence (token, false,
968 parseComment,
969 parseTemplate,
970 parseStringSQuote,
971 parseStringDQuote,
972 parseStringTemplate,
973 parseStringRegex,
974 parseParens,
975 parseSquares,
976 parseCurlies,
977 parseArrow,
978 parseNumber,
979 parseTypeofKeyword,
980 parseTypeChars,
981 parseIdentifier,
982 NULL);
983 if (parsed)
985 switch (token->type)
987 case TOKEN_KEYWORD:
988 switch (token->keyword)
990 case KEYWORD_typeof:
991 shouldEnd = true;
992 parsingType = true;
993 break;
994 default:
995 break;
997 break;
998 case TOKEN_COLON:
999 case TOKEN_TEMPLATE:
1000 case TOKEN_STRING:
1001 case TOKEN_PARENS:
1002 case TOKEN_SQUARES:
1003 case TOKEN_CURLIES:
1004 case TOKEN_NUMBER:
1005 shouldEnd = true;
1006 parsingType = false;
1007 break;
1008 case TOKEN_EQUAL_SIGN:
1009 case TOKEN_PIPE:
1010 case TOKEN_AMPERSAND:
1011 case TOKEN_ARROW:
1012 parsingType = true;
1013 break;
1014 case TOKEN_IDENTIFIER:
1015 if (! parsingType && ! shouldEnd)
1017 token->scope = scope;
1018 emitTag (token, TSTAG_ALIAS);
1020 else if (! parsingType && shouldEnd)
1022 for (int i = vStringLength(token->string); i >= 0; i--)
1023 uwiUngetC (vStringChar(token->string, i));
1025 parsed = false;
1027 parsingType = false;
1028 break;
1029 default:
1030 break;
1033 } while (parsed && ! isType (token, TOKEN_COMMA) && ! isType (token, TOKEN_SEMICOLON));
1035 clearPoolToken(token);
1038 MULTI_CHAR_PARSER_DEF (EnumBodyChars, "},=|&.",
1039 TOKEN_CLOSE_CURLY, TOKEN_COMMA, TOKEN_EQUAL_SIGN,
1040 TOKEN_PIPE, TOKEN_AMPERSAND, TOKEN_PERIOD)
1041 static void parseEnumBody (const int scope, tokenInfo *const token)
1043 bool parsed;
1047 parsed = tryInSequence (token, true,
1048 parseTemplate,
1049 parseComment,
1050 parseStringSQuote,
1051 parseStringDQuote,
1052 parseStringTemplate,
1053 parseStringRegex,
1054 parseParens,
1055 parseSquares,
1056 parseOpenCurly,
1057 NULL);
1058 } while (parsed && token->type != TOKEN_OPEN_CURLY);
1060 if (! parsed) return;
1062 tokenInfo *member = NULL;
1063 bool parsingValue = false;
1066 clearPoolToken (token);
1067 parsed = tryInSequence (token, true,
1068 parseTemplate,
1069 parseComment,
1070 parseStringSQuote,
1071 parseStringDQuote,
1072 parseStringTemplate,
1073 parseStringRegex,
1074 parseParens,
1075 parseSquares,
1076 parseCurlies,
1077 parseNumber,
1078 parseEnumBodyChars,
1079 parseNewKeyword,
1080 parseIdentifier,
1081 NULL);
1083 if (parsed)
1085 switch (token->type)
1087 case TOKEN_KEYWORD:
1088 switch (token->keyword)
1090 case KEYWORD_new:
1091 parsingValue = true;
1092 break;
1094 break;
1095 case TOKEN_EQUAL_SIGN:
1096 case TOKEN_PIPE:
1097 case TOKEN_AMPERSAND:
1098 case TOKEN_PERIOD:
1099 parsingValue = true;
1100 break;
1101 case TOKEN_COMMA:
1102 case TOKEN_SEMICOLON:
1103 case TOKEN_STRING:
1104 case TOKEN_PARENS:
1105 case TOKEN_SQUARES:
1106 case TOKEN_CURLIES:
1107 case TOKEN_NUMBER:
1108 parsingValue = false;
1109 break;
1110 case TOKEN_IDENTIFIER:
1111 if (!parsingValue)
1113 member = newToken ();
1114 copyToken (member, token, false);
1115 member->scope = scope;
1116 emitTag (member, TSTAG_ENUMERATOR);
1117 deleteToken (member);
1118 member = NULL;
1120 parsingValue = false;
1121 break;
1122 default:
1123 break;
1126 } while (parsed && ! isType (token, TOKEN_CLOSE_CURLY));
1128 if (member)
1130 deleteToken (member);
1134 static void parseEnum (const int scope, tokenInfo *const token)
1136 bool parsed;
1140 clearPoolToken (token);
1141 parsed = tryInSequence (token, false,
1142 parseComment,
1143 parseIdentifier,
1144 NULL);
1145 } while (parsed && token->type != TOKEN_IDENTIFIER);
1147 if (! parsed) return;
1149 token->scope = scope;
1150 const int nscope = emitTag (token, TSTAG_ENUM);
1152 parseEnumBody (nscope, token);
1155 MULTI_CHAR_PARSER_DEF (VariableChars, "|&=?[]{}()\n:;,.-+/^<>*",
1156 TOKEN_PIPE, TOKEN_AMPERSAND, TOKEN_EQUAL_SIGN, TOKEN_QUESTION_MARK,
1157 TOKEN_OPEN_SQUARE, TOKEN_CLOSE_SQUARE, TOKEN_OPEN_CURLY, TOKEN_CLOSE_CURLY,
1158 TOKEN_OPEN_PAREN, TOKEN_CLOSE_PAREN, TOKEN_NL, TOKEN_COLON, TOKEN_SEMICOLON,
1159 TOKEN_COMMA, TOKEN_PERIOD, TOKEN_MINUS, TOKEN_PLUS,
1160 TOKEN_DIV, TOKEN_POWER, TOKEN_LOWER, TOKEN_GREATER, TOKEN_STAR)
1161 static void parseVariable (bool constVar, bool localVar, const int scope, tokenInfo *const token)
1163 tokenInfo *member = NULL;
1164 bool parsed = false;
1165 bool parsingType = false;
1166 bool expectingVariable = false;
1167 bool mayBeFun = false;
1168 bool isFunction = false;
1169 int nestLevel = 0, parenLevel = 0;
1170 tsKind varKind = constVar ? TSTAG_CONSTANT : (localVar ? TSTAG_LOCAL : TSTAG_VARIABLE);
1174 clearPoolToken (token);
1175 parsed = tryInSequence (token, false,
1176 parseTemplate,
1177 parseComment,
1178 parseStringRegex,
1179 parseStringSQuote,
1180 parseStringDQuote,
1181 parseStringTemplate,
1182 parseNumber,
1183 parseArrow,
1184 parseAsKeyword,
1185 parseAwaitKeyword,
1186 parseForKeyword,
1187 parseFunctionKeyword,
1188 parseWhileKeyword,
1189 parseThisKeyword,
1190 parseEnumKeyword,
1191 parseOfKeyword,
1192 parseInKeyword,
1193 parseNewKeyword,
1194 parseTypeofKeyword,
1195 parseVariableChars,
1196 parseIdentifier,
1197 NULL);
1199 if (parsed)
1201 switch (token->type)
1203 case TOKEN_OPEN_SQUARE:
1204 case TOKEN_OPEN_CURLY:
1205 nestLevel += 1;
1206 break;
1207 case TOKEN_OPEN_PAREN:
1208 parenLevel += 1;
1209 nestLevel += 1;
1210 if (mayBeFun) isFunction = true;
1211 break;
1212 case TOKEN_CLOSE_SQUARE:
1213 nestLevel -= 1;
1214 break;
1215 case TOKEN_CLOSE_PAREN:
1216 parenLevel -= 1;
1217 nestLevel -= 1;
1218 break;
1219 case TOKEN_CLOSE_CURLY:
1220 nestLevel -= 1;
1221 if (nestLevel <= 0) isFunction = false;
1222 break;
1223 case TOKEN_COMMA:
1224 expectingVariable = true;
1225 case TOKEN_SEMICOLON:
1226 case TOKEN_NUMBER:
1227 case TOKEN_STRING:
1228 if (nestLevel <= 0)
1230 parsingType = false;
1231 nestLevel = 0;
1233 break;
1234 case TOKEN_STAR:
1235 case TOKEN_MINUS:
1236 case TOKEN_PLUS:
1237 case TOKEN_DIV:
1238 case TOKEN_POWER:
1239 case TOKEN_GREATER:
1240 case TOKEN_LOWER:
1241 case TOKEN_PERIOD:
1242 case TOKEN_PIPE:
1243 case TOKEN_AMPERSAND:
1244 case TOKEN_COLON:
1245 case TOKEN_EQUAL_SIGN:
1246 parsingType = true;
1247 break;
1248 case TOKEN_ARROW:
1249 isFunction = true;
1250 break;
1251 case TOKEN_IDENTIFIER:
1252 if (parenLevel <= 0 && ! isFunction && ! parsingType)
1254 member = newToken ();
1255 copyToken (member, token, false);
1256 member->scope = scope;
1257 emitTag (member, varKind);
1258 deleteToken (member);
1260 expectingVariable = false;
1261 parsingType = false;
1262 break;
1263 case TOKEN_KEYWORD:
1264 switch (token->keyword)
1266 case KEYWORD_enum:
1267 parseEnum (scope, token);
1268 break;
1269 case KEYWORD_as:
1270 case KEYWORD_of:
1271 case KEYWORD_in:
1272 case KEYWORD_await:
1273 case KEYWORD_new:
1274 case KEYWORD_typeof:
1275 parsingType = true;
1276 break;
1278 break;
1279 default:
1280 if (nestLevel <= 0) parsingType = false;
1281 if (token->type != TOKEN_NL) expectingVariable = false;
1282 break;
1285 if (isType (token, TOKEN_EQUAL_SIGN) || isKeyword (token, KEYWORD_function)) mayBeFun = true;
1286 else if (! isType(token, TOKEN_COMMENT_BLOCK) && nestLevel <= 0) mayBeFun = false;
1288 } while (parsed &&
1289 ! ((token->type == TOKEN_SEMICOLON
1290 || (token->type == TOKEN_CLOSE_PAREN && ! isFunction)
1291 || (token->type == TOKEN_NL && ! expectingVariable))
1292 && ! parsingType && nestLevel <= 0));
1294 clearPoolToken (token);
1297 MULTI_CHAR_PARSER_DEF (FunctionArgsChars, "\n(", TOKEN_NL, TOKEN_OPEN_PAREN)
1298 MULTI_CHAR_PARSER_DEF (FunctionArgsAfterParenChars, "|&=?[]{})\n:,.@",
1299 TOKEN_PIPE, TOKEN_AMPERSAND, TOKEN_EQUAL_SIGN, TOKEN_QUESTION_MARK,
1300 TOKEN_OPEN_SQUARE, TOKEN_CLOSE_SQUARE, TOKEN_OPEN_CURLY, TOKEN_CLOSE_CURLY,
1301 TOKEN_CLOSE_PAREN, TOKEN_NL, TOKEN_COLON, TOKEN_COMMA, TOKEN_PERIOD, TOKEN_AT)
1302 static void parseFunctionArgs (const int scope, tokenInfo *const token)
1304 bool parsed = false;
1305 bool parsingType = false;
1306 int nestLevel = 0;
1307 tokenInfo *member = NULL;
1311 clearPoolToken (token);
1312 parsed = tryInSequence (token, false,
1313 parseTemplate,
1314 parseComment,
1315 parseFunctionArgsChars,
1316 NULL);
1317 } while (parsed && token->type != TOKEN_OPEN_PAREN);
1319 if (! parsed) return;
1323 clearPoolToken (token);
1324 parsed = tryInSequence (token, false,
1325 parseTemplate,
1326 parseComment,
1327 parseStringSQuote,
1328 parseStringDQuote,
1329 parseStringTemplate,
1330 parseStringRegex,
1331 parseParens,
1332 parseNumber,
1333 parseFunctionArgsAfterParenChars,
1334 parseArrow,
1335 parseIdentifier,
1336 NULL);
1338 if (parsed)
1340 switch (token->type)
1342 case TOKEN_AT:
1343 uwiUngetC ('@');
1344 parseDecorator (token);
1345 break;
1346 case TOKEN_OPEN_SQUARE:
1347 case TOKEN_OPEN_CURLY:
1348 if (parsingType) nestLevel += 1;
1349 break;
1350 case TOKEN_CLOSE_SQUARE:
1351 case TOKEN_CLOSE_CURLY:
1352 if (parsingType) nestLevel -= 1;
1353 break;
1354 case TOKEN_COMMA:
1355 if (nestLevel <= 0)
1357 parsingType = false;
1358 nestLevel = 0;
1360 break;
1361 case TOKEN_COLON:
1362 case TOKEN_EQUAL_SIGN:
1363 parsingType = true;
1364 break;
1365 case TOKEN_IDENTIFIER:
1366 if (! parsingType)
1368 member = newToken ();
1369 copyToken (member, token, false);
1370 member->scope = scope;
1371 emitTag (member, TSTAG_PARAMETER);
1372 deleteToken (member);
1374 break;
1375 default:
1376 break;
1379 } while (parsed && token->type != TOKEN_CLOSE_PAREN);
1382 MULTI_CHAR_PARSER_DEF (FunctionBodyChars, "{}", TOKEN_OPEN_CURLY, TOKEN_CLOSE_CURLY)
1383 static void parseFunctionBody (const int scope, tokenInfo *const token)
1385 bool parsed = false;
1386 int nestLevel = 1;
1390 clearPoolToken (token);
1392 parsed = tryInSequence (token, true,
1393 parseOpenCurly,
1394 parseComment,
1395 parseStringSQuote,
1396 parseStringDQuote,
1397 parseStringTemplate,
1398 parseStringRegex,
1399 parseTemplate,
1400 NULL);
1402 } while (parsed && ! isType (token, TOKEN_OPEN_CURLY));
1404 if (! parsed) return;
1408 clearPoolToken (token);
1410 parsed = tryInSequence (token, true,
1411 parseFunctionBodyChars,
1412 parseComment,
1413 parseStringSQuote,
1414 parseStringDQuote,
1415 parseStringTemplate,
1416 parseStringRegex,
1417 parseTemplate,
1418 parseVarKeyword,
1419 parseLetKeyword,
1420 parseConstKeyword,
1421 NULL);
1423 if (parsed)
1425 switch (token->type)
1427 case TOKEN_OPEN_CURLY:
1428 nestLevel += 1;
1429 break;
1430 case TOKEN_CLOSE_CURLY:
1431 nestLevel -= 1;
1432 break;
1433 case TOKEN_KEYWORD:
1434 switch (token->keyword)
1436 case KEYWORD_var:
1437 case KEYWORD_let:
1438 parseVariable (false, true, scope, token);
1439 break;
1440 case KEYWORD_const:
1441 parseVariable (true, true, scope, token);
1442 break;
1444 break;
1445 default:
1446 break;
1449 } while (parsed && ! (isType (token, TOKEN_CLOSE_CURLY) && nestLevel <= 0));
1451 clearPoolToken (token);
1454 static void parseFunction (const int scope, tokenInfo *const token)
1456 bool isGenerator = false;
1457 bool parsed;
1461 clearPoolToken (token);
1462 parsed = tryInSequence (token, false,
1463 parseComment,
1464 parseStar,
1465 parseIdentifier,
1466 NULL);
1468 if (parsed && isType (token, TOKEN_STAR)) isGenerator = true;
1469 } while (parsed && token->type != TOKEN_IDENTIFIER);
1471 if (! parsed) return;
1473 token->scope = scope;
1475 const int nscope = emitTag (token, isGenerator ? TSTAG_GENERATOR : TSTAG_FUNCTION);
1477 parseFunctionArgs (nscope, token);
1478 parseFunctionBody (nscope, token);
1481 MULTI_CHAR_PARSER_DEF (PropertyTypeChars, "\n;|&,)",
1482 TOKEN_NL, TOKEN_SEMICOLON, TOKEN_PIPE, TOKEN_AMPERSAND,
1483 TOKEN_COMMA, TOKEN_CLOSE_PAREN)
1484 static void parsePropertyType (tokenInfo *const token)
1486 bool parsed = tryParser ((Parser) parseColon, token, true);
1487 bool parsedIdentifier = false;
1488 bool parseReturnValue = false;
1490 if (! parsed) return;
1494 clearPoolToken (token);
1496 if (parsedIdentifier)
1498 parsed = tryInSequence (token, false,
1499 parsePropertyTypeChars,
1500 parseArrow,
1501 parseTemplate,
1502 parseParens,
1503 parseComment,
1504 parseStringSQuote,
1505 parseStringDQuote,
1506 parseStringTemplate,
1507 parseStringRegex,
1508 parseSquares,
1509 parseCurlies,
1510 NULL);
1512 if (isType (token, TOKEN_PIPE) || isType (token, TOKEN_AMPERSAND)) parsedIdentifier = false;
1514 else
1516 parsed = tryInSequence (token, false,
1517 parsePropertyTypeChars,
1518 parseArrow,
1519 parseTemplate,
1520 parseParens,
1521 parseComment,
1522 parseStringSQuote,
1523 parseStringDQuote,
1524 parseStringTemplate,
1525 parseStringRegex,
1526 parseSquares,
1527 parseCurlies,
1528 parseIdentifier,
1529 NULL);
1531 if (isType (token, TOKEN_IDENTIFIER)) parsedIdentifier = true;
1535 if (isType (token, TOKEN_ARROW)) parseReturnValue = true;
1536 } while (parsed
1537 && ! isType (token, TOKEN_CLOSE_PAREN)
1538 && ! isType (token, TOKEN_SEMICOLON)
1539 && ! isType (token, TOKEN_COMMA)
1540 && ! (parseReturnValue && (
1541 isType (token, TOKEN_PARENS)
1542 || isType (token, TOKEN_CURLIES)
1543 || isType (token, TOKEN_SQUARES))));
1545 if (! parsed) return;
1547 if (isType (token, TOKEN_CLOSE_PAREN)) uwiUngetC (')');
1549 clearPoolToken (token);
1552 MULTI_CHAR_PARSER_DEF (ConstructorParamsChars, "\n(", TOKEN_NL, TOKEN_OPEN_PAREN)
1553 MULTI_CHAR_PARSER_DEF (ConstructorParamsAfterParenChars, "\n:,)@",
1554 TOKEN_NL, TOKEN_COLON, TOKEN_COMMA, TOKEN_CLOSE_PAREN, TOKEN_AT)
1555 static void parseConstructorParams (const int classScope, const int constrScope, tokenInfo *const token)
1557 bool parsed = false;
1561 clearPoolToken (token);
1563 parsed = tryInSequence (token, false,
1564 parseConstructorParamsChars,
1565 parseComment,
1566 NULL);
1567 } while (parsed && ! isType (token, TOKEN_OPEN_PAREN));
1569 if (! parsed) return;
1571 tokenInfo *member = NULL;
1572 int visibility = 0;
1576 clearPoolToken (token);
1578 parsed = tryInSequence (token, false,
1579 parseConstructorParamsAfterParenChars,
1580 parseComment,
1581 parsePrivateKeyword,
1582 parseProtectedKeyword,
1583 parsePublicKeyword,
1584 parseReadonlyKeyword,
1585 parseStaticKeyword,
1586 parseIdentifier,
1587 NULL);
1589 if (parsed)
1591 switch (token->type)
1593 case TOKEN_AT:
1594 uwiUngetC ('@');
1595 parseDecorator (token);
1596 break;
1597 case TOKEN_KEYWORD:
1598 switch (token->keyword)
1600 case KEYWORD_private:
1601 case KEYWORD_public:
1602 case KEYWORD_protected:
1603 visibility = token->keyword;
1604 break;
1606 break;
1607 case TOKEN_COLON:
1608 uwiUngetC (':');
1609 parsePropertyType (token);
1610 break;
1611 case TOKEN_IDENTIFIER:
1612 member = newToken ();
1613 copyToken (member, token, false);
1614 if (visibility)
1616 member->accessKeyword = visibility;
1617 member->scope = classScope;
1618 emitTag (member, TSTAG_PROPERTY);
1620 else
1622 member->scope = constrScope;
1623 emitTag (member, TSTAG_PARAMETER);
1625 deleteToken (member);
1626 member = NULL;
1627 visibility = 0;
1628 break;
1629 default:
1630 break;
1633 } while (parsed && ! isType (token, TOKEN_CLOSE_PAREN));
1637 MULTI_CHAR_PARSER_DEF (ClassBodyChars, "\n,{", TOKEN_NL, TOKEN_COMMA, TOKEN_OPEN_CURLY)
1638 MULTI_CHAR_PARSER_DEF (ClassBodyAfterCurlyChars, "\n}*@(:;=-+/^<>.,|&",
1639 TOKEN_NL, TOKEN_CLOSE_CURLY, TOKEN_STAR, TOKEN_AT, TOKEN_OPEN_PAREN,
1640 TOKEN_COLON, TOKEN_SEMICOLON, TOKEN_EQUAL_SIGN,
1641 TOKEN_MINUS, TOKEN_PLUS, TOKEN_DIV, TOKEN_POWER,
1642 TOKEN_GREATER, TOKEN_LOWER, TOKEN_PERIOD, TOKEN_COMMA,
1643 TOKEN_PIPE, TOKEN_AMPERSAND)
1644 static void parseClassBody (const int scope, tokenInfo *const token)
1646 bool parsed = false;
1647 vString *inheritance = NULL;
1649 //parse until {
1652 clearPoolToken (token);
1654 parsed = tryInSequence (token, false,
1655 parseClassBodyChars,
1656 parseTemplate,
1657 parseComment,
1658 parseExtendsKeyword,
1659 parseImplementsKeyword,
1660 parseIdentifier,
1661 NULL);
1663 if (token->type == TOKEN_KEYWORD
1664 && (token->keyword == KEYWORD_extends || token->keyword == KEYWORD_implements)
1665 && inheritance == NULL) inheritance = vStringNew ();
1666 else if (inheritance && token->type == TOKEN_IDENTIFIER) vStringJoin (inheritance, ',', token->string);
1667 } while (parsed && token->type != TOKEN_OPEN_CURLY);
1669 if (! parsed)
1671 vStringDelete (inheritance); /* NULL is acceptable. */
1672 return;
1675 if (inheritance)
1677 tagEntryInfo *klass = getEntryInCorkQueue (scope);
1678 if (klass)
1680 klass->extensionFields.inheritance = vStringDeleteUnwrap (inheritance);
1681 inheritance = NULL;
1683 vStringDelete (inheritance);
1686 tokenInfo *member = NULL;
1687 bool isGenerator = false;
1688 bool parsingValue = false;
1689 int visibility = 0;
1693 clearPoolToken (token);
1695 parsed = tryInSequence (token, false,
1696 parseComment,
1697 parseStringSQuote,
1698 parseStringDQuote,
1699 parseStringTemplate,
1700 parseStringRegex,
1701 parseAsyncKeyword,
1702 parseConstructorKeyword,
1703 parseNewKeyword,
1704 parsePrivateKeyword,
1705 parseProtectedKeyword,
1706 parsePublicKeyword,
1707 parseReadonlyKeyword,
1708 parseStaticKeyword,
1709 parseNumber,
1710 parseTemplate,
1711 parseTypeofKeyword,
1712 parseClassBodyAfterCurlyChars,
1713 parseSquares,
1714 parseCurlies,
1715 parseIdentifier,
1716 NULL);
1718 if (parsed)
1720 switch (token->type)
1722 case TOKEN_AT:
1723 uwiUngetC ('@');
1724 parseDecorator (token);
1725 break;
1726 case TOKEN_KEYWORD:
1727 switch (token->keyword)
1729 case KEYWORD_constructor:
1730 if (member)
1732 emitTag (member, TSTAG_PROPERTY);
1733 deleteToken (member);
1734 member = NULL;
1735 isGenerator = false;
1737 member = newToken ();
1738 copyToken (member, token, false);
1739 member->scope = scope;
1741 if (visibility) member->accessKeyword = visibility;
1742 else member->accessKeyword = KEYWORD_public;
1744 const int nscope = emitTag (member, TSTAG_METHOD);
1745 deleteToken (member);
1746 member = NULL;
1747 visibility = 0;
1749 parseConstructorParams (scope, nscope, token);
1751 parseFunctionBody (nscope, token);
1752 parsingValue = false;
1753 break;
1754 case KEYWORD_private:
1755 case KEYWORD_public:
1756 case KEYWORD_protected:
1757 if (member)
1759 emitTag (member, TSTAG_PROPERTY);
1760 deleteToken (member);
1761 member = NULL;
1763 visibility = token->keyword;
1764 parsingValue = false;
1765 break;
1766 case KEYWORD_new:
1767 case KEYWORD_typeof:
1768 parsingValue = true;
1769 break;
1771 isGenerator = false;
1772 break;
1773 case TOKEN_EQUAL_SIGN:
1774 if (member)
1776 emitTag (member, TSTAG_PROPERTY);
1777 deleteToken (member);
1778 member = NULL;
1779 isGenerator = false;
1781 parsingValue = true;
1782 break;
1783 case TOKEN_COLON:
1784 uwiUngetC (':');
1785 parsePropertyType (token);
1786 case TOKEN_SEMICOLON:
1787 if (member)
1789 emitTag (member, TSTAG_PROPERTY);
1790 deleteToken (member);
1791 member = NULL;
1792 isGenerator = false;
1793 visibility = 0;
1795 parsingValue = false;
1796 break;
1797 case TOKEN_STAR:
1798 isGenerator = true;
1799 case TOKEN_MINUS:
1800 case TOKEN_PLUS:
1801 case TOKEN_DIV:
1802 case TOKEN_POWER:
1803 case TOKEN_GREATER:
1804 case TOKEN_LOWER:
1805 case TOKEN_PERIOD:
1806 case TOKEN_PIPE:
1807 case TOKEN_AMPERSAND:
1808 parsingValue = true;
1809 break;
1810 case TOKEN_STRING:
1811 case TOKEN_COMMA:
1812 case TOKEN_NUMBER:
1813 case TOKEN_SQUARES:
1814 case TOKEN_CURLIES:
1815 parsingValue = false;
1816 break;
1817 case TOKEN_OPEN_PAREN:
1818 uwiUngetC ('(');
1819 if (! member) {
1820 parsed = tryParser (parseParens, token, false);
1821 break;
1824 const int nscope = emitTag (member, isGenerator ? TSTAG_GENERATOR : TSTAG_METHOD);
1826 deleteToken (member);
1827 member = NULL;
1829 parseFunctionArgs (nscope, token);
1830 parseFunctionBody (nscope, token);
1832 isGenerator = false;
1833 visibility = 0;
1834 parsingValue = false;
1835 break;
1836 case TOKEN_IDENTIFIER:
1837 if (!parsingValue) {
1838 if (member) deleteToken (member);
1839 member = newToken ();
1840 copyToken (member, token, false);
1841 member->scope = scope;
1842 if (visibility) member->accessKeyword = visibility;
1843 else member->accessKeyword = KEYWORD_public;
1846 parsingValue = false;
1847 isGenerator = false;
1848 break;
1849 default:
1850 isGenerator = false;
1851 visibility = 0;
1852 break;
1855 } while (parsed && token->type != TOKEN_CLOSE_CURLY);
1857 if (parsed && member)
1859 emitTag (member, TSTAG_PROPERTY);
1860 deleteToken (member);
1862 else if (member) deleteToken (member);
1865 static void parseClass (const int scope, tokenInfo *const token)
1867 bool parsed = false;
1871 clearPoolToken (token);
1873 parsed = tryInSequence (token, false,
1874 parseNewLine,
1875 parseComment,
1876 parseIdentifier,
1877 NULL);
1878 } while (parsed && token->type != TOKEN_IDENTIFIER);
1880 if (! parsed) return;
1882 token->scope = scope;
1883 const int nscope = emitTag (token, TSTAG_CLASS);
1885 parseClassBody (nscope, token);
1888 MULTI_CHAR_PARSER_DEF (NamespaceBodyChars, "\n{", TOKEN_NL, TOKEN_OPEN_CURLY)
1889 MULTI_CHAR_PARSER_DEF (NamespaceBodyAfterCurlyChars, "@{}()[]",
1890 TOKEN_AT, TOKEN_OPEN_CURLY, TOKEN_CLOSE_CURLY, TOKEN_OPEN_PAREN,
1891 TOKEN_CLOSE_PAREN, TOKEN_OPEN_SQUARE, TOKEN_CLOSE_SQUARE)
1892 static void parseNamespaceBody (const int scope, tokenInfo *const token)
1894 bool parsed = false;
1896 //parse until {
1899 parsed = tryInSequence (token, false,
1900 parseNamespaceBodyChars,
1901 parseComment,
1902 NULL);
1903 } while (parsed && token->type != TOKEN_OPEN_CURLY);
1905 if (! parsed) return;
1907 int parenLvl = 0;
1908 int squareLvl = 0;
1909 int curlyLvl = 1;
1913 clearPoolToken (token);
1915 parsed = tryInSequence (token, true,
1916 parseComment,
1917 parseTemplate,
1918 parseStringSQuote,
1919 parseStringDQuote,
1920 parseStringTemplate,
1921 parseStringRegex,
1922 parseInterfaceKeyword,
1923 parseTypeKeyword,
1924 parseEnumKeyword,
1925 parseFunctionKeyword,
1926 parseClassKeyword,
1927 parseVarKeyword,
1928 parseLetKeyword,
1929 parseConstKeyword,
1930 parseNamespaceBodyAfterCurlyChars,
1931 NULL);
1933 switch (token->type)
1935 case TOKEN_KEYWORD:
1936 switch (token->keyword)
1938 case KEYWORD_interface:
1939 parseInterface (scope, token);
1940 break;
1941 case KEYWORD_type:
1942 parseType (scope, token);
1943 break;
1944 case KEYWORD_enum:
1945 parseEnum (scope, token);
1946 break;
1947 case KEYWORD_function:
1948 parseFunction (scope, token);
1949 break;
1950 case KEYWORD_class:
1951 parseClass (scope, token);
1952 break;
1953 case KEYWORD_var:
1954 case KEYWORD_let:
1955 parseVariable (false, false, scope, token);
1956 break;
1957 case KEYWORD_const:
1958 parseVariable (true, false, scope, token);
1959 break;
1961 break;
1962 case TOKEN_AT:
1963 uwiUngetC ('@');
1964 parseDecorator (token);
1965 break;
1966 case TOKEN_OPEN_CURLY:
1967 curlyLvl += 1;
1968 break;
1969 case TOKEN_OPEN_SQUARE:
1970 squareLvl += 1;
1971 break;
1972 case TOKEN_OPEN_PAREN:
1973 parenLvl += 1;
1974 break;
1975 case TOKEN_CLOSE_CURLY:
1976 curlyLvl -= 1;
1977 break;
1978 case TOKEN_CLOSE_SQUARE:
1979 squareLvl -= 1;
1980 break;
1981 case TOKEN_CLOSE_PAREN:
1982 parenLvl -= 1;
1983 break;
1984 default:
1985 break;
1987 } while (parsed && ! (isType (token, TOKEN_CLOSE_CURLY) && parenLvl <= 0 && squareLvl <= 0 && curlyLvl <= 0));
1990 static void parseNamespace (tokenInfo *const token)
1992 bool parsed = false;
1996 clearPoolToken (token);
1998 parsed = tryInSequence (token, false,
1999 parseNewLine,
2000 parseComment,
2001 parseFQIdentifier,
2002 NULL);
2003 } while (parsed && token->type != TOKEN_IDENTIFIER);
2005 if (! parsed) return;
2007 const int scope = emitTag (token, TSTAG_NAMESPACE);
2009 parseNamespaceBody (scope, token);
2012 static void parseTsFile (tokenInfo *const token)
2014 bool parsed;
2018 clearPoolToken (token);
2020 parsed = tryInSequence (token, true,
2021 parseComment,
2022 parseTemplate,
2023 parseStringSQuote,
2024 parseStringDQuote,
2025 parseStringTemplate,
2026 parseStringRegex,
2027 parseInterfaceKeyword,
2028 parseTypeKeyword,
2029 parseEnumKeyword,
2030 parseFunctionKeyword,
2031 parseClassKeyword,
2032 parseNamespaceKeyword,
2033 parseVarKeyword,
2034 parseLetKeyword,
2035 parseConstKeyword,
2036 parseAt,
2037 NULL);
2039 switch (token->type)
2041 case TOKEN_KEYWORD:
2042 switch (token->keyword)
2044 case KEYWORD_interface:
2045 parseInterface (CORK_NIL, token);
2046 break;
2047 case KEYWORD_type:
2048 parseType (CORK_NIL, token);
2049 break;
2050 case KEYWORD_enum:
2051 parseEnum (CORK_NIL, token);
2052 break;
2053 case KEYWORD_function:
2054 parseFunction (CORK_NIL, token);
2055 break;
2056 case KEYWORD_class:
2057 parseClass (CORK_NIL, token);
2058 break;
2059 case KEYWORD_namespace:
2060 parseNamespace (token);
2061 break;
2062 case KEYWORD_var:
2063 case KEYWORD_let:
2064 parseVariable (false, false, CORK_NIL, token);
2065 break;
2066 case KEYWORD_const:
2067 parseVariable (true, false, CORK_NIL, token);
2068 break;
2070 break;
2071 case TOKEN_AT:
2072 uwiUngetC ('@');
2073 parseDecorator (token);
2074 break;
2075 default:
2076 break;
2078 } while (parsed);
2081 static void findTsTags (void)
2083 uwiActivate (256);
2085 tokenInfo *const token = newToken ();
2087 parseTsFile (token);
2089 deleteToken (token);
2091 uwiDeactivate (&tsUwiStats);
2094 static void initialize (const langType language)
2096 Lang_ts = language;
2098 TokenPool = objPoolNew (16, newPoolToken, deletePoolToken, clearPoolToken, NULL);
2101 static void finalize (langType language CTAGS_ATTR_UNUSED, bool initialized)
2103 if (! initialized) return;
2105 objPoolDelete (TokenPool);
2108 static void initStats (langType language CTAGS_ATTR_UNUSED)
2110 uwiStatsInit (&tsUwiStats);
2112 static void printStats (langType language CTAGS_ATTR_UNUSED)
2114 uwiStatsPrint (&tsUwiStats);
2117 /* Create parser definition structure */
2118 extern parserDefinition *TypeScriptParser (void)
2120 static const char *const extensions [] = { "ts", NULL };
2121 parserDefinition *const def = parserNew ("TypeScript");
2122 def->extensions = extensions;
2123 def->kindTable = TsKinds;
2124 def->kindCount = ARRAY_SIZE (TsKinds);
2125 def->parser = findTsTags;
2126 def->initialize = initialize;
2127 def->finalize = finalize;
2128 def->keywordTable = TsKeywordTable;
2129 def->keywordCount = ARRAY_SIZE (TsKeywordTable);
2130 def->useCork = CORK_QUEUE;
2131 def->requestAutomaticFQTag = true;
2133 def->initStats = initStats;
2134 def->printStats = printStats;
2136 return def;