13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2000-2003, Darren Hiebert
32ff1f9d2SColomban Wendling * Copyright (c) 2014-2016, Colomban Wendling <ban@herbesfolles.org>
43ae02089SMasatake YAMATO *
53ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
60ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
73ae02089SMasatake YAMATO *
83ae02089SMasatake YAMATO * This module contains functions for generating tags for Python language
93ae02089SMasatake YAMATO * files.
103ae02089SMasatake YAMATO */
112ff1f9d2SColomban Wendling
123ae02089SMasatake YAMATO #include "general.h" /* must always come first */
133ae02089SMasatake YAMATO
143ae02089SMasatake YAMATO #include <string.h>
153ae02089SMasatake YAMATO
163ae02089SMasatake YAMATO #include "entry.h"
1791ccf7d7SFrank Fesevur #include "nestlevel.h"
183ae02089SMasatake YAMATO #include "read.h"
192ff1f9d2SColomban Wendling #include "parse.h"
203ae02089SMasatake YAMATO #include "vstring.h"
212ff1f9d2SColomban Wendling #include "keyword.h"
223ae02089SMasatake YAMATO #include "routines.h"
233ae02089SMasatake YAMATO #include "debug.h"
24f5f8bd9aSMasatake YAMATO #include "xtag.h"
25d3bb2b5aSJiří Techet #include "objpool.h"
2634454f72SMasatake YAMATO #include "ptrarray.h"
273ae02089SMasatake YAMATO
28670267e5SJiří Techet #define isIdentifierChar(c) \
29670267e5SJiří Techet (isalnum (c) || (c) == '_' || (c) >= 0x80)
306ff4799bSJiří Techet #define newToken() (objPoolGet (TokenPool))
316ff4799bSJiří Techet #define deleteToken(t) (objPoolPut (TokenPool, (t)))
32090afdd9SMasatake YAMATO
334faa2076SColomban Wendling enum {
342ff1f9d2SColomban Wendling KEYWORD_as,
3516845a4eSColomban Wendling KEYWORD_async,
362ff1f9d2SColomban Wendling KEYWORD_cdef,
372ff1f9d2SColomban Wendling KEYWORD_class,
382ff1f9d2SColomban Wendling KEYWORD_cpdef,
392ff1f9d2SColomban Wendling KEYWORD_def,
402ff1f9d2SColomban Wendling KEYWORD_extern,
412ff1f9d2SColomban Wendling KEYWORD_from,
422ff1f9d2SColomban Wendling KEYWORD_import,
432ff1f9d2SColomban Wendling KEYWORD_inline,
442ff1f9d2SColomban Wendling KEYWORD_lambda,
452ff1f9d2SColomban Wendling KEYWORD_pass,
462ff1f9d2SColomban Wendling KEYWORD_return,
474faa2076SColomban Wendling };
484faa2076SColomban Wendling typedef int keywordId; /* to allow KEYWORD_NONE */
492ff1f9d2SColomban Wendling
502ff1f9d2SColomban Wendling typedef enum {
512ff1f9d2SColomban Wendling ACCESS_PRIVATE,
522ff1f9d2SColomban Wendling ACCESS_PROTECTED,
532ff1f9d2SColomban Wendling ACCESS_PUBLIC,
542ff1f9d2SColomban Wendling COUNT_ACCESS
552ff1f9d2SColomban Wendling } accessType;
562ff1f9d2SColomban Wendling
572ff1f9d2SColomban Wendling static const char *const PythonAccesses[COUNT_ACCESS] = {
582ff1f9d2SColomban Wendling "private",
592ff1f9d2SColomban Wendling "protected",
602ff1f9d2SColomban Wendling "public"
612ff1f9d2SColomban Wendling };
622ff1f9d2SColomban Wendling
632ff1f9d2SColomban Wendling typedef enum {
645d0fd5feSColomban Wendling F_DECORATORS,
656f605b92SMasatake YAMATO F_NAMEREF,
665d0fd5feSColomban Wendling COUNT_FIELD
675d0fd5feSColomban Wendling } pythonField;
685d0fd5feSColomban Wendling
69b56bd065SMasatake YAMATO static fieldDefinition PythonFields[COUNT_FIELD] = {
705d0fd5feSColomban Wendling { .name = "decorators",
715d0fd5feSColomban Wendling .description = "decorators on functions and classes",
72ce990805SThomas Braun .enabled = false },
736f605b92SMasatake YAMATO { .name = "nameref",
746f605b92SMasatake YAMATO .description = "the original name for the tag",
756f605b92SMasatake YAMATO .enabled = true },
765d0fd5feSColomban Wendling };
775d0fd5feSColomban Wendling
785d0fd5feSColomban Wendling typedef enum {
792ff1f9d2SColomban Wendling K_CLASS,
802ff1f9d2SColomban Wendling K_FUNCTION,
812ff1f9d2SColomban Wendling K_METHOD,
822ff1f9d2SColomban Wendling K_VARIABLE,
832ff1f9d2SColomban Wendling K_NAMESPACE,
842ff1f9d2SColomban Wendling K_MODULE,
852ff1f9d2SColomban Wendling K_UNKNOWN,
86257674afSColomban Wendling K_PARAMETER,
8798a8ebe8SColomban Wendling K_LOCAL_VARIABLE,
882ff1f9d2SColomban Wendling COUNT_KIND
893ae02089SMasatake YAMATO } pythonKind;
903ae02089SMasatake YAMATO
91f5f8bd9aSMasatake YAMATO typedef enum {
92f5f8bd9aSMasatake YAMATO PYTHON_MODULE_IMPORTED,
93f5f8bd9aSMasatake YAMATO PYTHON_MODULE_NAMESPACE,
94f5f8bd9aSMasatake YAMATO PYTHON_MODULE_INDIRECTLY_IMPORTED,
95f5f8bd9aSMasatake YAMATO } pythonModuleRole;
96f5f8bd9aSMasatake YAMATO
97f5f8bd9aSMasatake YAMATO typedef enum {
98f5f8bd9aSMasatake YAMATO PYTHON_UNKNOWN_IMPORTED,
99f5f8bd9aSMasatake YAMATO PYTHON_UNKNOWN_INDIRECTLY_IMPORTED,
100f5f8bd9aSMasatake YAMATO } pythonUnknownRole;
101f5f8bd9aSMasatake YAMATO
1022ff1f9d2SColomban Wendling /* Roles related to `import'
103f5f8bd9aSMasatake YAMATO * ==========================
104f5f8bd9aSMasatake YAMATO * import X X = (kind:module, role:imported)
105f5f8bd9aSMasatake YAMATO *
106a25c30ffSMasatake YAMATO * import X as Y X = (kind:module, role:indirectlyImported),
1076f605b92SMasatake YAMATO * Y = (kind:namespace, nameref:module:X)
108f5f8bd9aSMasatake YAMATO * ------------------------------------------------
1096f605b92SMasatake YAMATO * Don't confuse the kind of Y with namespace role of module kind.
110f5f8bd9aSMasatake YAMATO *
111f5f8bd9aSMasatake YAMATO * from X import * X = (kind:module, role:namespace)
112f5f8bd9aSMasatake YAMATO *
113f5f8bd9aSMasatake YAMATO * from X import Y X = (kind:module, role:namespace),
11472ab2762SMasatake YAMATO * Y = (kind:unknown, role:imported, scope:module:X)
115f5f8bd9aSMasatake YAMATO *
116f5f8bd9aSMasatake YAMATO * from X import Y as Z X = (kind:module, role:namespace),
11772ab2762SMasatake YAMATO * Y = (kind:unknown, role:indirectlyImported, scope:module:X)
1186f605b92SMasatake YAMATO * Z = (kind:unknown, nameref:unknown:Y) */
119f5f8bd9aSMasatake YAMATO
12013457258SMasatake YAMATO static roleDefinition PythonModuleRoles [] = {
121ce990805SThomas Braun { true, "imported",
122f5f8bd9aSMasatake YAMATO "imported modules" },
123ce990805SThomas Braun { true, "namespace",
124f5f8bd9aSMasatake YAMATO "namespace from where classes/variables/functions are imported" },
125a25c30ffSMasatake YAMATO { true, "indirectlyImported",
126f5f8bd9aSMasatake YAMATO "module imported in alternative name" },
127f5f8bd9aSMasatake YAMATO };
128f5f8bd9aSMasatake YAMATO
12913457258SMasatake YAMATO static roleDefinition PythonUnknownRoles [] = {
130ce990805SThomas Braun { true, "imported", "imported from the other module" },
131a25c30ffSMasatake YAMATO { true, "indirectlyImported",
1326dea6ba7SMasatake YAMATO "classes/variables/functions/modules imported in alternative name" },
133f5f8bd9aSMasatake YAMATO };
134f5f8bd9aSMasatake YAMATO
135e112e8abSMasatake YAMATO static kindDefinition PythonKinds[COUNT_KIND] = {
136ce990805SThomas Braun {true, 'c', "class", "classes"},
137ce990805SThomas Braun {true, 'f', "function", "functions"},
138ce990805SThomas Braun {true, 'm', "member", "class members"},
139ce990805SThomas Braun {true, 'v', "variable", "variables"},
140ce990805SThomas Braun {true, 'I', "namespace", "name referring a module defined in other file"},
141ce990805SThomas Braun {true, 'i', "module", "modules",
142ce990805SThomas Braun .referenceOnly = true, ATTACH_ROLES(PythonModuleRoles)},
143ce990805SThomas Braun {true, 'x', "unknown", "name referring a class/variable/function/module defined in other module",
144ce990805SThomas Braun .referenceOnly = false, ATTACH_ROLES(PythonUnknownRoles)},
145ce990805SThomas Braun {false, 'z', "parameter", "function parameters" },
146ce990805SThomas Braun {false, 'l', "local", "local variables" },
1473ae02089SMasatake YAMATO };
1483ae02089SMasatake YAMATO
149b0470ee9SMasatake YAMATO static const keywordTable PythonKeywordTable[] = {
1502ff1f9d2SColomban Wendling /* keyword keyword ID */
1512ff1f9d2SColomban Wendling { "as", KEYWORD_as },
15216845a4eSColomban Wendling { "async", KEYWORD_async },
1532ff1f9d2SColomban Wendling { "cdef", KEYWORD_cdef },
1542ff1f9d2SColomban Wendling { "cimport", KEYWORD_import },
1552ff1f9d2SColomban Wendling { "class", KEYWORD_class },
1562ff1f9d2SColomban Wendling { "cpdef", KEYWORD_cpdef },
1572ff1f9d2SColomban Wendling { "def", KEYWORD_def },
1582ff1f9d2SColomban Wendling { "extern", KEYWORD_extern },
1592ff1f9d2SColomban Wendling { "from", KEYWORD_from },
1602ff1f9d2SColomban Wendling { "import", KEYWORD_import },
1612ff1f9d2SColomban Wendling { "inline", KEYWORD_inline },
1622ff1f9d2SColomban Wendling { "lambda", KEYWORD_lambda },
1632ff1f9d2SColomban Wendling { "pass", KEYWORD_pass },
1642ff1f9d2SColomban Wendling { "return", KEYWORD_return },
1653ae02089SMasatake YAMATO };
1663ae02089SMasatake YAMATO
1672ff1f9d2SColomban Wendling typedef enum eTokenType {
1682ff1f9d2SColomban Wendling /* 0..255 are the byte's value */
1692ff1f9d2SColomban Wendling TOKEN_EOF = 256,
1702ff1f9d2SColomban Wendling TOKEN_UNDEFINED,
1712ff1f9d2SColomban Wendling TOKEN_INDENT,
1722ff1f9d2SColomban Wendling TOKEN_KEYWORD,
1732ff1f9d2SColomban Wendling TOKEN_OPERATOR,
1742ff1f9d2SColomban Wendling TOKEN_IDENTIFIER,
1752ff1f9d2SColomban Wendling TOKEN_STRING,
176c378e8b6SMasatake YAMATO TOKEN_ARROW, /* -> */
1772ff1f9d2SColomban Wendling TOKEN_WHITESPACE,
1782ff1f9d2SColomban Wendling } tokenType;
1796c11b8afSMasatake YAMATO
1802ff1f9d2SColomban Wendling typedef struct {
1812ff1f9d2SColomban Wendling int type;
1822ff1f9d2SColomban Wendling keywordId keyword;
1832ff1f9d2SColomban Wendling vString * string;
1842ff1f9d2SColomban Wendling int indent;
1852ff1f9d2SColomban Wendling unsigned long lineNumber;
1862ff1f9d2SColomban Wendling MIOPos filePosition;
1872ff1f9d2SColomban Wendling } tokenInfo;
1882ff1f9d2SColomban Wendling
1892ff1f9d2SColomban Wendling struct pythonNestingLevelUserData {
1902ff1f9d2SColomban Wendling int indentation;
1916c11b8afSMasatake YAMATO };
1922ff1f9d2SColomban Wendling #define PY_NL(nl) ((struct pythonNestingLevelUserData *) nestingLevelGetUserData (nl))
1936c11b8afSMasatake YAMATO
1942ff1f9d2SColomban Wendling static langType Lang_python;
1952ff1f9d2SColomban Wendling static unsigned int TokenContinuationDepth = 0;
1962ff1f9d2SColomban Wendling static tokenInfo *NextToken = NULL;
1972ff1f9d2SColomban Wendling static NestingLevels *PythonNestingLevels = NULL;
198d3bb2b5aSJiří Techet static objPool *TokenPool = NULL;
1993ae02089SMasatake YAMATO
2003ae02089SMasatake YAMATO
2013ae02089SMasatake YAMATO /* follows PEP-8, and always reports single-underscores as protected
2023ae02089SMasatake YAMATO * See:
2033ae02089SMasatake YAMATO * - http://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables
2043ae02089SMasatake YAMATO * - http://www.python.org/dev/peps/pep-0008/#designing-for-inheritance
2053ae02089SMasatake YAMATO */
accessFromIdentifier(const vString * const ident,pythonKind kind,int parentKind)2062ff1f9d2SColomban Wendling static accessType accessFromIdentifier (const vString *const ident,
2072ff1f9d2SColomban Wendling pythonKind kind, int parentKind)
2083ae02089SMasatake YAMATO {
2093ae02089SMasatake YAMATO const char *const p = vStringValue (ident);
2103ae02089SMasatake YAMATO const size_t len = vStringLength (ident);
2113ae02089SMasatake YAMATO
2123ae02089SMasatake YAMATO /* inside a function/method, private */
2132ff1f9d2SColomban Wendling if (parentKind != -1 && parentKind != K_CLASS)
2142ff1f9d2SColomban Wendling return ACCESS_PRIVATE;
2153ae02089SMasatake YAMATO /* not starting with "_", public */
2163ae02089SMasatake YAMATO else if (len < 1 || p[0] != '_')
2172ff1f9d2SColomban Wendling return ACCESS_PUBLIC;
2183ae02089SMasatake YAMATO /* "__...__": magic methods */
2192ff1f9d2SColomban Wendling else if (kind == K_FUNCTION && parentKind == K_CLASS &&
2203ae02089SMasatake YAMATO len > 3 && p[1] == '_' && p[len - 2] == '_' && p[len - 1] == '_')
2212ff1f9d2SColomban Wendling return ACCESS_PUBLIC;
2223ae02089SMasatake YAMATO /* "__...": name mangling */
2232ff1f9d2SColomban Wendling else if (parentKind == K_CLASS && len > 1 && p[1] == '_')
2242ff1f9d2SColomban Wendling return ACCESS_PRIVATE;
2253ae02089SMasatake YAMATO /* "_...": suggested as non-public, but easily accessible */
2263ae02089SMasatake YAMATO else
2272ff1f9d2SColomban Wendling return ACCESS_PROTECTED;
2283ae02089SMasatake YAMATO }
2293ae02089SMasatake YAMATO
initPythonEntry(tagEntryInfo * const e,const tokenInfo * const token,const pythonKind kind)2302ff1f9d2SColomban Wendling static void initPythonEntry (tagEntryInfo *const e, const tokenInfo *const token,
2312ff1f9d2SColomban Wendling const pythonKind kind)
2323ae02089SMasatake YAMATO {
2332ff1f9d2SColomban Wendling accessType access;
2342ff1f9d2SColomban Wendling int parentKind = -1;
2352ff1f9d2SColomban Wendling NestingLevel *nl;
2363ae02089SMasatake YAMATO
23716a2541cSMasatake YAMATO initTagEntry (e, vStringValue (token->string), kind);
2382ff1f9d2SColomban Wendling
2392ff1f9d2SColomban Wendling e->lineNumber = token->lineNumber;
2402ff1f9d2SColomban Wendling e->filePosition = token->filePosition;
2412ff1f9d2SColomban Wendling
2422ff1f9d2SColomban Wendling nl = nestingLevelsGetCurrent (PythonNestingLevels);
2432ff1f9d2SColomban Wendling if (nl)
2442ff1f9d2SColomban Wendling {
2452ff1f9d2SColomban Wendling tagEntryInfo *nlEntry = getEntryOfNestingLevel (nl);
2462ff1f9d2SColomban Wendling
2472ff1f9d2SColomban Wendling e->extensionFields.scopeIndex = nl->corkIndex;
2482ff1f9d2SColomban Wendling
2492ff1f9d2SColomban Wendling /* nlEntry can be NULL if a kind was disabled. But what can we do
2502ff1f9d2SColomban Wendling * here? Even disabled kinds should count for the hierarchy I
2512ff1f9d2SColomban Wendling * guess -- as it'd otherwise be wrong -- but with cork we're
2522ff1f9d2SColomban Wendling * fucked up as there's nothing to look up. Damn. */
2532ff1f9d2SColomban Wendling if (nlEntry)
2542ff1f9d2SColomban Wendling {
255f92e6bf2SMasatake YAMATO parentKind = nlEntry->kindIndex;
2562ff1f9d2SColomban Wendling
2572ff1f9d2SColomban Wendling /* functions directly inside classes are methods, fix it up */
2582ff1f9d2SColomban Wendling if (kind == K_FUNCTION && parentKind == K_CLASS)
259f92e6bf2SMasatake YAMATO e->kindIndex = K_METHOD;
2602ff1f9d2SColomban Wendling }
2612ff1f9d2SColomban Wendling }
2622ff1f9d2SColomban Wendling
2632ff1f9d2SColomban Wendling access = accessFromIdentifier (token->string, kind, parentKind);
2642ff1f9d2SColomban Wendling e->extensionFields.access = PythonAccesses[access];
2653ae02089SMasatake YAMATO /* FIXME: should we really set isFileScope in addition to access? */
2662ff1f9d2SColomban Wendling if (access == ACCESS_PRIVATE)
267ce990805SThomas Braun e->isFileScope = true;
2683ae02089SMasatake YAMATO }
2693ae02089SMasatake YAMATO
makeClassTag(const tokenInfo * const token,const vString * const inheritance,const vString * const decorators)2702ff1f9d2SColomban Wendling static int makeClassTag (const tokenInfo *const token,
2715d0fd5feSColomban Wendling const vString *const inheritance,
2725d0fd5feSColomban Wendling const vString *const decorators)
2733ae02089SMasatake YAMATO {
2742ff1f9d2SColomban Wendling if (PythonKinds[K_CLASS].enabled)
2752ff1f9d2SColomban Wendling {
2762ff1f9d2SColomban Wendling tagEntryInfo e;
277956bd9a1SMasatake YAMATO
2782ff1f9d2SColomban Wendling initPythonEntry (&e, token, K_CLASS);
2792ff1f9d2SColomban Wendling
2802ff1f9d2SColomban Wendling e.extensionFields.inheritance = inheritance ? vStringValue (inheritance) : "";
2815d0fd5feSColomban Wendling if (decorators && vStringLength (decorators) > 0)
2825d0fd5feSColomban Wendling {
283aa4def17SMasatake YAMATO attachParserField (&e, false, PythonFields[F_DECORATORS].ftype,
2845d0fd5feSColomban Wendling vStringValue (decorators));
2855d0fd5feSColomban Wendling }
2862ff1f9d2SColomban Wendling
2872ff1f9d2SColomban Wendling return makeTagEntry (&e);
28802b93863SMasatake YAMATO }
2894a95e4a5SColomban Wendling
290885fbc2cSMasatake YAMATO return CORK_NIL;
2913ae02089SMasatake YAMATO }
2923ae02089SMasatake YAMATO
makeFunctionTag(const tokenInfo * const token,const vString * const arglist,const vString * const decorators)2932ff1f9d2SColomban Wendling static int makeFunctionTag (const tokenInfo *const token,
2945d0fd5feSColomban Wendling const vString *const arglist,
2955d0fd5feSColomban Wendling const vString *const decorators)
2963ae02089SMasatake YAMATO {
2972ff1f9d2SColomban Wendling if (PythonKinds[K_FUNCTION].enabled)
2983ae02089SMasatake YAMATO {
2992ff1f9d2SColomban Wendling tagEntryInfo e;
3002ff1f9d2SColomban Wendling
3012ff1f9d2SColomban Wendling initPythonEntry (&e, token, K_FUNCTION);
3022ff1f9d2SColomban Wendling
3032ff1f9d2SColomban Wendling if (arglist)
3042ff1f9d2SColomban Wendling e.extensionFields.signature = vStringValue (arglist);
3055d0fd5feSColomban Wendling if (decorators && vStringLength (decorators) > 0)
3065d0fd5feSColomban Wendling {
307aa4def17SMasatake YAMATO attachParserField (&e, false, PythonFields[F_DECORATORS].ftype,
3085d0fd5feSColomban Wendling vStringValue (decorators));
3095d0fd5feSColomban Wendling }
3102ff1f9d2SColomban Wendling
3112ff1f9d2SColomban Wendling return makeTagEntry (&e);
3123ae02089SMasatake YAMATO }
3132ff1f9d2SColomban Wendling
3142ff1f9d2SColomban Wendling return CORK_NIL;
3152ff1f9d2SColomban Wendling }
3162ff1f9d2SColomban Wendling
makeSimplePythonTag(const tokenInfo * const token,pythonKind const kind)3172ff1f9d2SColomban Wendling static int makeSimplePythonTag (const tokenInfo *const token, pythonKind const kind)
3182ff1f9d2SColomban Wendling {
3192ff1f9d2SColomban Wendling if (PythonKinds[kind].enabled)
3202ff1f9d2SColomban Wendling {
3212ff1f9d2SColomban Wendling tagEntryInfo e;
3222ff1f9d2SColomban Wendling
3232ff1f9d2SColomban Wendling initPythonEntry (&e, token, kind);
3242ff1f9d2SColomban Wendling return makeTagEntry (&e);
3252ff1f9d2SColomban Wendling }
3262ff1f9d2SColomban Wendling
3272ff1f9d2SColomban Wendling return CORK_NIL;
3282ff1f9d2SColomban Wendling }
3292ff1f9d2SColomban Wendling
makeSimplePythonRefTag(const tokenInfo * const token,const vString * const altName,pythonKind const kind,int roleIndex,xtagType xtag)3302ff1f9d2SColomban Wendling static int makeSimplePythonRefTag (const tokenInfo *const token,
3312ff1f9d2SColomban Wendling const vString *const altName,
3322ff1f9d2SColomban Wendling pythonKind const kind,
3332ff1f9d2SColomban Wendling int roleIndex, xtagType xtag)
3342ff1f9d2SColomban Wendling {
335102b735bSColomban Wendling if (isXtagEnabled (XTAG_REFERENCE_TAGS) &&
336102b735bSColomban Wendling PythonKinds[kind].roles[roleIndex].enabled)
3372ff1f9d2SColomban Wendling {
3382ff1f9d2SColomban Wendling tagEntryInfo e;
3392ff1f9d2SColomban Wendling
3402ff1f9d2SColomban Wendling initRefTagEntry (&e, vStringValue (altName ? altName : token->string),
34116a2541cSMasatake YAMATO kind, roleIndex);
3422ff1f9d2SColomban Wendling
3432ff1f9d2SColomban Wendling e.lineNumber = token->lineNumber;
3442ff1f9d2SColomban Wendling e.filePosition = token->filePosition;
3452ff1f9d2SColomban Wendling
3462ff1f9d2SColomban Wendling if (xtag != XTAG_UNKNOWN)
3472ff1f9d2SColomban Wendling markTagExtraBit (&e, xtag);
3482ff1f9d2SColomban Wendling
3492ff1f9d2SColomban Wendling return makeTagEntry (&e);
3502ff1f9d2SColomban Wendling }
3512ff1f9d2SColomban Wendling
3522ff1f9d2SColomban Wendling return CORK_NIL;
3532ff1f9d2SColomban Wendling }
3542ff1f9d2SColomban Wendling
newPoolToken(void * createArg CTAGS_ATTR_UNUSED)355e013efc1SMasatake YAMATO static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
3562ff1f9d2SColomban Wendling {
3576ff4799bSJiří Techet tokenInfo *token = xMalloc (1, tokenInfo);
3582ff1f9d2SColomban Wendling token->string = vStringNew ();
3592ff1f9d2SColomban Wendling return token;
3602ff1f9d2SColomban Wendling }
3612ff1f9d2SColomban Wendling
deletePoolToken(void * data)3626ff4799bSJiří Techet static void deletePoolToken (void *data)
3632ff1f9d2SColomban Wendling {
3646ff4799bSJiří Techet tokenInfo *token = data;
3652ff1f9d2SColomban Wendling vStringDelete (token->string);
3662ff1f9d2SColomban Wendling eFree (token);
3672ff1f9d2SColomban Wendling }
3682ff1f9d2SColomban Wendling
clearPoolToken(void * data)3696ff4799bSJiří Techet static void clearPoolToken (void *data)
370d3bb2b5aSJiří Techet {
3716ff4799bSJiří Techet tokenInfo *token = data;
3726ff4799bSJiří Techet
373d3bb2b5aSJiří Techet token->type = TOKEN_UNDEFINED;
374d3bb2b5aSJiří Techet token->keyword = KEYWORD_NONE;
375d3bb2b5aSJiří Techet token->indent = 0;
376d3bb2b5aSJiří Techet token->lineNumber = getInputLineNumber ();
377d3bb2b5aSJiří Techet token->filePosition = getInputFilePosition ();
378d3bb2b5aSJiří Techet vStringClear (token->string);
379d3bb2b5aSJiří Techet }
380d3bb2b5aSJiří Techet
copyToken(tokenInfo * const dest,const tokenInfo * const src)3812ff1f9d2SColomban Wendling static void copyToken (tokenInfo *const dest, const tokenInfo *const src)
3822ff1f9d2SColomban Wendling {
3832ff1f9d2SColomban Wendling dest->lineNumber = src->lineNumber;
3842ff1f9d2SColomban Wendling dest->filePosition = src->filePosition;
3852ff1f9d2SColomban Wendling dest->type = src->type;
3862ff1f9d2SColomban Wendling dest->keyword = src->keyword;
3872ff1f9d2SColomban Wendling dest->indent = src->indent;
3882ff1f9d2SColomban Wendling vStringCopy(dest->string, src->string);
3892ff1f9d2SColomban Wendling }
3902ff1f9d2SColomban Wendling
3913ae02089SMasatake YAMATO /* Skip a single or double quoted string. */
readString(vString * const string,const int delimiter)3922ff1f9d2SColomban Wendling static void readString (vString *const string, const int delimiter)
3933ae02089SMasatake YAMATO {
3943ae02089SMasatake YAMATO int escaped = 0;
3952ff1f9d2SColomban Wendling int c;
3962ff1f9d2SColomban Wendling
3972ff1f9d2SColomban Wendling while ((c = getcFromInputFile ()) != EOF)
3983ae02089SMasatake YAMATO {
3993ae02089SMasatake YAMATO if (escaped)
4002ff1f9d2SColomban Wendling {
4012ff1f9d2SColomban Wendling vStringPut (string, c);
4023ae02089SMasatake YAMATO escaped--;
4032ff1f9d2SColomban Wendling }
4042ff1f9d2SColomban Wendling else if (c == '\\')
4053ae02089SMasatake YAMATO escaped++;
4062ff1f9d2SColomban Wendling else if (c == delimiter || c == '\n' || c == '\r')
407f4b83e63SMasatake YAMATO {
4082ff1f9d2SColomban Wendling if (c != delimiter)
4092ff1f9d2SColomban Wendling ungetcToInputFile (c);
4102ff1f9d2SColomban Wendling break;
4112ff1f9d2SColomban Wendling }
412f4b83e63SMasatake YAMATO else
4132ff1f9d2SColomban Wendling vStringPut (string, c);
4142ff1f9d2SColomban Wendling }
415f4b83e63SMasatake YAMATO }
416f4b83e63SMasatake YAMATO
4172ff1f9d2SColomban Wendling /* Skip a single or double triple quoted string. */
readTripleString(vString * const string,const int delimiter)4182ff1f9d2SColomban Wendling static void readTripleString (vString *const string, const int delimiter)
4193ae02089SMasatake YAMATO {
4202ff1f9d2SColomban Wendling int c;
4212ff1f9d2SColomban Wendling int escaped = 0;
4222ff1f9d2SColomban Wendling int n = 0;
4232ff1f9d2SColomban Wendling while ((c = getcFromInputFile ()) != EOF)
4243ae02089SMasatake YAMATO {
4252ff1f9d2SColomban Wendling if (c == delimiter && ! escaped)
426f822ba44SMasatake YAMATO {
4272ff1f9d2SColomban Wendling if (++n >= 3)
4282ff1f9d2SColomban Wendling break;
429f822ba44SMasatake YAMATO }
4302ff1f9d2SColomban Wendling else
4312ff1f9d2SColomban Wendling {
4322ff1f9d2SColomban Wendling for (; n > 0; n--)
4332ff1f9d2SColomban Wendling vStringPut (string, delimiter);
4342ff1f9d2SColomban Wendling if (c != '\\' || escaped)
4352ff1f9d2SColomban Wendling vStringPut (string, c);
4362ff1f9d2SColomban Wendling n = 0;
437f822ba44SMasatake YAMATO }
4383ae02089SMasatake YAMATO
4392ff1f9d2SColomban Wendling if (escaped)
4402ff1f9d2SColomban Wendling escaped--;
4412ff1f9d2SColomban Wendling else if (c == '\\')
4422ff1f9d2SColomban Wendling escaped++;
4433ae02089SMasatake YAMATO }
44498e25217SJiří Techet }
4453ae02089SMasatake YAMATO
readIdentifier(vString * const string,const int firstChar)4462ff1f9d2SColomban Wendling static void readIdentifier (vString *const string, const int firstChar)
447cae0f365SMasatake YAMATO {
4482ff1f9d2SColomban Wendling int c = firstChar;
4492ff1f9d2SColomban Wendling do
4502ff1f9d2SColomban Wendling {
4512ff1f9d2SColomban Wendling vStringPut (string, (char) c);
4522ff1f9d2SColomban Wendling c = getcFromInputFile ();
4532ff1f9d2SColomban Wendling }
4542ff1f9d2SColomban Wendling while (isIdentifierChar (c));
4552ff1f9d2SColomban Wendling ungetcToInputFile (c);
456cae0f365SMasatake YAMATO }
457cae0f365SMasatake YAMATO
ungetToken(tokenInfo * const token)4582ff1f9d2SColomban Wendling static void ungetToken (tokenInfo *const token)
4597f34b31fSMasatake YAMATO {
4602ff1f9d2SColomban Wendling Assert (NextToken == NULL);
4616ff4799bSJiří Techet NextToken = newToken ();
4622ff1f9d2SColomban Wendling copyToken (NextToken, token);
4637f34b31fSMasatake YAMATO }
4647f34b31fSMasatake YAMATO
readTokenFull(tokenInfo * const token,bool inclWhitespaces)465ce990805SThomas Braun static void readTokenFull (tokenInfo *const token, bool inclWhitespaces)
4663ae02089SMasatake YAMATO {
4672ff1f9d2SColomban Wendling int c;
4682ff1f9d2SColomban Wendling int n;
4692ff1f9d2SColomban Wendling
4702ff1f9d2SColomban Wendling /* if we've got a token held back, emit it */
4712ff1f9d2SColomban Wendling if (NextToken)
4722ff1f9d2SColomban Wendling {
4732ff1f9d2SColomban Wendling copyToken (token, NextToken);
4746ff4799bSJiří Techet deleteToken (NextToken);
4752ff1f9d2SColomban Wendling NextToken = NULL;
4762ff1f9d2SColomban Wendling return;
4773ae02089SMasatake YAMATO }
4783ae02089SMasatake YAMATO
4792ff1f9d2SColomban Wendling token->type = TOKEN_UNDEFINED;
4802ff1f9d2SColomban Wendling token->keyword = KEYWORD_NONE;
4812ff1f9d2SColomban Wendling vStringClear (token->string);
4822ff1f9d2SColomban Wendling
4832ff1f9d2SColomban Wendling getNextChar:
4842ff1f9d2SColomban Wendling
4852ff1f9d2SColomban Wendling n = 0;
4862ff1f9d2SColomban Wendling do
4873ae02089SMasatake YAMATO {
4882ff1f9d2SColomban Wendling c = getcFromInputFile ();
4892ff1f9d2SColomban Wendling n++;
4903ae02089SMasatake YAMATO }
4912ff1f9d2SColomban Wendling while (c == ' ' || c == '\t' || c == '\f');
4922ff1f9d2SColomban Wendling
4934340e862SColomban Wendling token->lineNumber = getInputLineNumber ();
4942ff1f9d2SColomban Wendling token->filePosition = getInputFilePosition ();
4952ff1f9d2SColomban Wendling
4962ff1f9d2SColomban Wendling if (inclWhitespaces && n > 1 && c != '\r' && c != '\n')
4972ff1f9d2SColomban Wendling {
4982ff1f9d2SColomban Wendling ungetcToInputFile (c);
4992ff1f9d2SColomban Wendling vStringPut (token->string, ' ');
5002ff1f9d2SColomban Wendling token->type = TOKEN_WHITESPACE;
5012ff1f9d2SColomban Wendling return;
5023ae02089SMasatake YAMATO }
5033ae02089SMasatake YAMATO
5042ff1f9d2SColomban Wendling switch (c)
5053ae02089SMasatake YAMATO {
5062ff1f9d2SColomban Wendling case EOF:
5072ff1f9d2SColomban Wendling token->type = TOKEN_EOF;
5082ff1f9d2SColomban Wendling break;
5092ff1f9d2SColomban Wendling
5102ff1f9d2SColomban Wendling case '\'':
5112ff1f9d2SColomban Wendling case '"':
5122ff1f9d2SColomban Wendling {
5132ff1f9d2SColomban Wendling int d = getcFromInputFile ();
5142ff1f9d2SColomban Wendling token->type = TOKEN_STRING;
5152ff1f9d2SColomban Wendling vStringPut (token->string, c);
5162ff1f9d2SColomban Wendling if (d != c)
5172ff1f9d2SColomban Wendling {
5182ff1f9d2SColomban Wendling ungetcToInputFile (d);
5192ff1f9d2SColomban Wendling readString (token->string, c);
5202ff1f9d2SColomban Wendling }
5212ff1f9d2SColomban Wendling else if ((d = getcFromInputFile ()) == c)
5222ff1f9d2SColomban Wendling readTripleString (token->string, c);
5232ff1f9d2SColomban Wendling else /* empty string */
5242ff1f9d2SColomban Wendling ungetcToInputFile (d);
5252ff1f9d2SColomban Wendling vStringPut (token->string, c);
5264340e862SColomban Wendling token->lineNumber = getInputLineNumber ();
5272ff1f9d2SColomban Wendling token->filePosition = getInputFilePosition ();
5282ff1f9d2SColomban Wendling break;
5293ae02089SMasatake YAMATO }
5303ae02089SMasatake YAMATO
5312ff1f9d2SColomban Wendling case '=':
5323ae02089SMasatake YAMATO {
5332ff1f9d2SColomban Wendling int d = getcFromInputFile ();
5342ff1f9d2SColomban Wendling vStringPut (token->string, c);
5352ff1f9d2SColomban Wendling if (d == c)
5363ae02089SMasatake YAMATO {
5372ff1f9d2SColomban Wendling vStringPut (token->string, d);
5382ff1f9d2SColomban Wendling token->type = TOKEN_OPERATOR;
5393ae02089SMasatake YAMATO }
5402ff1f9d2SColomban Wendling else
5412ff1f9d2SColomban Wendling {
5422ff1f9d2SColomban Wendling ungetcToInputFile (d);
5432ff1f9d2SColomban Wendling token->type = c;
5442ff1f9d2SColomban Wendling }
5452ff1f9d2SColomban Wendling break;
5463ae02089SMasatake YAMATO }
5473ae02089SMasatake YAMATO
5482ff1f9d2SColomban Wendling case '-':
549c378e8b6SMasatake YAMATO {
550c378e8b6SMasatake YAMATO int d = getcFromInputFile ();
551c378e8b6SMasatake YAMATO if (d == '>')
552c378e8b6SMasatake YAMATO {
553c378e8b6SMasatake YAMATO vStringPut (token->string, c);
554c378e8b6SMasatake YAMATO vStringPut (token->string, d);
555c378e8b6SMasatake YAMATO token->type = TOKEN_ARROW;
556c378e8b6SMasatake YAMATO break;
557c378e8b6SMasatake YAMATO }
558c378e8b6SMasatake YAMATO ungetcToInputFile (d);
559c378e8b6SMasatake YAMATO /* fall through */
560c378e8b6SMasatake YAMATO }
561c378e8b6SMasatake YAMATO case '+':
5622ff1f9d2SColomban Wendling case '*':
5632ff1f9d2SColomban Wendling case '%':
5642ff1f9d2SColomban Wendling case '<':
5652ff1f9d2SColomban Wendling case '>':
5662ff1f9d2SColomban Wendling case '/':
5677f34b31fSMasatake YAMATO {
5682ff1f9d2SColomban Wendling int d = getcFromInputFile ();
5692ff1f9d2SColomban Wendling vStringPut (token->string, c);
5702ff1f9d2SColomban Wendling if (d != '=')
571f34b6795SColomban Wendling {
5722ff1f9d2SColomban Wendling ungetcToInputFile (d);
573f34b6795SColomban Wendling token->type = c;
574f34b6795SColomban Wendling }
5752ff1f9d2SColomban Wendling else
576f34b6795SColomban Wendling {
5772ff1f9d2SColomban Wendling vStringPut (token->string, d);
5782ff1f9d2SColomban Wendling token->type = TOKEN_OPERATOR;
579f34b6795SColomban Wendling }
5802ff1f9d2SColomban Wendling break;
5817f34b31fSMasatake YAMATO }
5827f34b31fSMasatake YAMATO
5832ff1f9d2SColomban Wendling /* eats newline to implement line continuation */
5842ff1f9d2SColomban Wendling case '\\':
5853ae02089SMasatake YAMATO {
5862ff1f9d2SColomban Wendling int d = getcFromInputFile ();
5872ff1f9d2SColomban Wendling if (d == '\r')
5882ff1f9d2SColomban Wendling d = getcFromInputFile ();
5892ff1f9d2SColomban Wendling if (d != '\n')
5902ff1f9d2SColomban Wendling ungetcToInputFile (d);
5912ff1f9d2SColomban Wendling goto getNextChar;
5922ff1f9d2SColomban Wendling }
5932ff1f9d2SColomban Wendling
5942ff1f9d2SColomban Wendling case '#': /* comment */
5952ff1f9d2SColomban Wendling case '\r': /* newlines for indent */
5962ff1f9d2SColomban Wendling case '\n':
5970f13d82bSColomban Wendling {
5980f13d82bSColomban Wendling int indent = 0;
5992ff1f9d2SColomban Wendling do
6002ff1f9d2SColomban Wendling {
6012ff1f9d2SColomban Wendling if (c == '#')
6022ff1f9d2SColomban Wendling {
6032ff1f9d2SColomban Wendling do
6042ff1f9d2SColomban Wendling c = getcFromInputFile ();
6052ff1f9d2SColomban Wendling while (c != EOF && c != '\r' && c != '\n');
6062ff1f9d2SColomban Wendling }
6072ff1f9d2SColomban Wendling if (c == '\r')
6082ff1f9d2SColomban Wendling {
6092ff1f9d2SColomban Wendling int d = getcFromInputFile ();
6102ff1f9d2SColomban Wendling if (d != '\n')
6112ff1f9d2SColomban Wendling ungetcToInputFile (d);
6122ff1f9d2SColomban Wendling }
6130f13d82bSColomban Wendling indent = 0;
6142ff1f9d2SColomban Wendling while ((c = getcFromInputFile ()) == ' ' || c == '\t' || c == '\f')
6152ff1f9d2SColomban Wendling {
6162ff1f9d2SColomban Wendling if (c == '\t')
6170f13d82bSColomban Wendling indent += 8 - (indent % 8);
6182ff1f9d2SColomban Wendling else if (c == '\f') /* yeah, it's weird */
6190f13d82bSColomban Wendling indent = 0;
6202ff1f9d2SColomban Wendling else
6210f13d82bSColomban Wendling indent++;
6222ff1f9d2SColomban Wendling }
6232ff1f9d2SColomban Wendling } /* skip completely empty lines, so retry */
6242ff1f9d2SColomban Wendling while (c == '\r' || c == '\n' || c == '#');
6252ff1f9d2SColomban Wendling ungetcToInputFile (c);
6262ff1f9d2SColomban Wendling if (TokenContinuationDepth > 0)
6272ff1f9d2SColomban Wendling {
6282ff1f9d2SColomban Wendling if (inclWhitespaces)
6292ff1f9d2SColomban Wendling {
6302ff1f9d2SColomban Wendling vStringPut (token->string, ' ');
6312ff1f9d2SColomban Wendling token->type = TOKEN_WHITESPACE;
6322ff1f9d2SColomban Wendling }
6332ff1f9d2SColomban Wendling else
6342ff1f9d2SColomban Wendling goto getNextChar;
6352ff1f9d2SColomban Wendling }
6360f13d82bSColomban Wendling else
6370f13d82bSColomban Wendling {
6380f13d82bSColomban Wendling token->type = TOKEN_INDENT;
6390f13d82bSColomban Wendling token->indent = indent;
6400f13d82bSColomban Wendling }
6412ff1f9d2SColomban Wendling break;
6420f13d82bSColomban Wendling }
6432ff1f9d2SColomban Wendling
6442ff1f9d2SColomban Wendling default:
6452ff1f9d2SColomban Wendling if (! isIdentifierChar (c))
6462ff1f9d2SColomban Wendling {
6472ff1f9d2SColomban Wendling vStringPut (token->string, c);
6482ff1f9d2SColomban Wendling token->type = c;
6492ff1f9d2SColomban Wendling }
6502ff1f9d2SColomban Wendling else
6512ff1f9d2SColomban Wendling {
652c9fc4e04SColomban Wendling /* FIXME: handle U, B, R and F string prefixes? */
6532ff1f9d2SColomban Wendling readIdentifier (token->string, c);
6548f29d6c9SJiří Techet token->keyword = lookupKeyword (vStringValue (token->string), Lang_python);
6552ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_NONE)
6562ff1f9d2SColomban Wendling token->type = TOKEN_IDENTIFIER;
6572ff1f9d2SColomban Wendling else
6582ff1f9d2SColomban Wendling token->type = TOKEN_KEYWORD;
6592ff1f9d2SColomban Wendling }
6602ff1f9d2SColomban Wendling break;
6612ff1f9d2SColomban Wendling }
6622ff1f9d2SColomban Wendling
6632ff1f9d2SColomban Wendling /* handle implicit continuation lines not to emit INDENT inside brackets
6642ff1f9d2SColomban Wendling * https://docs.python.org/3.6/reference/lexical_analysis.html#implicit-line-joining */
6652ff1f9d2SColomban Wendling if (token->type == '(' ||
6662ff1f9d2SColomban Wendling token->type == '{' ||
6672ff1f9d2SColomban Wendling token->type == '[')
6682ff1f9d2SColomban Wendling {
6692ff1f9d2SColomban Wendling TokenContinuationDepth ++;
6702ff1f9d2SColomban Wendling }
6712ff1f9d2SColomban Wendling else if (TokenContinuationDepth > 0 &&
6722ff1f9d2SColomban Wendling (token->type == ')' ||
6732ff1f9d2SColomban Wendling token->type == '}' ||
6742ff1f9d2SColomban Wendling token->type == ']'))
6752ff1f9d2SColomban Wendling {
6762ff1f9d2SColomban Wendling TokenContinuationDepth --;
6772ff1f9d2SColomban Wendling }
6782ff1f9d2SColomban Wendling }
6792ff1f9d2SColomban Wendling
readToken(tokenInfo * const token)6802ff1f9d2SColomban Wendling static void readToken (tokenInfo *const token)
6812ff1f9d2SColomban Wendling {
682ce990805SThomas Braun readTokenFull (token, false);
6832ff1f9d2SColomban Wendling }
6842ff1f9d2SColomban Wendling
6852ff1f9d2SColomban Wendling /*================================= parsing =================================*/
6862ff1f9d2SColomban Wendling
6872ff1f9d2SColomban Wendling
reprCat(vString * const repr,const tokenInfo * const token)6882ff1f9d2SColomban Wendling static void reprCat (vString *const repr, const tokenInfo *const token)
6892ff1f9d2SColomban Wendling {
6902ff1f9d2SColomban Wendling if (token->type != TOKEN_INDENT &&
6912ff1f9d2SColomban Wendling token->type != TOKEN_WHITESPACE)
6922ff1f9d2SColomban Wendling {
6932ff1f9d2SColomban Wendling vStringCat (repr, token->string);
6942ff1f9d2SColomban Wendling }
6952ff1f9d2SColomban Wendling else if (vStringLength (repr) > 0 && vStringLast (repr) != ' ')
6962ff1f9d2SColomban Wendling {
6972ff1f9d2SColomban Wendling vStringPut (repr, ' ');
6982ff1f9d2SColomban Wendling }
6992ff1f9d2SColomban Wendling }
7002ff1f9d2SColomban Wendling
skipOverPair(tokenInfo * const token,int tOpen,int tClose,vString * const repr,bool reprOuterPair)701ce990805SThomas Braun static bool skipOverPair (tokenInfo *const token, int tOpen, int tClose,
702ce990805SThomas Braun vString *const repr, bool reprOuterPair)
7032ff1f9d2SColomban Wendling {
7042ff1f9d2SColomban Wendling if (token->type == tOpen)
7052ff1f9d2SColomban Wendling {
7062ff1f9d2SColomban Wendling int depth = 1;
7072ff1f9d2SColomban Wendling
7082ff1f9d2SColomban Wendling if (repr && reprOuterPair)
7092ff1f9d2SColomban Wendling reprCat (repr, token);
7102ff1f9d2SColomban Wendling do
7112ff1f9d2SColomban Wendling {
712ce990805SThomas Braun readTokenFull (token, true);
7132ff1f9d2SColomban Wendling if (repr && (reprOuterPair || token->type != tClose || depth > 1))
7142ff1f9d2SColomban Wendling {
7152ff1f9d2SColomban Wendling reprCat (repr, token);
7162ff1f9d2SColomban Wendling }
7172ff1f9d2SColomban Wendling if (token->type == tOpen)
7182ff1f9d2SColomban Wendling depth ++;
7192ff1f9d2SColomban Wendling else if (token->type == tClose)
7202ff1f9d2SColomban Wendling depth --;
7212ff1f9d2SColomban Wendling }
7222ff1f9d2SColomban Wendling while (token->type != TOKEN_EOF && depth > 0);
7232ff1f9d2SColomban Wendling }
7242ff1f9d2SColomban Wendling
7252ff1f9d2SColomban Wendling return token->type == tClose;
7262ff1f9d2SColomban Wendling }
7272ff1f9d2SColomban Wendling
skipLambdaArglist(tokenInfo * const token,vString * const repr)728ce990805SThomas Braun static bool skipLambdaArglist (tokenInfo *const token, vString *const repr)
7292ff1f9d2SColomban Wendling {
7302ff1f9d2SColomban Wendling while (token->type != TOKEN_EOF && token->type != ':' &&
7312ff1f9d2SColomban Wendling /* avoid reading too much, just in case */
7322ff1f9d2SColomban Wendling token->type != TOKEN_INDENT)
7332ff1f9d2SColomban Wendling {
734ce990805SThomas Braun bool readNext = true;
7352ff1f9d2SColomban Wendling
7362ff1f9d2SColomban Wendling if (token->type == '(')
737ce990805SThomas Braun readNext = skipOverPair (token, '(', ')', repr, true);
7382ff1f9d2SColomban Wendling else if (token->type == '[')
739ce990805SThomas Braun readNext = skipOverPair (token, '[', ']', repr, true);
7402ff1f9d2SColomban Wendling else if (token->type == '{')
741ce990805SThomas Braun readNext = skipOverPair (token, '{', '}', repr, true);
7422ff1f9d2SColomban Wendling else if (token->keyword == KEYWORD_lambda)
7432ff1f9d2SColomban Wendling { /* handle lambdas in a default value */
7442ff1f9d2SColomban Wendling if (repr)
7452ff1f9d2SColomban Wendling reprCat (repr, token);
746ce990805SThomas Braun readTokenFull (token, true);
7472ff1f9d2SColomban Wendling readNext = skipLambdaArglist (token, repr);
7482ff1f9d2SColomban Wendling if (token->type == ':')
749ce990805SThomas Braun readNext = true;
7502ff1f9d2SColomban Wendling if (readNext && repr)
7512ff1f9d2SColomban Wendling reprCat (repr, token);
7522ff1f9d2SColomban Wendling }
7532ff1f9d2SColomban Wendling else if (repr)
7542ff1f9d2SColomban Wendling {
7552ff1f9d2SColomban Wendling reprCat (repr, token);
7562ff1f9d2SColomban Wendling }
7572ff1f9d2SColomban Wendling
7582ff1f9d2SColomban Wendling if (readNext)
759ce990805SThomas Braun readTokenFull (token, true);
7602ff1f9d2SColomban Wendling }
761ce990805SThomas Braun return false;
7622ff1f9d2SColomban Wendling }
7632ff1f9d2SColomban Wendling
readQualifiedName(tokenInfo * const nameToken)7642ff1f9d2SColomban Wendling static void readQualifiedName (tokenInfo *const nameToken)
7652ff1f9d2SColomban Wendling {
7662ff1f9d2SColomban Wendling readToken (nameToken);
7672ff1f9d2SColomban Wendling
7682ff1f9d2SColomban Wendling if (nameToken->type == TOKEN_IDENTIFIER ||
7692ff1f9d2SColomban Wendling nameToken->type == '.')
7702ff1f9d2SColomban Wendling {
7712ff1f9d2SColomban Wendling vString *qualifiedName = vStringNew ();
7726ff4799bSJiří Techet tokenInfo *token = newToken ();
7732ff1f9d2SColomban Wendling
7742ff1f9d2SColomban Wendling while (nameToken->type == TOKEN_IDENTIFIER ||
7752ff1f9d2SColomban Wendling nameToken->type == '.')
7762ff1f9d2SColomban Wendling {
7772ff1f9d2SColomban Wendling vStringCat (qualifiedName, nameToken->string);
7782ff1f9d2SColomban Wendling copyToken (token, nameToken);
7792ff1f9d2SColomban Wendling
7802ff1f9d2SColomban Wendling readToken (nameToken);
7812ff1f9d2SColomban Wendling }
7822ff1f9d2SColomban Wendling /* put the last, non-matching, token back */
7832ff1f9d2SColomban Wendling ungetToken (nameToken);
7842ff1f9d2SColomban Wendling
7852ff1f9d2SColomban Wendling copyToken (nameToken, token);
7862ff1f9d2SColomban Wendling nameToken->type = TOKEN_IDENTIFIER;
7872ff1f9d2SColomban Wendling vStringCopy (nameToken->string, qualifiedName);
7882ff1f9d2SColomban Wendling
7896ff4799bSJiří Techet deleteToken (token);
7902ff1f9d2SColomban Wendling vStringDelete (qualifiedName);
7912ff1f9d2SColomban Wendling }
7922ff1f9d2SColomban Wendling }
7932ff1f9d2SColomban Wendling
readCDefName(tokenInfo * const token,pythonKind * kind)794ce990805SThomas Braun static bool readCDefName (tokenInfo *const token, pythonKind *kind)
7952ff1f9d2SColomban Wendling {
7962ff1f9d2SColomban Wendling readToken (token);
7972ff1f9d2SColomban Wendling
7982ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_extern ||
7992ff1f9d2SColomban Wendling token->keyword == KEYWORD_import)
8002ff1f9d2SColomban Wendling {
8012ff1f9d2SColomban Wendling readToken (token);
8022ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_from)
803ce990805SThomas Braun return false;
8042ff1f9d2SColomban Wendling }
8052ff1f9d2SColomban Wendling
8062ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_class)
8072ff1f9d2SColomban Wendling {
8082ff1f9d2SColomban Wendling *kind = K_CLASS;
8092ff1f9d2SColomban Wendling readToken (token);
8102ff1f9d2SColomban Wendling }
8112ff1f9d2SColomban Wendling else
8121d511f1fSColomban Wendling {
8131d511f1fSColomban Wendling /* skip the optional type declaration -- everything on the same line
8142ff1f9d2SColomban Wendling * until an identifier followed by "(". */
8156ff4799bSJiří Techet tokenInfo *candidate = newToken ();
8162ff1f9d2SColomban Wendling
8172ff1f9d2SColomban Wendling while (token->type != TOKEN_EOF &&
8182ff1f9d2SColomban Wendling token->type != TOKEN_INDENT &&
8192ff1f9d2SColomban Wendling token->type != '=' &&
8202ff1f9d2SColomban Wendling token->type != ',' &&
8212ff1f9d2SColomban Wendling token->type != ':')
8222ff1f9d2SColomban Wendling {
8232ff1f9d2SColomban Wendling if (token->type == '[')
8242ff1f9d2SColomban Wendling {
825ce990805SThomas Braun if (skipOverPair (token, '[', ']', NULL, false))
8262ff1f9d2SColomban Wendling readToken (token);
8272ff1f9d2SColomban Wendling }
8282ff1f9d2SColomban Wendling else if (token->type == '(')
8292ff1f9d2SColomban Wendling {
830ce990805SThomas Braun if (skipOverPair (token, '(', ')', NULL, false))
8312ff1f9d2SColomban Wendling readToken (token);
8322ff1f9d2SColomban Wendling }
8332ff1f9d2SColomban Wendling else if (token->type == TOKEN_IDENTIFIER)
8342ff1f9d2SColomban Wendling {
8352ff1f9d2SColomban Wendling copyToken (candidate, token);
8362ff1f9d2SColomban Wendling readToken (token);
8372ff1f9d2SColomban Wendling if (token->type == '(')
8382ff1f9d2SColomban Wendling { /* okay, we really found a function, use this */
8392ff1f9d2SColomban Wendling *kind = K_FUNCTION;
8402ff1f9d2SColomban Wendling ungetToken (token);
8412ff1f9d2SColomban Wendling copyToken (token, candidate);
8422ff1f9d2SColomban Wendling break;
8432ff1f9d2SColomban Wendling }
8442ff1f9d2SColomban Wendling }
8452ff1f9d2SColomban Wendling else
8462ff1f9d2SColomban Wendling readToken (token);
8472ff1f9d2SColomban Wendling }
8482ff1f9d2SColomban Wendling
8496ff4799bSJiří Techet deleteToken (candidate);
8502ff1f9d2SColomban Wendling }
8512ff1f9d2SColomban Wendling
8522ff1f9d2SColomban Wendling return token->type == TOKEN_IDENTIFIER;
8532ff1f9d2SColomban Wendling }
8542ff1f9d2SColomban Wendling
parseParamTypeAnnotation(tokenInfo * const token,vString * arglist)855a1cdce69SMasatake YAMATO static vString *parseParamTypeAnnotation (tokenInfo *const token,
856a1cdce69SMasatake YAMATO vString *arglist)
857a1cdce69SMasatake YAMATO {
858a1cdce69SMasatake YAMATO readToken (token);
859a1cdce69SMasatake YAMATO if (token->type != ':')
860a1cdce69SMasatake YAMATO {
861a1cdce69SMasatake YAMATO ungetToken (token);
862a1cdce69SMasatake YAMATO return NULL;
863a1cdce69SMasatake YAMATO }
864a1cdce69SMasatake YAMATO
865a1cdce69SMasatake YAMATO reprCat (arglist, token);
866a1cdce69SMasatake YAMATO int depth = 0;
867a1cdce69SMasatake YAMATO vString *t = vStringNew ();
868a1cdce69SMasatake YAMATO while (true)
869a1cdce69SMasatake YAMATO {
870a1cdce69SMasatake YAMATO readTokenFull (token, true);
871a1cdce69SMasatake YAMATO if (token->type == TOKEN_WHITESPACE)
872a1cdce69SMasatake YAMATO {
873a1cdce69SMasatake YAMATO reprCat (arglist, token);
874a1cdce69SMasatake YAMATO continue;
875a1cdce69SMasatake YAMATO }
876a1cdce69SMasatake YAMATO else if (token->type == TOKEN_EOF)
877a1cdce69SMasatake YAMATO break;
878a1cdce69SMasatake YAMATO
879a1cdce69SMasatake YAMATO if (token->type == '(' ||
880a1cdce69SMasatake YAMATO token->type == '[' ||
881a1cdce69SMasatake YAMATO token->type == '{')
882a1cdce69SMasatake YAMATO depth ++;
883a1cdce69SMasatake YAMATO else if (token->type == ')' ||
884a1cdce69SMasatake YAMATO token->type == ']' ||
885a1cdce69SMasatake YAMATO token->type == '}')
886a1cdce69SMasatake YAMATO depth --;
887a1cdce69SMasatake YAMATO
888a1cdce69SMasatake YAMATO if (depth < 0
889a1cdce69SMasatake YAMATO || (depth == 0 && (token->type == '='
890a1cdce69SMasatake YAMATO || token->type == ',')))
891a1cdce69SMasatake YAMATO {
892a1cdce69SMasatake YAMATO ungetToken (token);
893a1cdce69SMasatake YAMATO return t;
894a1cdce69SMasatake YAMATO }
895a1cdce69SMasatake YAMATO reprCat (arglist, token);
896a1cdce69SMasatake YAMATO reprCat (t, token);
897a1cdce69SMasatake YAMATO }
898a1cdce69SMasatake YAMATO vStringDelete (t);
899a1cdce69SMasatake YAMATO return NULL;
900a1cdce69SMasatake YAMATO }
901a1cdce69SMasatake YAMATO
parseReturnTypeAnnotation(tokenInfo * const token)902c378e8b6SMasatake YAMATO static vString *parseReturnTypeAnnotation (tokenInfo *const token)
903c378e8b6SMasatake YAMATO {
904c378e8b6SMasatake YAMATO readToken (token);
905c378e8b6SMasatake YAMATO if (token->type != TOKEN_ARROW)
906c378e8b6SMasatake YAMATO {
907c378e8b6SMasatake YAMATO ungetToken (token);
908c378e8b6SMasatake YAMATO return NULL;
909c378e8b6SMasatake YAMATO }
910c378e8b6SMasatake YAMATO
911c378e8b6SMasatake YAMATO int depth = 0;
912c378e8b6SMasatake YAMATO vString *t = vStringNew ();
913c378e8b6SMasatake YAMATO while (true)
914c378e8b6SMasatake YAMATO {
915c378e8b6SMasatake YAMATO readToken (token);
916c378e8b6SMasatake YAMATO if (token->type == TOKEN_EOF)
917c378e8b6SMasatake YAMATO break;
918c378e8b6SMasatake YAMATO
919c378e8b6SMasatake YAMATO if (token->type == '(' ||
920c378e8b6SMasatake YAMATO token->type == '[' ||
921c378e8b6SMasatake YAMATO token->type == '{')
922c378e8b6SMasatake YAMATO depth ++;
923c378e8b6SMasatake YAMATO else if (token->type == ')' ||
924c378e8b6SMasatake YAMATO token->type == ']' ||
925c378e8b6SMasatake YAMATO token->type == '}')
926c378e8b6SMasatake YAMATO depth --;
927c378e8b6SMasatake YAMATO if (depth == 0 && token->type == ':')
928c378e8b6SMasatake YAMATO {
929c378e8b6SMasatake YAMATO ungetToken (token);
930c378e8b6SMasatake YAMATO return t;
931c378e8b6SMasatake YAMATO }
932c378e8b6SMasatake YAMATO else
933c378e8b6SMasatake YAMATO reprCat (t, token);
934c378e8b6SMasatake YAMATO }
935c378e8b6SMasatake YAMATO vStringDelete (t);
936c378e8b6SMasatake YAMATO return NULL;
937c378e8b6SMasatake YAMATO }
938c378e8b6SMasatake YAMATO
93934454f72SMasatake YAMATO struct typedParam {
94034454f72SMasatake YAMATO tokenInfo *token;
94134454f72SMasatake YAMATO vString *type;
94234454f72SMasatake YAMATO };
94334454f72SMasatake YAMATO
makeTypedParam(tokenInfo * token,vString * type)94434454f72SMasatake YAMATO static struct typedParam *makeTypedParam (tokenInfo *token, vString *type)
94534454f72SMasatake YAMATO {
94634454f72SMasatake YAMATO struct typedParam *p = xMalloc (1, struct typedParam);
94734454f72SMasatake YAMATO p->token = token;
94834454f72SMasatake YAMATO p->type = type;
94934454f72SMasatake YAMATO return p;
95034454f72SMasatake YAMATO }
95134454f72SMasatake YAMATO
makeTypedParamWithCopy(const tokenInfo * token,const vString * type)952*23ceb0b6SMasatake YAMATO static struct typedParam *makeTypedParamWithCopy (const tokenInfo *token, const vString *type)
953*23ceb0b6SMasatake YAMATO {
954*23ceb0b6SMasatake YAMATO tokenInfo *token_copied = newToken ();
955*23ceb0b6SMasatake YAMATO copyToken (token_copied, token);
956*23ceb0b6SMasatake YAMATO
957*23ceb0b6SMasatake YAMATO
958*23ceb0b6SMasatake YAMATO vString *type_copied = type? vStringNewCopy (type): NULL;
959*23ceb0b6SMasatake YAMATO return makeTypedParam (token_copied, type_copied);
960*23ceb0b6SMasatake YAMATO }
961*23ceb0b6SMasatake YAMATO
deleteTypedParam(struct typedParam * p)96234454f72SMasatake YAMATO static void deleteTypedParam (struct typedParam *p)
96334454f72SMasatake YAMATO {
96434454f72SMasatake YAMATO deleteToken (p->token);
96534454f72SMasatake YAMATO vStringDelete (p->type); /* NULL is acceptable. */
96634454f72SMasatake YAMATO eFree (p);
96734454f72SMasatake YAMATO }
96834454f72SMasatake YAMATO
parseArglist(tokenInfo * const token,const int kind,vString * const arglist,ptrArray * const parameters)9694491a5beSMasatake YAMATO static void parseArglist (tokenInfo *const token, const int kind,
9704491a5beSMasatake YAMATO vString *const arglist, ptrArray *const parameters)
971f5f8bd9aSMasatake YAMATO {
972257674afSColomban Wendling int prevTokenType = token->type;
973257674afSColomban Wendling int depth = 1;
974257674afSColomban Wendling
975257674afSColomban Wendling if (kind != K_CLASS)
976257674afSColomban Wendling reprCat (arglist, token);
977257674afSColomban Wendling
978257674afSColomban Wendling do
979257674afSColomban Wendling {
980f34b6795SColomban Wendling if (token->type != TOKEN_WHITESPACE &&
981f34b6795SColomban Wendling /* for easy `*args` and `**kwargs` support, we also ignore
982f34b6795SColomban Wendling * `*`, which anyway can't otherwise screw us up */
983f34b6795SColomban Wendling token->type != '*')
984f34b6795SColomban Wendling {
985257674afSColomban Wendling prevTokenType = token->type;
986f34b6795SColomban Wendling }
987257674afSColomban Wendling
988ce990805SThomas Braun readTokenFull (token, true);
989257674afSColomban Wendling if (kind != K_CLASS || token->type != ')' || depth > 1)
990257674afSColomban Wendling reprCat (arglist, token);
991257674afSColomban Wendling
992f34b6795SColomban Wendling if (token->type == '(' ||
993f34b6795SColomban Wendling token->type == '[' ||
994f34b6795SColomban Wendling token->type == '{')
995257674afSColomban Wendling depth ++;
996f34b6795SColomban Wendling else if (token->type == ')' ||
997f34b6795SColomban Wendling token->type == ']' ||
998f34b6795SColomban Wendling token->type == '}')
999257674afSColomban Wendling depth --;
1000257674afSColomban Wendling else if (kind != K_CLASS && depth == 1 &&
1001257674afSColomban Wendling token->type == TOKEN_IDENTIFIER &&
1002257674afSColomban Wendling (prevTokenType == '(' || prevTokenType == ',') &&
1003257674afSColomban Wendling PythonKinds[K_PARAMETER].enabled)
1004257674afSColomban Wendling {
100534454f72SMasatake YAMATO tokenInfo *parameterName;
100634454f72SMasatake YAMATO vString *parameterType;
100734454f72SMasatake YAMATO struct typedParam *parameter;
1008257674afSColomban Wendling
100934454f72SMasatake YAMATO parameterName = newToken ();
1010257674afSColomban Wendling copyToken (parameterName, token);
101134454f72SMasatake YAMATO parameterType = parseParamTypeAnnotation (token, arglist);
101234454f72SMasatake YAMATO
101334454f72SMasatake YAMATO parameter = makeTypedParam (parameterName, parameterType);
101434454f72SMasatake YAMATO ptrArrayAdd (parameters, parameter);
1015257674afSColomban Wendling }
1016257674afSColomban Wendling }
1017257674afSColomban Wendling while (token->type != TOKEN_EOF && depth > 0);
1018f5f8bd9aSMasatake YAMATO }
1019f5f8bd9aSMasatake YAMATO
parseCArglist(tokenInfo * const token,const int kind,vString * const arglist,ptrArray * const parameters)1020*23ceb0b6SMasatake YAMATO static void parseCArglist (tokenInfo *const token, const int kind,
1021*23ceb0b6SMasatake YAMATO vString *const arglist, ptrArray *const parameters)
1022*23ceb0b6SMasatake YAMATO {
1023*23ceb0b6SMasatake YAMATO int depth = 1;
1024*23ceb0b6SMasatake YAMATO tokenInfo *pname = newToken ();
1025*23ceb0b6SMasatake YAMATO vString *ptype = vStringNew ();
1026*23ceb0b6SMasatake YAMATO vStringCat (arglist, token->string); /* '(' */
1027*23ceb0b6SMasatake YAMATO
1028*23ceb0b6SMasatake YAMATO while (true)
1029*23ceb0b6SMasatake YAMATO {
1030*23ceb0b6SMasatake YAMATO readToken (token);
1031*23ceb0b6SMasatake YAMATO if (token->type == TOKEN_EOF)
1032*23ceb0b6SMasatake YAMATO {
1033*23ceb0b6SMasatake YAMATO /* Unexpected input. */
1034*23ceb0b6SMasatake YAMATO vStringClear (arglist);
1035*23ceb0b6SMasatake YAMATO ptrArrayClear (parameters);
1036*23ceb0b6SMasatake YAMATO break;
1037*23ceb0b6SMasatake YAMATO }
1038*23ceb0b6SMasatake YAMATO
1039*23ceb0b6SMasatake YAMATO if (depth == 1 && (token->type == ',' || token->type == ')'))
1040*23ceb0b6SMasatake YAMATO {
1041*23ceb0b6SMasatake YAMATO if (pname->type == TOKEN_IDENTIFIER)
1042*23ceb0b6SMasatake YAMATO {
1043*23ceb0b6SMasatake YAMATO struct typedParam *p;
1044*23ceb0b6SMasatake YAMATO
1045*23ceb0b6SMasatake YAMATO /*
1046*23ceb0b6SMasatake YAMATO * Clean up the type string.
1047*23ceb0b6SMasatake YAMATO * The type string includes the parameter name at the end.
1048*23ceb0b6SMasatake YAMATO * 1. Trim the parameter name at the end.
1049*23ceb0b6SMasatake YAMATO * 2. Then, trim the white space at the end of the type string.
1050*23ceb0b6SMasatake YAMATO * 3. If the type string is not empty,
1051*23ceb0b6SMasatake YAMATO * 3.a append (the type stirng + ' ' + the parameter name) to arglist.
1052*23ceb0b6SMasatake YAMATO * 3.b else just append the parameter name to arglist.
1053*23ceb0b6SMasatake YAMATO *
1054*23ceb0b6SMasatake YAMATO * FIXME:
1055*23ceb0b6SMasatake YAMATO * This doesn't work well with an array and a function pointer.
1056*23ceb0b6SMasatake YAMATO *
1057*23ceb0b6SMasatake YAMATO * f(..., int seq [dim], ...)
1058*23ceb0b6SMasatake YAMATO * in this case, dim is extacted as a parameter.
1059*23ceb0b6SMasatake YAMATO *
1060*23ceb0b6SMasatake YAMATO * f(..., int (*fn)(int), ...)
1061*23ceb0b6SMasatake YAMATO * in this case , int is extacted as a parameter.
1062*23ceb0b6SMasatake YAMATO */
1063*23ceb0b6SMasatake YAMATO Assert (vStringLength (ptype) >= vStringLength (pname->string));
1064*23ceb0b6SMasatake YAMATO size_t ptype_len = vStringLength (ptype) - vStringLength (pname->string);
1065*23ceb0b6SMasatake YAMATO vStringTruncate (ptype, ptype_len);
1066*23ceb0b6SMasatake YAMATO
1067*23ceb0b6SMasatake YAMATO if (vStringLength (ptype) > 0)
1068*23ceb0b6SMasatake YAMATO {
1069*23ceb0b6SMasatake YAMATO vStringStripTrailing (ptype);
1070*23ceb0b6SMasatake YAMATO if (vStringLength (ptype) > 0)
1071*23ceb0b6SMasatake YAMATO {
1072*23ceb0b6SMasatake YAMATO vStringCat (arglist, ptype);
1073*23ceb0b6SMasatake YAMATO vStringPut (arglist, ' ');
1074*23ceb0b6SMasatake YAMATO }
1075*23ceb0b6SMasatake YAMATO }
1076*23ceb0b6SMasatake YAMATO vStringCat (arglist, pname->string);
1077*23ceb0b6SMasatake YAMATO
1078*23ceb0b6SMasatake YAMATO p = makeTypedParamWithCopy (pname, vStringIsEmpty(ptype)? NULL: ptype);
1079*23ceb0b6SMasatake YAMATO ptrArrayAdd (parameters, p);
1080*23ceb0b6SMasatake YAMATO }
1081*23ceb0b6SMasatake YAMATO if (token->type == ')')
1082*23ceb0b6SMasatake YAMATO {
1083*23ceb0b6SMasatake YAMATO vStringPut (arglist, ')');
1084*23ceb0b6SMasatake YAMATO break;
1085*23ceb0b6SMasatake YAMATO }
1086*23ceb0b6SMasatake YAMATO vStringCatS (arglist, ", ");
1087*23ceb0b6SMasatake YAMATO vStringClear (ptype);
1088*23ceb0b6SMasatake YAMATO pname->type = TOKEN_UNDEFINED;
1089*23ceb0b6SMasatake YAMATO continue;
1090*23ceb0b6SMasatake YAMATO }
1091*23ceb0b6SMasatake YAMATO
1092*23ceb0b6SMasatake YAMATO if (token->type == '(' ||
1093*23ceb0b6SMasatake YAMATO token->type == '[' ||
1094*23ceb0b6SMasatake YAMATO token->type == '{')
1095*23ceb0b6SMasatake YAMATO {
1096*23ceb0b6SMasatake YAMATO vStringPut (ptype, token->type);
1097*23ceb0b6SMasatake YAMATO depth ++;
1098*23ceb0b6SMasatake YAMATO continue;
1099*23ceb0b6SMasatake YAMATO }
1100*23ceb0b6SMasatake YAMATO
1101*23ceb0b6SMasatake YAMATO if (token->type == ')' ||
1102*23ceb0b6SMasatake YAMATO token->type == ']' ||
1103*23ceb0b6SMasatake YAMATO token->type == '}')
1104*23ceb0b6SMasatake YAMATO {
1105*23ceb0b6SMasatake YAMATO vStringPut (ptype, token->type);
1106*23ceb0b6SMasatake YAMATO depth --;
1107*23ceb0b6SMasatake YAMATO continue;
1108*23ceb0b6SMasatake YAMATO }
1109*23ceb0b6SMasatake YAMATO
1110*23ceb0b6SMasatake YAMATO if (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_KEYWORD)
1111*23ceb0b6SMasatake YAMATO {
1112*23ceb0b6SMasatake YAMATO if (vStringLength (ptype) > 0
1113*23ceb0b6SMasatake YAMATO && (isalnum ((unsigned char)vStringLast (ptype))
1114*23ceb0b6SMasatake YAMATO || vStringLast (ptype) == ','))
1115*23ceb0b6SMasatake YAMATO vStringPut (ptype, ' ');
1116*23ceb0b6SMasatake YAMATO vStringCat (ptype, token->string);
1117*23ceb0b6SMasatake YAMATO
1118*23ceb0b6SMasatake YAMATO if (!isdigit ((unsigned char)vStringLast (token->string)))
1119*23ceb0b6SMasatake YAMATO copyToken (pname, token);
1120*23ceb0b6SMasatake YAMATO continue;
1121*23ceb0b6SMasatake YAMATO }
1122*23ceb0b6SMasatake YAMATO
1123*23ceb0b6SMasatake YAMATO vStringCat (ptype, token->string);
1124*23ceb0b6SMasatake YAMATO }
1125*23ceb0b6SMasatake YAMATO
1126*23ceb0b6SMasatake YAMATO vStringDelete (ptype);
1127*23ceb0b6SMasatake YAMATO deleteToken (pname);
1128*23ceb0b6SMasatake YAMATO }
1129*23ceb0b6SMasatake YAMATO
parseClassOrDef(tokenInfo * const token,const vString * const decorators,pythonKind kind,bool isCDef)11304491a5beSMasatake YAMATO static bool parseClassOrDef (tokenInfo *const token,
11314491a5beSMasatake YAMATO const vString *const decorators,
11324491a5beSMasatake YAMATO pythonKind kind, bool isCDef)
11334491a5beSMasatake YAMATO {
11344491a5beSMasatake YAMATO vString *arglist = NULL;
11354491a5beSMasatake YAMATO tokenInfo *name = NULL;
11364491a5beSMasatake YAMATO ptrArray *parameters = NULL;
11374491a5beSMasatake YAMATO NestingLevel *lv;
11384491a5beSMasatake YAMATO int corkIndex;
11394491a5beSMasatake YAMATO
11404491a5beSMasatake YAMATO if (isCDef)
11414491a5beSMasatake YAMATO {
11424491a5beSMasatake YAMATO if (! readCDefName (token, &kind))
11434491a5beSMasatake YAMATO return false;
11444491a5beSMasatake YAMATO }
11454491a5beSMasatake YAMATO else
11464491a5beSMasatake YAMATO {
11474491a5beSMasatake YAMATO readToken (token);
11484491a5beSMasatake YAMATO if (token->type != TOKEN_IDENTIFIER)
11494491a5beSMasatake YAMATO return false;
11504491a5beSMasatake YAMATO }
11514491a5beSMasatake YAMATO
11524491a5beSMasatake YAMATO name = newToken ();
11534491a5beSMasatake YAMATO copyToken (name, token);
11544491a5beSMasatake YAMATO
11554491a5beSMasatake YAMATO readToken (token);
11564491a5beSMasatake YAMATO /* collect parameters or inheritance */
11574491a5beSMasatake YAMATO if (token->type == '(')
11584491a5beSMasatake YAMATO {
11594491a5beSMasatake YAMATO arglist = vStringNew ();
11604491a5beSMasatake YAMATO parameters = ptrArrayNew ((ptrArrayDeleteFunc)deleteTypedParam);
11614491a5beSMasatake YAMATO
1162*23ceb0b6SMasatake YAMATO if (isCDef && kind != K_CLASS)
1163*23ceb0b6SMasatake YAMATO parseCArglist (token, kind, arglist, parameters);
1164*23ceb0b6SMasatake YAMATO else
11654491a5beSMasatake YAMATO parseArglist (token, kind, arglist, parameters);
11664491a5beSMasatake YAMATO }
11674491a5beSMasatake YAMATO
11682ff1f9d2SColomban Wendling if (kind == K_CLASS)
11695d0fd5feSColomban Wendling corkIndex = makeClassTag (name, arglist, decorators);
11702ff1f9d2SColomban Wendling else
11715d0fd5feSColomban Wendling corkIndex = makeFunctionTag (name, arglist, decorators);
1172f5f8bd9aSMasatake YAMATO
11732ff1f9d2SColomban Wendling lv = nestingLevelsPush (PythonNestingLevels, corkIndex);
11742ff1f9d2SColomban Wendling PY_NL (lv)->indentation = token->indent;
11752ff1f9d2SColomban Wendling
11766ff4799bSJiří Techet deleteToken (name);
11772ff1f9d2SColomban Wendling vStringDelete (arglist);
11782ff1f9d2SColomban Wendling
117934454f72SMasatake YAMATO if (parameters && !ptrArrayIsEmpty (parameters))
1180257674afSColomban Wendling {
1181257674afSColomban Wendling unsigned int i;
1182257674afSColomban Wendling
118334454f72SMasatake YAMATO for (i = 0; i < ptrArrayCount (parameters); i++)
1184257674afSColomban Wendling {
118534454f72SMasatake YAMATO struct typedParam *parameter = ptrArrayItem (parameters, i);
118634454f72SMasatake YAMATO int paramCorkIndex = makeSimplePythonTag (parameter->token, K_PARAMETER);
1187a1cdce69SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (paramCorkIndex);
118834454f72SMasatake YAMATO if (e && parameter->type)
1189a1cdce69SMasatake YAMATO {
1190a1cdce69SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
119134454f72SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (parameter->type);
119234454f72SMasatake YAMATO parameter->type = NULL;
1193257674afSColomban Wendling }
1194257674afSColomban Wendling }
119534454f72SMasatake YAMATO }
119634454f72SMasatake YAMATO ptrArrayDelete (parameters); /* NULL is acceptable. */
1197257674afSColomban Wendling
1198c378e8b6SMasatake YAMATO tagEntryInfo *e;
1199c378e8b6SMasatake YAMATO vString *t;
1200c378e8b6SMasatake YAMATO if (kind != K_CLASS
1201c378e8b6SMasatake YAMATO && (e = getEntryInCorkQueue (corkIndex))
1202c378e8b6SMasatake YAMATO && (t = parseReturnTypeAnnotation (token)))
1203c378e8b6SMasatake YAMATO {
1204c378e8b6SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
1205c378e8b6SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (t);
1206c378e8b6SMasatake YAMATO }
1207c378e8b6SMasatake YAMATO
1208ce990805SThomas Braun return true;
12092ff1f9d2SColomban Wendling }
12102ff1f9d2SColomban Wendling
parseImport(tokenInfo * const token)1211ce990805SThomas Braun static bool parseImport (tokenInfo *const token)
12122ff1f9d2SColomban Wendling {
12132ff1f9d2SColomban Wendling tokenInfo *fromModule = NULL;
12142ff1f9d2SColomban Wendling
12152ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_from)
12162ff1f9d2SColomban Wendling {
12172ff1f9d2SColomban Wendling readQualifiedName (token);
12182ff1f9d2SColomban Wendling if (token->type == TOKEN_IDENTIFIER)
12192ff1f9d2SColomban Wendling {
12206ff4799bSJiří Techet fromModule = newToken ();
12212ff1f9d2SColomban Wendling copyToken (fromModule, token);
12222ff1f9d2SColomban Wendling readToken (token);
12232ff1f9d2SColomban Wendling }
12242ff1f9d2SColomban Wendling }
12252ff1f9d2SColomban Wendling
12262ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_import)
12272ff1f9d2SColomban Wendling {
1228ce990805SThomas Braun bool parenthesized = false;
122972ab2762SMasatake YAMATO int moduleIndex;
12302ff1f9d2SColomban Wendling
12312ff1f9d2SColomban Wendling if (fromModule)
12322ff1f9d2SColomban Wendling {
12332ff1f9d2SColomban Wendling /* from X import ...
12342ff1f9d2SColomban Wendling * --------------------
12352ff1f9d2SColomban Wendling * X = (kind:module, role:namespace) */
123672ab2762SMasatake YAMATO moduleIndex = makeSimplePythonRefTag (fromModule, NULL, K_MODULE,
12372ff1f9d2SColomban Wendling PYTHON_MODULE_NAMESPACE,
12382ff1f9d2SColomban Wendling XTAG_UNKNOWN);
12392ff1f9d2SColomban Wendling }
12402ff1f9d2SColomban Wendling
12412ff1f9d2SColomban Wendling do
12422ff1f9d2SColomban Wendling {
12432ff1f9d2SColomban Wendling readQualifiedName (token);
12442ff1f9d2SColomban Wendling
12452ff1f9d2SColomban Wendling /* support for `from x import (...)` */
12462ff1f9d2SColomban Wendling if (fromModule && ! parenthesized && token->type == '(')
12472ff1f9d2SColomban Wendling {
1248ce990805SThomas Braun parenthesized = true;
12492ff1f9d2SColomban Wendling readQualifiedName (token);
12502ff1f9d2SColomban Wendling }
12512ff1f9d2SColomban Wendling
12522ff1f9d2SColomban Wendling if (token->type == TOKEN_IDENTIFIER)
12532ff1f9d2SColomban Wendling {
12546ff4799bSJiří Techet tokenInfo *name = newToken ();
12552ff1f9d2SColomban Wendling
12562ff1f9d2SColomban Wendling copyToken (name, token);
12572ff1f9d2SColomban Wendling readToken (token);
12582ff1f9d2SColomban Wendling /* if there is an "as", use it as the name */
12592ff1f9d2SColomban Wendling if (token->keyword == KEYWORD_as)
12602ff1f9d2SColomban Wendling {
12612ff1f9d2SColomban Wendling readToken (token);
12622ff1f9d2SColomban Wendling if (token->type == TOKEN_IDENTIFIER)
12632ff1f9d2SColomban Wendling {
12642ff1f9d2SColomban Wendling if (fromModule)
1265f5f8bd9aSMasatake YAMATO {
1266f5f8bd9aSMasatake YAMATO /* from x import Y as Z
12672ff1f9d2SColomban Wendling * ----------------------------
12682ff1f9d2SColomban Wendling * x = (kind:module, role:namespace),
126972ab2762SMasatake YAMATO * Y = (kind:unknown, role:indirectlyImported, scope:module:X),
12706f605b92SMasatake YAMATO * Z = (kind:unknown, nameref:unknown:Y) */
127172ab2762SMasatake YAMATO int index;
1272f5f8bd9aSMasatake YAMATO
1273f5f8bd9aSMasatake YAMATO /* Y */
127472ab2762SMasatake YAMATO index = makeSimplePythonRefTag (name, NULL, K_UNKNOWN,
12752ff1f9d2SColomban Wendling PYTHON_UNKNOWN_INDIRECTLY_IMPORTED,
12762ff1f9d2SColomban Wendling XTAG_UNKNOWN);
127772ab2762SMasatake YAMATO /* fill the scope field for Y */
127872ab2762SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (index);
127972ab2762SMasatake YAMATO if (e)
128072ab2762SMasatake YAMATO e->extensionFields.scopeIndex = moduleIndex;
128172ab2762SMasatake YAMATO
1282f5f8bd9aSMasatake YAMATO /* Z */
128372ab2762SMasatake YAMATO index = makeSimplePythonTag (token, K_UNKNOWN);
12846f605b92SMasatake YAMATO /* fill the nameref filed for Y */
12856f605b92SMasatake YAMATO if (PythonFields[F_NAMEREF].enabled)
12866f605b92SMasatake YAMATO {
12876f605b92SMasatake YAMATO vString *nameref = vStringNewInit (PythonKinds [K_UNKNOWN].name);
12886f605b92SMasatake YAMATO vStringPut (nameref, ':');
12896f605b92SMasatake YAMATO vStringCat (nameref, name->string);
12906f605b92SMasatake YAMATO attachParserFieldToCorkEntry (index, PythonFields[F_NAMEREF].ftype,
12916f605b92SMasatake YAMATO vStringValue (nameref));
12926f605b92SMasatake YAMATO vStringDelete (nameref);
12936f605b92SMasatake YAMATO }
1294f5f8bd9aSMasatake YAMATO }
1295f5f8bd9aSMasatake YAMATO else
1296f5f8bd9aSMasatake YAMATO {
1297f5f8bd9aSMasatake YAMATO /* import x as Y
12982ff1f9d2SColomban Wendling * ----------------------------
12996f605b92SMasatake YAMATO * x = (kind:module, role:indirectlyImported)
13006f605b92SMasatake YAMATO * Y = (kind:namespace, nameref:module:x)*/
13016f605b92SMasatake YAMATO /* x */
13022ff1f9d2SColomban Wendling makeSimplePythonRefTag (name, NULL, K_MODULE,
13032ff1f9d2SColomban Wendling PYTHON_MODULE_INDIRECTLY_IMPORTED,
13042ff1f9d2SColomban Wendling XTAG_UNKNOWN);
1305f5f8bd9aSMasatake YAMATO /* Y */
13066f605b92SMasatake YAMATO int index = makeSimplePythonTag (token, K_NAMESPACE);
13076f605b92SMasatake YAMATO /* fill the nameref filed for Y */
13086f605b92SMasatake YAMATO if (PythonFields[F_NAMEREF].enabled)
13096f605b92SMasatake YAMATO {
13106f605b92SMasatake YAMATO vString *nameref = vStringNewInit (PythonKinds [K_MODULE].name);
13116f605b92SMasatake YAMATO vStringPut (nameref, ':');
13126f605b92SMasatake YAMATO vStringCat (nameref, name->string);
13136f605b92SMasatake YAMATO attachParserFieldToCorkEntry (index, PythonFields[F_NAMEREF].ftype,
13146f605b92SMasatake YAMATO vStringValue (nameref));
13156f605b92SMasatake YAMATO vStringDelete (nameref);
13166f605b92SMasatake YAMATO }
1317f5f8bd9aSMasatake YAMATO }
1318f5f8bd9aSMasatake YAMATO
13192ff1f9d2SColomban Wendling copyToken (name, token);
13202ff1f9d2SColomban Wendling readToken (token);
1321f5f8bd9aSMasatake YAMATO }
1322f5f8bd9aSMasatake YAMATO }
1323f5f8bd9aSMasatake YAMATO else
1324f5f8bd9aSMasatake YAMATO {
13252ff1f9d2SColomban Wendling if (fromModule)
1326f5f8bd9aSMasatake YAMATO {
1327f5f8bd9aSMasatake YAMATO /* from x import Y
1328f5f8bd9aSMasatake YAMATO --------------
1329f5f8bd9aSMasatake YAMATO x = (kind:module, role:namespace),
133072ab2762SMasatake YAMATO Y = (kind:unknown, role:imported, scope:module:x) */
1331f5f8bd9aSMasatake YAMATO /* Y */
133272ab2762SMasatake YAMATO int index = makeSimplePythonRefTag (name, NULL, K_UNKNOWN,
1333978db657SMasatake YAMATO PYTHON_UNKNOWN_IMPORTED,
13342ff1f9d2SColomban Wendling XTAG_UNKNOWN);
133572ab2762SMasatake YAMATO /* fill the scope field for Y */
133672ab2762SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (index);
133772ab2762SMasatake YAMATO if (e)
133872ab2762SMasatake YAMATO e->extensionFields.scopeIndex = moduleIndex;
1339f5f8bd9aSMasatake YAMATO }
1340f5f8bd9aSMasatake YAMATO else
1341f5f8bd9aSMasatake YAMATO {
1342f5f8bd9aSMasatake YAMATO /* import X
1343f5f8bd9aSMasatake YAMATO --------------
1344f5f8bd9aSMasatake YAMATO X = (kind:module, role:imported) */
13452ff1f9d2SColomban Wendling makeSimplePythonRefTag (name, NULL, K_MODULE,
13462ff1f9d2SColomban Wendling PYTHON_MODULE_IMPORTED,
13472ff1f9d2SColomban Wendling XTAG_UNKNOWN);
1348f5f8bd9aSMasatake YAMATO }
1349f5f8bd9aSMasatake YAMATO }
1350f5f8bd9aSMasatake YAMATO
13516ff4799bSJiří Techet deleteToken (name);
1352f5f8bd9aSMasatake YAMATO }
1353f5f8bd9aSMasatake YAMATO }
13542ff1f9d2SColomban Wendling while (token->type == ',');
1355f5f8bd9aSMasatake YAMATO
13562ff1f9d2SColomban Wendling if (parenthesized && token->type == ')')
13572ff1f9d2SColomban Wendling readToken (token);
1358f5f8bd9aSMasatake YAMATO }
1359f5f8bd9aSMasatake YAMATO
13602ff1f9d2SColomban Wendling if (fromModule)
13616ff4799bSJiří Techet deleteToken (fromModule);
13627489fd61SMasatake YAMATO
1363ce990805SThomas Braun return false;
13647489fd61SMasatake YAMATO }
13657489fd61SMasatake YAMATO
1366d771a1e5SColomban Wendling /* this only handles the most common cases, but an annotation can be any
1367d771a1e5SColomban Wendling * expression in theory.
1368d771a1e5SColomban Wendling * this function assumes there must be an annotation, and doesn't do any check
1369d771a1e5SColomban Wendling * on the token on which it is called: the caller should do that part. */
skipVariableTypeAnnotation(tokenInfo * const token,vString * const repr)1370ba92e639SMasatake YAMATO static bool skipVariableTypeAnnotation (tokenInfo *const token, vString *const repr)
1371d771a1e5SColomban Wendling {
1372d771a1e5SColomban Wendling bool readNext = true;
1373d771a1e5SColomban Wendling
1374d771a1e5SColomban Wendling readToken (token);
1375d771a1e5SColomban Wendling switch (token->type)
1376d771a1e5SColomban Wendling {
1377ba92e639SMasatake YAMATO case '[': readNext = skipOverPair (token, '[', ']', repr, true); break;
1378ba92e639SMasatake YAMATO case '(': readNext = skipOverPair (token, '(', ')', repr, true); break;
1379ba92e639SMasatake YAMATO case '{': readNext = skipOverPair (token, '{', '}', repr, true); break;
1380ba92e639SMasatake YAMATO default: reprCat (repr, token);
1381d771a1e5SColomban Wendling }
1382d771a1e5SColomban Wendling if (readNext)
1383d771a1e5SColomban Wendling readToken (token);
1384d771a1e5SColomban Wendling /* skip subscripts and calls */
13850f7e912bSMasatake YAMATO while (token->type == '[' || token->type == '(' || token->type == '.' || token->type == '|')
1386d771a1e5SColomban Wendling {
1387d771a1e5SColomban Wendling switch (token->type)
1388d771a1e5SColomban Wendling {
1389ba92e639SMasatake YAMATO case '[': readNext = skipOverPair (token, '[', ']', repr, true); break;
1390ba92e639SMasatake YAMATO case '(': readNext = skipOverPair (token, '(', ')', repr, true); break;
13910f7e912bSMasatake YAMATO case '|':
13920f7e912bSMasatake YAMATO reprCat (repr, token);
13930f7e912bSMasatake YAMATO skipVariableTypeAnnotation (token, repr);
13940f7e912bSMasatake YAMATO readNext = false;
13950f7e912bSMasatake YAMATO break;
1396d771a1e5SColomban Wendling case '.':
1397ba92e639SMasatake YAMATO reprCat (repr, token);
1398d771a1e5SColomban Wendling readToken (token);
1399d771a1e5SColomban Wendling readNext = token->type == TOKEN_IDENTIFIER;
1400ba92e639SMasatake YAMATO if (readNext)
1401ba92e639SMasatake YAMATO reprCat (repr, token);
1402d771a1e5SColomban Wendling break;
1403d771a1e5SColomban Wendling default: readNext = false; break;
1404d771a1e5SColomban Wendling }
1405d771a1e5SColomban Wendling if (readNext)
1406d771a1e5SColomban Wendling readToken (token);
1407d771a1e5SColomban Wendling }
1408d771a1e5SColomban Wendling
1409d771a1e5SColomban Wendling return false;
1410d771a1e5SColomban Wendling }
1411d771a1e5SColomban Wendling
parseVariable(tokenInfo * const token,const pythonKind kind)1412ce990805SThomas Braun static bool parseVariable (tokenInfo *const token, const pythonKind kind)
14139a4b69e0SColomban Wendling {
14140c188d12SColomban Wendling /* In order to support proper tag type for lambdas in multiple
14150c188d12SColomban Wendling * assignations, we first collect all the names, and then try and map
14160c188d12SColomban Wendling * an assignation to it */
14170c188d12SColomban Wendling tokenInfo *nameTokens[8] = { NULL };
1418ba92e639SMasatake YAMATO vString *nameTypes [ARRAY_SIZE (nameTokens)] = { NULL };
14190c188d12SColomban Wendling unsigned int nameCount = 0;
1420ba92e639SMasatake YAMATO vString *type = vStringNew();
14210c188d12SColomban Wendling
14220c188d12SColomban Wendling /* first, collect variable name tokens */
14230c188d12SColomban Wendling while (token->type == TOKEN_IDENTIFIER &&
14240c188d12SColomban Wendling nameCount < ARRAY_SIZE (nameTokens))
14250c188d12SColomban Wendling {
1426ba92e639SMasatake YAMATO unsigned int i;
14276ff4799bSJiří Techet tokenInfo *name = newToken ();
14280c188d12SColomban Wendling copyToken (name, token);
14290c188d12SColomban Wendling
1430bbb831cfSColomban Wendling readToken (token);
1431bbb831cfSColomban Wendling if (token->type == '.')
1432bbb831cfSColomban Wendling {
1433bbb831cfSColomban Wendling /* FIXME: what to do with dotted names? We currently ignore them
1434bbb831cfSColomban Wendling * as we need to do something not to break the whole
1435bbb831cfSColomban Wendling * declaration, but the expected behavior is questionable */
14366ff4799bSJiří Techet deleteToken (name);
1437bbb831cfSColomban Wendling name = NULL;
1438bbb831cfSColomban Wendling
1439bbb831cfSColomban Wendling do
1440bbb831cfSColomban Wendling {
1441bbb831cfSColomban Wendling readToken (token);
1442bbb831cfSColomban Wendling }
1443bbb831cfSColomban Wendling while (token->type == TOKEN_IDENTIFIER ||
1444bbb831cfSColomban Wendling token->type == '.');
1445bbb831cfSColomban Wendling }
1446bbb831cfSColomban Wendling
1447ba92e639SMasatake YAMATO i = nameCount++;
1448ba92e639SMasatake YAMATO nameTokens[i] = name;
14490c188d12SColomban Wendling
1450ba92e639SMasatake YAMATO /* (parse and) skip annotations. we need not to be too permissive because we
1451d771a1e5SColomban Wendling * aren't yet sure we're actually parsing a variable. */
1452ba92e639SMasatake YAMATO if (token->type == ':' && skipVariableTypeAnnotation (token, type))
1453d771a1e5SColomban Wendling readToken (token);
1454d771a1e5SColomban Wendling
1455ba92e639SMasatake YAMATO if (vStringLength (type) > 0)
1456ba92e639SMasatake YAMATO {
1457ba92e639SMasatake YAMATO nameTypes[i] = type;
1458ba92e639SMasatake YAMATO type = vStringNew ();
1459ba92e639SMasatake YAMATO }
1460ba92e639SMasatake YAMATO
14610c188d12SColomban Wendling if (token->type == ',')
14620c188d12SColomban Wendling readToken (token);
14630c188d12SColomban Wendling else
14640c188d12SColomban Wendling break;
14650c188d12SColomban Wendling }
1466ba92e639SMasatake YAMATO vStringDelete (type);
14670c188d12SColomban Wendling
14680c188d12SColomban Wendling /* then, if it's a proper assignation, try and map assignations so that
14690c188d12SColomban Wendling * we catch lambdas and alike */
14700c188d12SColomban Wendling if (token->type == '=')
14710c188d12SColomban Wendling {
14720c188d12SColomban Wendling unsigned int i = 0;
14739a4b69e0SColomban Wendling
14749a4b69e0SColomban Wendling do
14759a4b69e0SColomban Wendling {
1476ba92e639SMasatake YAMATO const tokenInfo *const nameToken = nameTokens[i];
1477ba92e639SMasatake YAMATO vString **type = &(nameTypes[i++]);
1478bbb831cfSColomban Wendling
14799a4b69e0SColomban Wendling readToken (token);
14800c188d12SColomban Wendling
1481bbb831cfSColomban Wendling if (! nameToken)
1482bbb831cfSColomban Wendling /* nothing */;
1483bbb831cfSColomban Wendling else if (token->keyword != KEYWORD_lambda)
1484ba92e639SMasatake YAMATO {
1485ba92e639SMasatake YAMATO int index = makeSimplePythonTag (nameToken, kind);
1486ba92e639SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (index);
1487ba92e639SMasatake YAMATO if (e && *type)
1488ba92e639SMasatake YAMATO {
1489ba92e639SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
1490ba92e639SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (*type);
1491ba92e639SMasatake YAMATO *type = NULL;
1492ba92e639SMasatake YAMATO }
1493ba92e639SMasatake YAMATO }
14949a4b69e0SColomban Wendling else
14959a4b69e0SColomban Wendling {
149671b09f08SMasatake YAMATO tokenInfo *anon = NULL;
14979a4b69e0SColomban Wendling vString *arglist = vStringNew ();
149871b09f08SMasatake YAMATO if (*type)
149971b09f08SMasatake YAMATO {
150071b09f08SMasatake YAMATO anon = newToken ();
150171b09f08SMasatake YAMATO copyToken (anon, token);
150271b09f08SMasatake YAMATO }
15039a4b69e0SColomban Wendling readToken (token);
15049a4b69e0SColomban Wendling vStringPut (arglist, '(');
15059a4b69e0SColomban Wendling skipLambdaArglist (token, arglist);
15069a4b69e0SColomban Wendling vStringPut (arglist, ')');
150771b09f08SMasatake YAMATO if (*type)
150871b09f08SMasatake YAMATO {
150971b09f08SMasatake YAMATO /* How to handle lambda assigned to a variable
151071b09f08SMasatake YAMATO * --------------------------------------------
1511ba92e639SMasatake YAMATO *
151271b09f08SMasatake YAMATO * input.py:
1513ba92e639SMasatake YAMATO *
151471b09f08SMasatake YAMATO * id = lambda var: var
151571b09f08SMasatake YAMATO * id_t: Callable[[int], int] = lambda var: var
1516ba92e639SMasatake YAMATO *
151771b09f08SMasatake YAMATO * `id' is tagged as a function kind object like:
1518ba92e639SMasatake YAMATO *
151971b09f08SMasatake YAMATO * id input.py /^id = lambda var: var$/;" function
1520ba92e639SMasatake YAMATO *
152171b09f08SMasatake YAMATO * For `id_t' we cannot do the same as `id'.
1522ba92e639SMasatake YAMATO *
152371b09f08SMasatake YAMATO * We should not store `Callable[[int], int]' to typeref
152471b09f08SMasatake YAMATO * field of the tag of `id_t' if the tag has "function" as
152571b09f08SMasatake YAMATO * its kind because users expect the typeref field of a
152671b09f08SMasatake YAMATO * function kind represents a type for the value returned
152771b09f08SMasatake YAMATO * from the function (return type).
1528ba92e639SMasatake YAMATO *
152971b09f08SMasatake YAMATO * the unexpected tag:
1530ba92e639SMasatake YAMATO *
153171b09f08SMasatake YAMATO * id_t input.py /^id_t: Callable[[int], int] = lambda var: var$/;" function \
153271b09f08SMasatake YAMATO * typeref:typename:Callable[[int], int]
1533ba92e639SMasatake YAMATO *
153471b09f08SMasatake YAMATO * If we make a tag for `id_t' as a function, we should
153571b09f08SMasatake YAMATO * attach `typeref:typename:int' and `signature:(int)'. To
153671b09f08SMasatake YAMATO * achieve this, we have to make ctags analyze
153771b09f08SMasatake YAMATO * `Callable[[int], int]'. However, we want to avoid the
153871b09f08SMasatake YAMATO * level of analyzing.
1539ba92e639SMasatake YAMATO *
154071b09f08SMasatake YAMATO * For recording `Callable[[int], int]', a valuable
154171b09f08SMasatake YAMATO * information in the input, we use indirection.
154271b09f08SMasatake YAMATO *
154371b09f08SMasatake YAMATO * id_t input.py /^id_t: Callable[[int], int] = lambda var: var$/;" variable \
154471b09f08SMasatake YAMATO * typeref:typename:Callable[[int], int] nameref:function:anonFuncNNN
154571b09f08SMasatake YAMATO * anonFuncNNN input.py /^id_t: Callable[[int], int] = lambda var: var$/;" function \
154671b09f08SMasatake YAMATO * extras:anonymous
1547ba92e639SMasatake YAMATO */
154871b09f08SMasatake YAMATO int vindex = makeSimplePythonTag (nameToken, kind);
154971b09f08SMasatake YAMATO vStringClear (anon->string);
155071b09f08SMasatake YAMATO anonGenerate (anon->string, "anonFunc", K_FUNCTION);
155171b09f08SMasatake YAMATO int findex = makeFunctionTag (anon, arglist, NULL);
155271b09f08SMasatake YAMATO tagEntryInfo *fe = getEntryInCorkQueue (findex);
155371b09f08SMasatake YAMATO if (fe)
155471b09f08SMasatake YAMATO markTagExtraBit (fe, XTAG_ANONYMOUS);
155571b09f08SMasatake YAMATO
155671b09f08SMasatake YAMATO tagEntryInfo *ve = getEntryInCorkQueue (vindex);
155771b09f08SMasatake YAMATO if (ve)
155871b09f08SMasatake YAMATO {
155971b09f08SMasatake YAMATO ve->extensionFields.typeRef [0] = eStrdup ("typename");
156071b09f08SMasatake YAMATO ve->extensionFields.typeRef [1] = vStringDeleteUnwrap (*type);
156171b09f08SMasatake YAMATO *type = NULL;
156271b09f08SMasatake YAMATO vString *nameref = vStringNewInit (PythonKinds [K_FUNCTION].name);
156371b09f08SMasatake YAMATO vStringPut (nameref, ':');
156471b09f08SMasatake YAMATO vStringCat (nameref, anon->string);
156571b09f08SMasatake YAMATO attachParserField (ve, true, PythonFields[F_NAMEREF].ftype,
156671b09f08SMasatake YAMATO vStringValue (nameref));
156771b09f08SMasatake YAMATO vStringDelete (nameref);
156871b09f08SMasatake YAMATO }
156971b09f08SMasatake YAMATO if (anon)
157071b09f08SMasatake YAMATO deleteToken (anon);
157171b09f08SMasatake YAMATO }
157271b09f08SMasatake YAMATO else
157371b09f08SMasatake YAMATO makeFunctionTag (nameToken, arglist, NULL);
15749a4b69e0SColomban Wendling vStringDelete (arglist);
15759a4b69e0SColomban Wendling }
15769a4b69e0SColomban Wendling
15770c188d12SColomban Wendling /* skip until next initializer */
15780c188d12SColomban Wendling while ((TokenContinuationDepth > 0 || token->type != ',') &&
15790c188d12SColomban Wendling token->type != TOKEN_EOF &&
1580cf4e7a83SColomban Wendling token->type != ';' &&
15810c188d12SColomban Wendling token->type != TOKEN_INDENT)
15820c188d12SColomban Wendling {
15830c188d12SColomban Wendling readToken (token);
15840c188d12SColomban Wendling }
15850c188d12SColomban Wendling }
15860c188d12SColomban Wendling while (token->type == ',' && i < nameCount);
15870c188d12SColomban Wendling
15880c188d12SColomban Wendling /* if we got leftover to initialize, just make variables out of them.
15890c188d12SColomban Wendling * This handles cases like `a, b, c = (c, d, e)` -- or worse */
15905e8ffad2SColomban Wendling for (; i < nameCount; i++)
15915e8ffad2SColomban Wendling {
15925e8ffad2SColomban Wendling if (nameTokens[i])
15935e8ffad2SColomban Wendling makeSimplePythonTag (nameTokens[i], kind);
15945e8ffad2SColomban Wendling }
15950c188d12SColomban Wendling }
15960c188d12SColomban Wendling
15970c188d12SColomban Wendling while (nameCount > 0)
1598bbb831cfSColomban Wendling {
1599bbb831cfSColomban Wendling if (nameTokens[--nameCount])
16006ff4799bSJiří Techet deleteToken (nameTokens[nameCount]);
1601ba92e639SMasatake YAMATO vStringDelete (nameTypes[nameCount]); /* NULL is acceptable. */
1602bbb831cfSColomban Wendling }
16039a4b69e0SColomban Wendling
1604ce990805SThomas Braun return false;
16059a4b69e0SColomban Wendling }
16069a4b69e0SColomban Wendling
16077489fd61SMasatake YAMATO /* pops any level >= to indent */
setIndent(tokenInfo * const token)16087489fd61SMasatake YAMATO static void setIndent (tokenInfo *const token)
16097489fd61SMasatake YAMATO {
16107489fd61SMasatake YAMATO NestingLevel *lv = nestingLevelsGetCurrent (PythonNestingLevels);
16117489fd61SMasatake YAMATO
16127489fd61SMasatake YAMATO while (lv && PY_NL (lv)->indentation >= token->indent)
16137489fd61SMasatake YAMATO {
16143afb5475SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (lv->corkIndex);
16153671ad72SMasatake YAMATO if (e)
16167489fd61SMasatake YAMATO e->extensionFields.endLine = token->lineNumber;
16177489fd61SMasatake YAMATO
16187489fd61SMasatake YAMATO nestingLevelsPop (PythonNestingLevels);
16197489fd61SMasatake YAMATO lv = nestingLevelsGetCurrent (PythonNestingLevels);
16207489fd61SMasatake YAMATO }
16217489fd61SMasatake YAMATO }
16227489fd61SMasatake YAMATO
findPythonTags(void)16237489fd61SMasatake YAMATO static void findPythonTags (void)
16247489fd61SMasatake YAMATO {
16256ff4799bSJiří Techet tokenInfo *const token = newToken ();
16265d0fd5feSColomban Wendling vString *decorators = vStringNew ();
1627ce990805SThomas Braun bool atStatementStart = true;
16287489fd61SMasatake YAMATO
16297489fd61SMasatake YAMATO TokenContinuationDepth = 0;
16307489fd61SMasatake YAMATO NextToken = NULL;
16317489fd61SMasatake YAMATO PythonNestingLevels = nestingLevelsNew (sizeof (struct pythonNestingLevelUserData));
16327489fd61SMasatake YAMATO
16337489fd61SMasatake YAMATO readToken (token);
16347489fd61SMasatake YAMATO while (token->type != TOKEN_EOF)
16357489fd61SMasatake YAMATO {
16365d0fd5feSColomban Wendling tokenType iterationTokenType = token->type;
1637ce990805SThomas Braun bool readNext = true;
16387489fd61SMasatake YAMATO
163916845a4eSColomban Wendling /* skip async keyword that confuses decorator parsing before a def */
164016845a4eSColomban Wendling if (token->keyword == KEYWORD_async)
164116845a4eSColomban Wendling readToken (token);
164216845a4eSColomban Wendling
16437489fd61SMasatake YAMATO if (token->type == TOKEN_INDENT)
16447489fd61SMasatake YAMATO setIndent (token);
16457489fd61SMasatake YAMATO else if (token->keyword == KEYWORD_class ||
16467489fd61SMasatake YAMATO token->keyword == KEYWORD_def)
16477489fd61SMasatake YAMATO {
16487489fd61SMasatake YAMATO pythonKind kind = token->keyword == KEYWORD_class ? K_CLASS : K_FUNCTION;
16497489fd61SMasatake YAMATO
1650ce990805SThomas Braun readNext = parseClassOrDef (token, decorators, kind, false);
16517489fd61SMasatake YAMATO }
16527489fd61SMasatake YAMATO else if (token->keyword == KEYWORD_cdef ||
16537489fd61SMasatake YAMATO token->keyword == KEYWORD_cpdef)
16547489fd61SMasatake YAMATO {
1655ce990805SThomas Braun readNext = parseClassOrDef (token, decorators, K_FUNCTION, true);
16567489fd61SMasatake YAMATO }
16577489fd61SMasatake YAMATO else if (token->keyword == KEYWORD_from ||
16587489fd61SMasatake YAMATO token->keyword == KEYWORD_import)
16597489fd61SMasatake YAMATO {
16607489fd61SMasatake YAMATO readNext = parseImport (token);
1661f5f8bd9aSMasatake YAMATO }
16622ff1f9d2SColomban Wendling else if (token->type == '(')
16632ff1f9d2SColomban Wendling { /* skip parentheses to avoid finding stuff inside them */
1664ce990805SThomas Braun readNext = skipOverPair (token, '(', ')', NULL, false);
1665f5f8bd9aSMasatake YAMATO }
1666cf4e7a83SColomban Wendling else if (token->type == TOKEN_IDENTIFIER && atStatementStart)
1667f5f8bd9aSMasatake YAMATO {
16682ff1f9d2SColomban Wendling NestingLevel *lv = nestingLevelsGetCurrent (PythonNestingLevels);
16692ff1f9d2SColomban Wendling tagEntryInfo *lvEntry = getEntryOfNestingLevel (lv);
167098a8ebe8SColomban Wendling pythonKind kind = K_VARIABLE;
16713ae02089SMasatake YAMATO
1672f92e6bf2SMasatake YAMATO if (lvEntry && lvEntry->kindIndex != K_CLASS)
167398a8ebe8SColomban Wendling kind = K_LOCAL_VARIABLE;
167498a8ebe8SColomban Wendling
167598a8ebe8SColomban Wendling readNext = parseVariable (token, kind);
16763ae02089SMasatake YAMATO }
16775d0fd5feSColomban Wendling else if (token->type == '@' && atStatementStart &&
16785d0fd5feSColomban Wendling PythonFields[F_DECORATORS].enabled)
16795d0fd5feSColomban Wendling {
16805d0fd5feSColomban Wendling /* collect decorators */
16815d0fd5feSColomban Wendling readQualifiedName (token);
16825d0fd5feSColomban Wendling if (token->type != TOKEN_IDENTIFIER)
1683ce990805SThomas Braun readNext = false;
16845d0fd5feSColomban Wendling else
16855d0fd5feSColomban Wendling {
16865d0fd5feSColomban Wendling if (vStringLength (decorators) > 0)
16875d0fd5feSColomban Wendling vStringPut (decorators, ',');
16885d0fd5feSColomban Wendling vStringCat (decorators, token->string);
16895d0fd5feSColomban Wendling readToken (token);
1690ce990805SThomas Braun readNext = skipOverPair (token, '(', ')', decorators, true);
16915d0fd5feSColomban Wendling }
16925d0fd5feSColomban Wendling }
16935d0fd5feSColomban Wendling
16945d0fd5feSColomban Wendling /* clear collected decorators for any non-decorator tokens non-indent
16955d0fd5feSColomban Wendling * token. decorator collection takes care of skipping the possible
16965d0fd5feSColomban Wendling * argument list, so we should never hit here parsing a decorator */
16975d0fd5feSColomban Wendling if (iterationTokenType != TOKEN_INDENT &&
16985d0fd5feSColomban Wendling iterationTokenType != '@' &&
16995d0fd5feSColomban Wendling PythonFields[F_DECORATORS].enabled)
17005d0fd5feSColomban Wendling {
17015d0fd5feSColomban Wendling vStringClear (decorators);
17025d0fd5feSColomban Wendling }
17036c11b8afSMasatake YAMATO
1704cf4e7a83SColomban Wendling atStatementStart = (token->type == TOKEN_INDENT || token->type == ';');
17056c11b8afSMasatake YAMATO
17062ff1f9d2SColomban Wendling if (readNext)
17072ff1f9d2SColomban Wendling readToken (token);
17082ff1f9d2SColomban Wendling }
17092ff1f9d2SColomban Wendling
17102ff1f9d2SColomban Wendling nestingLevelsFree (PythonNestingLevels);
17115d0fd5feSColomban Wendling vStringDelete (decorators);
17126ff4799bSJiří Techet deleteToken (token);
17132ff1f9d2SColomban Wendling Assert (NextToken == NULL);
17142ff1f9d2SColomban Wendling }
17152ff1f9d2SColomban Wendling
initialize(const langType language)17162ff1f9d2SColomban Wendling static void initialize (const langType language)
17172ff1f9d2SColomban Wendling {
17182ff1f9d2SColomban Wendling Lang_python = language;
1719d3bb2b5aSJiří Techet
1720e013efc1SMasatake YAMATO TokenPool = objPoolNew (16, newPoolToken, deletePoolToken, clearPoolToken, NULL);
1721d3bb2b5aSJiří Techet }
1722d3bb2b5aSJiří Techet
finalize(langType language CTAGS_ATTR_UNUSED,bool initialized)1723d3bb2b5aSJiří Techet static void finalize (langType language CTAGS_ATTR_UNUSED, bool initialized)
1724d3bb2b5aSJiří Techet {
1725d3bb2b5aSJiří Techet if (!initialized)
1726d3bb2b5aSJiří Techet return;
1727d3bb2b5aSJiří Techet
1728d3bb2b5aSJiří Techet objPoolDelete (TokenPool);
17293ae02089SMasatake YAMATO }
17303ae02089SMasatake YAMATO
PythonParser(void)17313ae02089SMasatake YAMATO extern parserDefinition* PythonParser (void)
17323ae02089SMasatake YAMATO {
1733ce0d6577SMasatake YAMATO static const char *const extensions[] = { "py", "pyx", "pxd", "pxi", "scons",
1734ce0d6577SMasatake YAMATO "wsgi", NULL };
17352ff1f9d2SColomban Wendling static const char *const aliases[] = { "python[23]*", "scons", NULL };
17363ae02089SMasatake YAMATO parserDefinition *def = parserNew ("Python");
173709ae690fSMasatake YAMATO def->kindTable = PythonKinds;
17383db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (PythonKinds);
17393ae02089SMasatake YAMATO def->extensions = extensions;
17403ae02089SMasatake YAMATO def->aliases = aliases;
17413ae02089SMasatake YAMATO def->parser = findPythonTags;
17422ff1f9d2SColomban Wendling def->initialize = initialize;
1743d3bb2b5aSJiří Techet def->finalize = finalize;
1744b0470ee9SMasatake YAMATO def->keywordTable = PythonKeywordTable;
1745b0470ee9SMasatake YAMATO def->keywordCount = ARRAY_SIZE (PythonKeywordTable);
1746a739fa5fSMasatake YAMATO def->fieldTable = PythonFields;
1747a739fa5fSMasatake YAMATO def->fieldCount = ARRAY_SIZE (PythonFields);
17486b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
1749ce990805SThomas Braun def->requestAutomaticFQTag = true;
17503ae02089SMasatake YAMATO return def;
17513ae02089SMasatake YAMATO }
1752