13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2013, Colomban Wendling <ban@herbesfolles.org>
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO * This module contains code for generating tags for the PHP scripting
83ae02089SMasatake YAMATO * language.
91b68ab24SMasatake YAMATO *
101b68ab24SMasatake YAMATO * The language reference: http://php.net/manual/en/langref.php
113ae02089SMasatake YAMATO */
123ae02089SMasatake YAMATO
133ae02089SMasatake YAMATO /*
143ae02089SMasatake YAMATO * INCLUDE FILES
153ae02089SMasatake YAMATO */
163ae02089SMasatake YAMATO #include "general.h" /* must always come first */
1746f05046SMasatake YAMATO
1846f05046SMasatake YAMATO #include <string.h>
1946f05046SMasatake YAMATO
203ae02089SMasatake YAMATO #include "parse.h"
213ae02089SMasatake YAMATO #include "read.h"
223ae02089SMasatake YAMATO #include "vstring.h"
233ae02089SMasatake YAMATO #include "keyword.h"
243ae02089SMasatake YAMATO #include "entry.h"
253ae02089SMasatake YAMATO #include "routines.h"
263ae02089SMasatake YAMATO #include "debug.h"
270988269fSJiří Techet #include "objpool.h"
28*f476dfe1SMasatake YAMATO #include "promise.h"
293ae02089SMasatake YAMATO
302b28d0e0SJiří Techet #define isIdentChar(c) (isalnum (c) || (c) == '_' || (c) >= 0x80)
310988269fSJiří Techet #define newToken() (objPoolGet (TokenPool))
320988269fSJiří Techet #define deleteToken(t) (objPoolPut (TokenPool, (t)))
333ae02089SMasatake YAMATO
344faa2076SColomban Wendling enum {
353ae02089SMasatake YAMATO KEYWORD_abstract,
363ae02089SMasatake YAMATO KEYWORD_and,
373ae02089SMasatake YAMATO KEYWORD_as,
383ae02089SMasatake YAMATO KEYWORD_break,
393ae02089SMasatake YAMATO KEYWORD_callable,
403ae02089SMasatake YAMATO KEYWORD_case,
413ae02089SMasatake YAMATO KEYWORD_catch,
423ae02089SMasatake YAMATO KEYWORD_class,
433ae02089SMasatake YAMATO KEYWORD_clone,
443ae02089SMasatake YAMATO KEYWORD_const,
453ae02089SMasatake YAMATO KEYWORD_continue,
463ae02089SMasatake YAMATO KEYWORD_declare,
473ae02089SMasatake YAMATO KEYWORD_define,
483ae02089SMasatake YAMATO KEYWORD_default,
493ae02089SMasatake YAMATO KEYWORD_do,
503ae02089SMasatake YAMATO KEYWORD_echo,
513ae02089SMasatake YAMATO KEYWORD_else,
523ae02089SMasatake YAMATO KEYWORD_elif,
533ae02089SMasatake YAMATO KEYWORD_enddeclare,
543ae02089SMasatake YAMATO KEYWORD_endfor,
553ae02089SMasatake YAMATO KEYWORD_endforeach,
563ae02089SMasatake YAMATO KEYWORD_endif,
573ae02089SMasatake YAMATO KEYWORD_endswitch,
583ae02089SMasatake YAMATO KEYWORD_endwhile,
593ae02089SMasatake YAMATO KEYWORD_extends,
603ae02089SMasatake YAMATO KEYWORD_final,
613ae02089SMasatake YAMATO KEYWORD_finally,
623ae02089SMasatake YAMATO KEYWORD_for,
633ae02089SMasatake YAMATO KEYWORD_foreach,
643ae02089SMasatake YAMATO KEYWORD_function,
653ae02089SMasatake YAMATO KEYWORD_global,
663ae02089SMasatake YAMATO KEYWORD_goto,
673ae02089SMasatake YAMATO KEYWORD_if,
683ae02089SMasatake YAMATO KEYWORD_implements,
693ae02089SMasatake YAMATO KEYWORD_include,
703ae02089SMasatake YAMATO KEYWORD_include_once,
713ae02089SMasatake YAMATO KEYWORD_instanceof,
723ae02089SMasatake YAMATO KEYWORD_insteadof,
733ae02089SMasatake YAMATO KEYWORD_interface,
743ae02089SMasatake YAMATO KEYWORD_namespace,
753ae02089SMasatake YAMATO KEYWORD_new,
763ae02089SMasatake YAMATO KEYWORD_or,
773ae02089SMasatake YAMATO KEYWORD_print,
783ae02089SMasatake YAMATO KEYWORD_private,
793ae02089SMasatake YAMATO KEYWORD_protected,
803ae02089SMasatake YAMATO KEYWORD_public,
813ae02089SMasatake YAMATO KEYWORD_require,
823ae02089SMasatake YAMATO KEYWORD_require_once,
833ae02089SMasatake YAMATO KEYWORD_return,
843ae02089SMasatake YAMATO KEYWORD_static,
853ae02089SMasatake YAMATO KEYWORD_switch,
863ae02089SMasatake YAMATO KEYWORD_throw,
873ae02089SMasatake YAMATO KEYWORD_trait,
883ae02089SMasatake YAMATO KEYWORD_try,
893ae02089SMasatake YAMATO KEYWORD_use,
903ae02089SMasatake YAMATO KEYWORD_var,
913ae02089SMasatake YAMATO KEYWORD_while,
923ae02089SMasatake YAMATO KEYWORD_xor,
933ae02089SMasatake YAMATO KEYWORD_yield
944faa2076SColomban Wendling };
954faa2076SColomban Wendling typedef int keywordId; /* to allow KEYWORD_NONE */
963ae02089SMasatake YAMATO
973ae02089SMasatake YAMATO typedef enum {
983ae02089SMasatake YAMATO ACCESS_UNDEFINED,
993ae02089SMasatake YAMATO ACCESS_PRIVATE,
1003ae02089SMasatake YAMATO ACCESS_PROTECTED,
1013ae02089SMasatake YAMATO ACCESS_PUBLIC,
1023ae02089SMasatake YAMATO COUNT_ACCESS
1033ae02089SMasatake YAMATO } accessType;
1043ae02089SMasatake YAMATO
1053ae02089SMasatake YAMATO typedef enum {
1063ae02089SMasatake YAMATO IMPL_UNDEFINED,
1073ae02089SMasatake YAMATO IMPL_ABSTRACT,
1083ae02089SMasatake YAMATO COUNT_IMPL
1093ae02089SMasatake YAMATO } implType;
1103ae02089SMasatake YAMATO
1113ae02089SMasatake YAMATO typedef enum {
1123ae02089SMasatake YAMATO K_CLASS,
1133ae02089SMasatake YAMATO K_DEFINE,
1143ae02089SMasatake YAMATO K_FUNCTION,
1153ae02089SMasatake YAMATO K_INTERFACE,
1163ae02089SMasatake YAMATO K_LOCAL_VARIABLE,
1173ae02089SMasatake YAMATO K_NAMESPACE,
1183ae02089SMasatake YAMATO K_TRAIT,
1193ae02089SMasatake YAMATO K_VARIABLE,
120c65c05feSColomban Wendling K_ALIAS,
1213ae02089SMasatake YAMATO COUNT_KIND
1223ae02089SMasatake YAMATO } phpKind;
1233ae02089SMasatake YAMATO
124a4af1067SMasatake YAMATO #define NAMESPACE_SEPARATOR "\\"
125a4af1067SMasatake YAMATO static scopeSeparator PhpGenericSeparators [] = {
126f92e6bf2SMasatake YAMATO { K_NAMESPACE , NAMESPACE_SEPARATOR },
127f92e6bf2SMasatake YAMATO { KIND_WILDCARD_INDEX, "::" },
128a4af1067SMasatake YAMATO };
129a4af1067SMasatake YAMATO
130e112e8abSMasatake YAMATO static kindDefinition PhpKinds[COUNT_KIND] = {
131ce990805SThomas Braun { true, 'c', "class", "classes",
132a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators) },
133ce990805SThomas Braun { true, 'd', "define", "constant definitions",
134a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
135ce990805SThomas Braun { true, 'f', "function", "functions",
136a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
137ce990805SThomas Braun { true, 'i', "interface", "interfaces",
138a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
139ce990805SThomas Braun { false, 'l', "local", "local variables",
140a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
141ce990805SThomas Braun { true, 'n', "namespace", "namespaces",
142a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
143ce990805SThomas Braun { true, 't', "trait", "traits",
144a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
145ce990805SThomas Braun { true, 'v', "variable", "variables",
146a4af1067SMasatake YAMATO ATTACH_SEPARATORS(PhpGenericSeparators)},
147ce990805SThomas Braun { true, 'a', "alias", "aliases",
148c65c05feSColomban Wendling ATTACH_SEPARATORS(PhpGenericSeparators)},
1493ae02089SMasatake YAMATO };
1503ae02089SMasatake YAMATO
15182c11d8cSRich Siegel static const keywordTable PhpKeywordTable[] = {
1523ae02089SMasatake YAMATO /* keyword keyword ID */
1533ae02089SMasatake YAMATO { "abstract", KEYWORD_abstract },
1543ae02089SMasatake YAMATO { "and", KEYWORD_and },
1553ae02089SMasatake YAMATO { "as", KEYWORD_as },
1563ae02089SMasatake YAMATO { "break", KEYWORD_break },
1573ae02089SMasatake YAMATO { "callable", KEYWORD_callable },
1583ae02089SMasatake YAMATO { "case", KEYWORD_case },
1593ae02089SMasatake YAMATO { "catch", KEYWORD_catch },
1603ae02089SMasatake YAMATO { "cfunction", KEYWORD_function }, /* nobody knows what the hell this is, but it seems to behave much like "function" so bind it to it */
1613ae02089SMasatake YAMATO { "class", KEYWORD_class },
1623ae02089SMasatake YAMATO { "clone", KEYWORD_clone },
1633ae02089SMasatake YAMATO { "const", KEYWORD_const },
1643ae02089SMasatake YAMATO { "continue", KEYWORD_continue },
1653ae02089SMasatake YAMATO { "declare", KEYWORD_declare },
1663ae02089SMasatake YAMATO { "define", KEYWORD_define }, /* this isn't really a keyword but we handle it so it's easier this way */
1673ae02089SMasatake YAMATO { "default", KEYWORD_default },
1683ae02089SMasatake YAMATO { "do", KEYWORD_do },
1693ae02089SMasatake YAMATO { "echo", KEYWORD_echo },
1703ae02089SMasatake YAMATO { "else", KEYWORD_else },
1713ae02089SMasatake YAMATO { "elseif", KEYWORD_elif },
1723ae02089SMasatake YAMATO { "enddeclare", KEYWORD_enddeclare },
1733ae02089SMasatake YAMATO { "endfor", KEYWORD_endfor },
1743ae02089SMasatake YAMATO { "endforeach", KEYWORD_endforeach },
1753ae02089SMasatake YAMATO { "endif", KEYWORD_endif },
1763ae02089SMasatake YAMATO { "endswitch", KEYWORD_endswitch },
1773ae02089SMasatake YAMATO { "endwhile", KEYWORD_endwhile },
1783ae02089SMasatake YAMATO { "extends", KEYWORD_extends },
1793ae02089SMasatake YAMATO { "final", KEYWORD_final },
1803ae02089SMasatake YAMATO { "finally", KEYWORD_finally },
1813ae02089SMasatake YAMATO { "for", KEYWORD_for },
1823ae02089SMasatake YAMATO { "foreach", KEYWORD_foreach },
1833ae02089SMasatake YAMATO { "function", KEYWORD_function },
1843ae02089SMasatake YAMATO { "global", KEYWORD_global },
1853ae02089SMasatake YAMATO { "goto", KEYWORD_goto },
1863ae02089SMasatake YAMATO { "if", KEYWORD_if },
1873ae02089SMasatake YAMATO { "implements", KEYWORD_implements },
1883ae02089SMasatake YAMATO { "include", KEYWORD_include },
1893ae02089SMasatake YAMATO { "include_once", KEYWORD_include_once },
1903ae02089SMasatake YAMATO { "instanceof", KEYWORD_instanceof },
1913ae02089SMasatake YAMATO { "insteadof", KEYWORD_insteadof },
1923ae02089SMasatake YAMATO { "interface", KEYWORD_interface },
1933ae02089SMasatake YAMATO { "namespace", KEYWORD_namespace },
1943ae02089SMasatake YAMATO { "new", KEYWORD_new },
1953ae02089SMasatake YAMATO { "or", KEYWORD_or },
1963ae02089SMasatake YAMATO { "print", KEYWORD_print },
1973ae02089SMasatake YAMATO { "private", KEYWORD_private },
1983ae02089SMasatake YAMATO { "protected", KEYWORD_protected },
1993ae02089SMasatake YAMATO { "public", KEYWORD_public },
2003ae02089SMasatake YAMATO { "require", KEYWORD_require },
2013ae02089SMasatake YAMATO { "require_once", KEYWORD_require_once },
2023ae02089SMasatake YAMATO { "return", KEYWORD_return },
2033ae02089SMasatake YAMATO { "static", KEYWORD_static },
2043ae02089SMasatake YAMATO { "switch", KEYWORD_switch },
2053ae02089SMasatake YAMATO { "throw", KEYWORD_throw },
2063ae02089SMasatake YAMATO { "trait", KEYWORD_trait },
2073ae02089SMasatake YAMATO { "try", KEYWORD_try },
2083ae02089SMasatake YAMATO { "use", KEYWORD_use },
2093ae02089SMasatake YAMATO { "var", KEYWORD_var },
2103ae02089SMasatake YAMATO { "while", KEYWORD_while },
2113ae02089SMasatake YAMATO { "xor", KEYWORD_xor },
2123ae02089SMasatake YAMATO { "yield", KEYWORD_yield }
2133ae02089SMasatake YAMATO };
2143ae02089SMasatake YAMATO
2153ae02089SMasatake YAMATO
2163ae02089SMasatake YAMATO typedef enum eTokenType {
2173ae02089SMasatake YAMATO TOKEN_UNDEFINED,
2183ae02089SMasatake YAMATO TOKEN_EOF,
2193ae02089SMasatake YAMATO TOKEN_CHARACTER,
2203ae02089SMasatake YAMATO TOKEN_CLOSE_PAREN,
2213ae02089SMasatake YAMATO TOKEN_SEMICOLON,
2223ae02089SMasatake YAMATO TOKEN_COLON,
2233ae02089SMasatake YAMATO TOKEN_COMMA,
2243ae02089SMasatake YAMATO TOKEN_KEYWORD,
2253ae02089SMasatake YAMATO TOKEN_OPEN_PAREN,
2263ae02089SMasatake YAMATO TOKEN_OPERATOR,
2273ae02089SMasatake YAMATO TOKEN_IDENTIFIER,
2283ae02089SMasatake YAMATO TOKEN_STRING,
2293ae02089SMasatake YAMATO TOKEN_PERIOD,
2303ae02089SMasatake YAMATO TOKEN_OPEN_CURLY,
2313ae02089SMasatake YAMATO TOKEN_CLOSE_CURLY,
2323ae02089SMasatake YAMATO TOKEN_EQUAL_SIGN,
2333ae02089SMasatake YAMATO TOKEN_OPEN_SQUARE,
2343ae02089SMasatake YAMATO TOKEN_CLOSE_SQUARE,
2353ae02089SMasatake YAMATO TOKEN_VARIABLE,
236acbcd162SColomban Wendling TOKEN_AMPERSAND,
23751f37d45SMasatake YAMATO TOKEN_BACKSLASH,
23851f37d45SMasatake YAMATO TOKEN_QMARK,
2393ae02089SMasatake YAMATO } tokenType;
2403ae02089SMasatake YAMATO
2413ae02089SMasatake YAMATO typedef struct {
2423ae02089SMasatake YAMATO tokenType type;
2433ae02089SMasatake YAMATO keywordId keyword;
2443ae02089SMasatake YAMATO vString * string;
2453ae02089SMasatake YAMATO vString * scope;
2463ae02089SMasatake YAMATO unsigned long lineNumber;
247509a47dbSJiří Techet MIOPos filePosition;
2483ae02089SMasatake YAMATO int parentKind; /* -1 if none */
2493165d268SMasatake YAMATO bool anonymous; /* true if token specifies
2503165d268SMasatake YAMATO * an anonymous class */
2513ae02089SMasatake YAMATO } tokenInfo;
2523ae02089SMasatake YAMATO
2533ae02089SMasatake YAMATO static langType Lang_php;
2543ae02089SMasatake YAMATO static langType Lang_zephir;
2553ae02089SMasatake YAMATO
256ce990805SThomas Braun static bool InPhp = false; /* whether we are between <? ?> */
25775ba24d4SColomban Wendling /* whether the next token may be a keyword, e.g. not after "::" or "->" */
25875ba24d4SColomban Wendling static bool MayBeKeyword = true;
2593ae02089SMasatake YAMATO
2603ae02089SMasatake YAMATO /* current statement details */
2613ae02089SMasatake YAMATO static struct {
2623ae02089SMasatake YAMATO accessType access;
2633ae02089SMasatake YAMATO implType impl;
2643ae02089SMasatake YAMATO } CurrentStatement;
2653ae02089SMasatake YAMATO
2663ae02089SMasatake YAMATO /* Current namespace */
2673ae02089SMasatake YAMATO static vString *CurrentNamesapce;
2683ae02089SMasatake YAMATO /* Cache variable to build the tag's scope. It has no real meaning outside
2693ae02089SMasatake YAMATO * of initPhpEntry()'s scope. */
2703ae02089SMasatake YAMATO static vString *FullScope;
271f176923cSMasatake YAMATO /* The class name specified at "extends" keyword in the current class
272f176923cSMasatake YAMATO * definition. Used to resolve "parent" in return type. */
273f176923cSMasatake YAMATO static vString *ParentClass;
2743ae02089SMasatake YAMATO
2750988269fSJiří Techet static objPool *TokenPool = NULL;
2760988269fSJiří Techet
phpScopeSeparatorFor(int kind,int upperScopeKind)277c06d97daSColomban Wendling static const char *phpScopeSeparatorFor (int kind, int upperScopeKind)
278a4af1067SMasatake YAMATO {
279c06d97daSColomban Wendling return scopeSeparatorFor (getInputLanguage(), kind, upperScopeKind);
280a4af1067SMasatake YAMATO }
2813ae02089SMasatake YAMATO
accessToString(const accessType access)2823ae02089SMasatake YAMATO static const char *accessToString (const accessType access)
2833ae02089SMasatake YAMATO {
2843ae02089SMasatake YAMATO static const char *const names[COUNT_ACCESS] = {
2853ae02089SMasatake YAMATO "undefined",
2863ae02089SMasatake YAMATO "private",
2873ae02089SMasatake YAMATO "protected",
2883ae02089SMasatake YAMATO "public"
2893ae02089SMasatake YAMATO };
2903ae02089SMasatake YAMATO
2913ae02089SMasatake YAMATO Assert (access < COUNT_ACCESS);
2923ae02089SMasatake YAMATO
2933ae02089SMasatake YAMATO return names[access];
2943ae02089SMasatake YAMATO }
2953ae02089SMasatake YAMATO
implToString(const implType impl)2963ae02089SMasatake YAMATO static const char *implToString (const implType impl)
2973ae02089SMasatake YAMATO {
2983ae02089SMasatake YAMATO static const char *const names[COUNT_IMPL] = {
2993ae02089SMasatake YAMATO "undefined",
3003ae02089SMasatake YAMATO "abstract"
3013ae02089SMasatake YAMATO };
3023ae02089SMasatake YAMATO
3033ae02089SMasatake YAMATO Assert (impl < COUNT_IMPL);
3043ae02089SMasatake YAMATO
3053ae02089SMasatake YAMATO return names[impl];
3063ae02089SMasatake YAMATO }
3073ae02089SMasatake YAMATO
initPhpEntry(tagEntryInfo * const e,const tokenInfo * const token,const phpKind kind,const accessType access)3083ae02089SMasatake YAMATO static void initPhpEntry (tagEntryInfo *const e, const tokenInfo *const token,
3093ae02089SMasatake YAMATO const phpKind kind, const accessType access)
3103ae02089SMasatake YAMATO {
3113ae02089SMasatake YAMATO int parentKind = -1;
3123ae02089SMasatake YAMATO
3133ae02089SMasatake YAMATO vStringClear (FullScope);
3143ae02089SMasatake YAMATO
3153ae02089SMasatake YAMATO if (vStringLength (CurrentNamesapce) > 0)
3163ae02089SMasatake YAMATO {
3173ae02089SMasatake YAMATO parentKind = K_NAMESPACE;
318e9e86f51SMasatake YAMATO vStringCat (FullScope, CurrentNamesapce);
319e9e86f51SMasatake YAMATO
3203ae02089SMasatake YAMATO }
3213ae02089SMasatake YAMATO
32216a2541cSMasatake YAMATO initTagEntry (e, vStringValue (token->string), kind);
3233ae02089SMasatake YAMATO
3243ae02089SMasatake YAMATO e->lineNumber = token->lineNumber;
3253ae02089SMasatake YAMATO e->filePosition = token->filePosition;
3263ae02089SMasatake YAMATO
3273ae02089SMasatake YAMATO if (access != ACCESS_UNDEFINED)
3283ae02089SMasatake YAMATO e->extensionFields.access = accessToString (access);
3293ae02089SMasatake YAMATO if (vStringLength (token->scope) > 0)
3303ae02089SMasatake YAMATO {
3313ae02089SMasatake YAMATO parentKind = token->parentKind;
332a4af1067SMasatake YAMATO
3333ae02089SMasatake YAMATO if (vStringLength (FullScope) > 0)
334a4af1067SMasatake YAMATO {
335a4af1067SMasatake YAMATO const char* sep;
336a4af1067SMasatake YAMATO
337a4af1067SMasatake YAMATO sep = phpScopeSeparatorFor (parentKind,
338a4af1067SMasatake YAMATO K_NAMESPACE);
339a4af1067SMasatake YAMATO vStringCatS (FullScope, sep);
340a4af1067SMasatake YAMATO }
3413ae02089SMasatake YAMATO vStringCat (FullScope, token->scope);
3423ae02089SMasatake YAMATO }
3433ae02089SMasatake YAMATO if (vStringLength (FullScope) > 0)
3443ae02089SMasatake YAMATO {
3453ae02089SMasatake YAMATO Assert (parentKind >= 0);
3463ae02089SMasatake YAMATO
347f92e6bf2SMasatake YAMATO e->extensionFields.scopeKindIndex = parentKind;
348015ab54cSMasatake YAMATO e->extensionFields.scopeName = vStringValue (FullScope);
3493ae02089SMasatake YAMATO }
3503165d268SMasatake YAMATO
3513165d268SMasatake YAMATO if (token->anonymous)
3523165d268SMasatake YAMATO markTagExtraBit (e, XTAG_ANONYMOUS);
3533ae02089SMasatake YAMATO }
3543ae02089SMasatake YAMATO
makePhpTagEntry(tagEntryInfo * const e)3559014223fSMasatake YAMATO static void makePhpTagEntry (tagEntryInfo *const e)
3569014223fSMasatake YAMATO {
3579014223fSMasatake YAMATO makeTagEntry (e);
3589014223fSMasatake YAMATO makeQualifiedTagEntry (e);
3599014223fSMasatake YAMATO }
3605ed230b0SMasatake YAMATO
fillTypeRefField(tagEntryInfo * const e,const vString * const rtype,const tokenInfo * const token)3615ed230b0SMasatake YAMATO static void fillTypeRefField (tagEntryInfo *const e,
3625ed230b0SMasatake YAMATO const vString *const rtype, const tokenInfo *const token)
3635ed230b0SMasatake YAMATO {
3645ed230b0SMasatake YAMATO if ((vStringLength (rtype) == 4)
3655ed230b0SMasatake YAMATO && (strcmp (vStringValue (rtype), "self") == 0)
3665ed230b0SMasatake YAMATO && vStringLength (token->scope) > 0)
3675ed230b0SMasatake YAMATO {
3685ed230b0SMasatake YAMATO if (token->parentKind == -1)
3695ed230b0SMasatake YAMATO e->extensionFields.typeRef [0] = "unknown";
3705ed230b0SMasatake YAMATO else
3715ed230b0SMasatake YAMATO e->extensionFields.typeRef [0] = PhpKinds [token->parentKind].name;
3725ed230b0SMasatake YAMATO e->extensionFields.typeRef [1] = vStringValue (token->scope);
3735ed230b0SMasatake YAMATO }
3745ed230b0SMasatake YAMATO else if ((vStringLength (rtype) == 6)
3755ed230b0SMasatake YAMATO && (strcmp (vStringValue (rtype), "parent") == 0)
3765ed230b0SMasatake YAMATO && (ParentClass && vStringLength (ParentClass) > 0))
3775ed230b0SMasatake YAMATO {
3785ed230b0SMasatake YAMATO e->extensionFields.typeRef [0] = "class";
3795ed230b0SMasatake YAMATO e->extensionFields.typeRef [1] = vStringValue (ParentClass);
3805ed230b0SMasatake YAMATO }
3815ed230b0SMasatake YAMATO else
3825ed230b0SMasatake YAMATO {
3835ed230b0SMasatake YAMATO e->extensionFields.typeRef [0] = "unknown";
3845ed230b0SMasatake YAMATO e->extensionFields.typeRef [1] = vStringValue (rtype);
3855ed230b0SMasatake YAMATO }
3865ed230b0SMasatake YAMATO }
3875ed230b0SMasatake YAMATO
makeTypedPhpTag(const tokenInfo * const token,const phpKind kind,const accessType access,vString * typeName)3885ed230b0SMasatake YAMATO static void makeTypedPhpTag (const tokenInfo *const token, const phpKind kind,
3895ed230b0SMasatake YAMATO const accessType access, vString* typeName)
3903ae02089SMasatake YAMATO {
3913ae02089SMasatake YAMATO if (PhpKinds[kind].enabled)
3923ae02089SMasatake YAMATO {
3933ae02089SMasatake YAMATO tagEntryInfo e;
3943ae02089SMasatake YAMATO
3953ae02089SMasatake YAMATO initPhpEntry (&e, token, kind, access);
3965ed230b0SMasatake YAMATO if (typeName)
3975ed230b0SMasatake YAMATO fillTypeRefField (&e, typeName, token);
3989014223fSMasatake YAMATO makePhpTagEntry (&e);
3993ae02089SMasatake YAMATO }
4003ae02089SMasatake YAMATO }
4013ae02089SMasatake YAMATO
makeSimplePhpTag(const tokenInfo * const token,const phpKind kind,const accessType access)4025ed230b0SMasatake YAMATO static void makeSimplePhpTag (const tokenInfo *const token, const phpKind kind,
4035ed230b0SMasatake YAMATO const accessType access)
4045ed230b0SMasatake YAMATO {
4055ed230b0SMasatake YAMATO makeTypedPhpTag (token, kind, access, NULL);
4065ed230b0SMasatake YAMATO }
4075ed230b0SMasatake YAMATO
makeNamespacePhpTag(const tokenInfo * const token,const vString * const name)4083ae02089SMasatake YAMATO static void makeNamespacePhpTag (const tokenInfo *const token, const vString *const name)
4093ae02089SMasatake YAMATO {
4103ae02089SMasatake YAMATO if (PhpKinds[K_NAMESPACE].enabled)
4113ae02089SMasatake YAMATO {
4123ae02089SMasatake YAMATO tagEntryInfo e;
4133ae02089SMasatake YAMATO
41416a2541cSMasatake YAMATO initTagEntry (&e, vStringValue (name), K_NAMESPACE);
4153ae02089SMasatake YAMATO
4163ae02089SMasatake YAMATO e.lineNumber = token->lineNumber;
4173ae02089SMasatake YAMATO e.filePosition = token->filePosition;
4183ae02089SMasatake YAMATO
4199014223fSMasatake YAMATO makePhpTagEntry (&e);
4203ae02089SMasatake YAMATO }
4213ae02089SMasatake YAMATO }
4223ae02089SMasatake YAMATO
makeClassOrIfaceTag(const phpKind kind,const tokenInfo * const token,vString * const inheritance,const implType impl)4233ae02089SMasatake YAMATO static void makeClassOrIfaceTag (const phpKind kind, const tokenInfo *const token,
4243ae02089SMasatake YAMATO vString *const inheritance, const implType impl)
4253ae02089SMasatake YAMATO {
4263ae02089SMasatake YAMATO if (PhpKinds[kind].enabled)
4273ae02089SMasatake YAMATO {
4283ae02089SMasatake YAMATO tagEntryInfo e;
4293ae02089SMasatake YAMATO
4303ae02089SMasatake YAMATO initPhpEntry (&e, token, kind, ACCESS_UNDEFINED);
4313ae02089SMasatake YAMATO
4323ae02089SMasatake YAMATO if (impl != IMPL_UNDEFINED)
4333ae02089SMasatake YAMATO e.extensionFields.implementation = implToString (impl);
4343ae02089SMasatake YAMATO if (vStringLength (inheritance) > 0)
4353ae02089SMasatake YAMATO e.extensionFields.inheritance = vStringValue (inheritance);
4363ae02089SMasatake YAMATO
4379014223fSMasatake YAMATO makePhpTagEntry (&e);
4383ae02089SMasatake YAMATO }
4393ae02089SMasatake YAMATO }
4403ae02089SMasatake YAMATO
makeFunctionTag(const tokenInfo * const token,const vString * const arglist,const vString * const rtype,const accessType access,const implType impl)4413ae02089SMasatake YAMATO static void makeFunctionTag (const tokenInfo *const token,
4423ae02089SMasatake YAMATO const vString *const arglist,
443c74b5ff0SMasatake YAMATO const vString *const rtype,
4443ae02089SMasatake YAMATO const accessType access, const implType impl)
4453ae02089SMasatake YAMATO {
4463ae02089SMasatake YAMATO if (PhpKinds[K_FUNCTION].enabled)
4473ae02089SMasatake YAMATO {
4483ae02089SMasatake YAMATO tagEntryInfo e;
4493ae02089SMasatake YAMATO
4503ae02089SMasatake YAMATO initPhpEntry (&e, token, K_FUNCTION, access);
4513ae02089SMasatake YAMATO
4523ae02089SMasatake YAMATO if (impl != IMPL_UNDEFINED)
4533ae02089SMasatake YAMATO e.extensionFields.implementation = implToString (impl);
4543ae02089SMasatake YAMATO if (arglist)
4553ae02089SMasatake YAMATO e.extensionFields.signature = vStringValue (arglist);
456c74b5ff0SMasatake YAMATO if (rtype)
4575ed230b0SMasatake YAMATO fillTypeRefField (&e, rtype, token);
4583ae02089SMasatake YAMATO
4599014223fSMasatake YAMATO makePhpTagEntry (&e);
4603ae02089SMasatake YAMATO }
4613ae02089SMasatake YAMATO }
4623ae02089SMasatake YAMATO
newPoolToken(void * createArg CTAGS_ATTR_UNUSED)463e013efc1SMasatake YAMATO static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
4643ae02089SMasatake YAMATO {
4650988269fSJiří Techet tokenInfo *token = xMalloc (1, tokenInfo);
4663ae02089SMasatake YAMATO
4673ae02089SMasatake YAMATO token->string = vStringNew ();
4683ae02089SMasatake YAMATO token->scope = vStringNew ();
4693ae02089SMasatake YAMATO return token;
4703ae02089SMasatake YAMATO }
4713ae02089SMasatake YAMATO
clearPoolToken(void * data)4720988269fSJiří Techet static void clearPoolToken (void *data)
4733ae02089SMasatake YAMATO {
4740988269fSJiří Techet tokenInfo *token = data;
4750988269fSJiří Techet
4760988269fSJiří Techet token->type = TOKEN_UNDEFINED;
4770988269fSJiří Techet token->keyword = KEYWORD_NONE;
4780988269fSJiří Techet token->lineNumber = getInputLineNumber ();
4790988269fSJiří Techet token->filePosition = getInputFilePosition ();
4800988269fSJiří Techet token->parentKind = -1;
4813165d268SMasatake YAMATO token->anonymous = false;
4820988269fSJiří Techet vStringClear (token->string);
4830988269fSJiří Techet vStringClear (token->scope);
4840988269fSJiří Techet }
4850988269fSJiří Techet
deletePoolToken(void * data)4860988269fSJiří Techet static void deletePoolToken (void *data)
4870988269fSJiří Techet {
4880988269fSJiří Techet tokenInfo *token = data;
4893ae02089SMasatake YAMATO vStringDelete (token->string);
4903ae02089SMasatake YAMATO vStringDelete (token->scope);
4913ae02089SMasatake YAMATO eFree (token);
4923ae02089SMasatake YAMATO }
4933ae02089SMasatake YAMATO
copyToken(tokenInfo * const dest,const tokenInfo * const src,bool scope)4943ae02089SMasatake YAMATO static void copyToken (tokenInfo *const dest, const tokenInfo *const src,
495ce990805SThomas Braun bool scope)
4963ae02089SMasatake YAMATO {
4973ae02089SMasatake YAMATO dest->lineNumber = src->lineNumber;
4983ae02089SMasatake YAMATO dest->filePosition = src->filePosition;
4993ae02089SMasatake YAMATO dest->type = src->type;
5003ae02089SMasatake YAMATO dest->keyword = src->keyword;
5013ae02089SMasatake YAMATO vStringCopy(dest->string, src->string);
5023ae02089SMasatake YAMATO dest->parentKind = src->parentKind;
5033ae02089SMasatake YAMATO if (scope)
5043ae02089SMasatake YAMATO vStringCopy(dest->scope, src->scope);
5053165d268SMasatake YAMATO dest->anonymous = src->anonymous;
5063ae02089SMasatake YAMATO }
5073ae02089SMasatake YAMATO
5083ae02089SMasatake YAMATO #if 0
5093ae02089SMasatake YAMATO #include <stdio.h>
5103ae02089SMasatake YAMATO
5113ae02089SMasatake YAMATO static const char *tokenTypeName (const tokenType type)
5123ae02089SMasatake YAMATO {
5133ae02089SMasatake YAMATO switch (type)
5143ae02089SMasatake YAMATO {
5153ae02089SMasatake YAMATO case TOKEN_UNDEFINED: return "undefined";
5163ae02089SMasatake YAMATO case TOKEN_EOF: return "EOF";
5173ae02089SMasatake YAMATO case TOKEN_CHARACTER: return "character";
5183ae02089SMasatake YAMATO case TOKEN_CLOSE_PAREN: return "')'";
5193ae02089SMasatake YAMATO case TOKEN_SEMICOLON: return "';'";
5203ae02089SMasatake YAMATO case TOKEN_COLON: return "':'";
5213ae02089SMasatake YAMATO case TOKEN_COMMA: return "','";
5223ae02089SMasatake YAMATO case TOKEN_OPEN_PAREN: return "'('";
5233ae02089SMasatake YAMATO case TOKEN_OPERATOR: return "operator";
5243ae02089SMasatake YAMATO case TOKEN_IDENTIFIER: return "identifier";
5253ae02089SMasatake YAMATO case TOKEN_KEYWORD: return "keyword";
5263ae02089SMasatake YAMATO case TOKEN_STRING: return "string";
5273ae02089SMasatake YAMATO case TOKEN_PERIOD: return "'.'";
5283ae02089SMasatake YAMATO case TOKEN_OPEN_CURLY: return "'{'";
5293ae02089SMasatake YAMATO case TOKEN_CLOSE_CURLY: return "'}'";
5303ae02089SMasatake YAMATO case TOKEN_EQUAL_SIGN: return "'='";
5313ae02089SMasatake YAMATO case TOKEN_OPEN_SQUARE: return "'['";
5323ae02089SMasatake YAMATO case TOKEN_CLOSE_SQUARE: return "']'";
5333ae02089SMasatake YAMATO case TOKEN_VARIABLE: return "variable";
5343ae02089SMasatake YAMATO }
5353ae02089SMasatake YAMATO return NULL;
5363ae02089SMasatake YAMATO }
5373ae02089SMasatake YAMATO
5383ae02089SMasatake YAMATO static void printToken (const tokenInfo *const token)
5393ae02089SMasatake YAMATO {
5403ae02089SMasatake YAMATO fprintf (stderr, "%p:\n\ttype:\t%s\n\tline:\t%lu\n\tscope:\t%s\n", (void *) token,
5413ae02089SMasatake YAMATO tokenTypeName (token->type),
5423ae02089SMasatake YAMATO token->lineNumber,
5433ae02089SMasatake YAMATO vStringValue (token->scope));
5443ae02089SMasatake YAMATO switch (token->type)
5453ae02089SMasatake YAMATO {
5463ae02089SMasatake YAMATO case TOKEN_IDENTIFIER:
5473ae02089SMasatake YAMATO case TOKEN_STRING:
5483ae02089SMasatake YAMATO case TOKEN_VARIABLE:
5493ae02089SMasatake YAMATO fprintf (stderr, "\tcontent:\t%s\n", vStringValue (token->string));
5503ae02089SMasatake YAMATO break;
5513ae02089SMasatake YAMATO
5523ae02089SMasatake YAMATO case TOKEN_KEYWORD:
5533ae02089SMasatake YAMATO {
554158a3387SMasatake YAMATO size_t n = ARRAY_SIZE (PhpKeywordTable);
5553ae02089SMasatake YAMATO size_t i;
5563ae02089SMasatake YAMATO
5573ae02089SMasatake YAMATO fprintf (stderr, "\tkeyword:\t");
5583ae02089SMasatake YAMATO for (i = 0; i < n; i++)
5593ae02089SMasatake YAMATO {
5603ae02089SMasatake YAMATO if (PhpKeywordTable[i].id == token->keyword)
5613ae02089SMasatake YAMATO {
5623ae02089SMasatake YAMATO fprintf (stderr, "%s\n", PhpKeywordTable[i].name);
5633ae02089SMasatake YAMATO break;
5643ae02089SMasatake YAMATO }
5653ae02089SMasatake YAMATO }
5663ae02089SMasatake YAMATO if (i >= n)
5673ae02089SMasatake YAMATO fprintf (stderr, "(unknown)\n");
5683ae02089SMasatake YAMATO }
5693ae02089SMasatake YAMATO
5703ae02089SMasatake YAMATO default: break;
5713ae02089SMasatake YAMATO }
5723ae02089SMasatake YAMATO }
5733ae02089SMasatake YAMATO #endif
5743ae02089SMasatake YAMATO
addToScope(tokenInfo * const token,const vString * const extra,int kindOfUpperScope)575a4af1067SMasatake YAMATO static void addToScope (tokenInfo *const token, const vString *const extra,
576a4af1067SMasatake YAMATO int kindOfUpperScope)
5773ae02089SMasatake YAMATO {
5783ae02089SMasatake YAMATO if (vStringLength (token->scope) > 0)
579a4af1067SMasatake YAMATO {
580a4af1067SMasatake YAMATO const char* sep;
581a4af1067SMasatake YAMATO
582a4af1067SMasatake YAMATO sep = phpScopeSeparatorFor(token->parentKind,
583a4af1067SMasatake YAMATO kindOfUpperScope);
584a4af1067SMasatake YAMATO vStringCatS (token->scope, sep);
585a4af1067SMasatake YAMATO }
586c11faac7SMasatake YAMATO vStringCat (token->scope, extra);
5873ae02089SMasatake YAMATO }
5883ae02089SMasatake YAMATO
skipToCharacter(const int c)5893ae02089SMasatake YAMATO static int skipToCharacter (const int c)
5903ae02089SMasatake YAMATO {
5913ae02089SMasatake YAMATO int d;
5923ae02089SMasatake YAMATO do
5933ae02089SMasatake YAMATO {
594018bce0bSMasatake YAMATO d = getcFromInputFile ();
5953ae02089SMasatake YAMATO } while (d != EOF && d != c);
5963ae02089SMasatake YAMATO return d;
5973ae02089SMasatake YAMATO }
5983ae02089SMasatake YAMATO
parseString(vString * const string,const int delimiter)5993ae02089SMasatake YAMATO static void parseString (vString *const string, const int delimiter)
6003ae02089SMasatake YAMATO {
601ce990805SThomas Braun while (true)
6023ae02089SMasatake YAMATO {
603018bce0bSMasatake YAMATO int c = getcFromInputFile ();
6043ae02089SMasatake YAMATO
605018bce0bSMasatake YAMATO if (c == '\\' && (c = getcFromInputFile ()) != EOF)
6063ae02089SMasatake YAMATO vStringPut (string, (char) c);
6073ae02089SMasatake YAMATO else if (c == EOF || c == delimiter)
6083ae02089SMasatake YAMATO break;
6093ae02089SMasatake YAMATO else
6103ae02089SMasatake YAMATO vStringPut (string, (char) c);
6113ae02089SMasatake YAMATO }
6123ae02089SMasatake YAMATO }
6133ae02089SMasatake YAMATO
6144c42296bSColomban Wendling /* Strips @indent_len characters from lines in @string to get the correct
6154c42296bSColomban Wendling * string value for an indented heredoc (PHP 7.3+).
6164c42296bSColomban Wendling * This doesn't handle invalid values specially and might yield surprising
6174c42296bSColomban Wendling * results with them, but it doesn't really matter as it's invalid anyway. */
stripHeredocIndent(vString * const string,size_t indent_len)6184c42296bSColomban Wendling static void stripHeredocIndent (vString *const string, size_t indent_len)
6194c42296bSColomban Wendling {
6204c42296bSColomban Wendling char *str = vStringValue (string);
6214c42296bSColomban Wendling size_t str_len = vStringLength (string);
6224c42296bSColomban Wendling char *p = str;
6234c42296bSColomban Wendling size_t new_len = str_len;
6244c42296bSColomban Wendling bool at_line_start = true;
6254c42296bSColomban Wendling
6264c42296bSColomban Wendling while (*p)
6274c42296bSColomban Wendling {
6284c42296bSColomban Wendling if (at_line_start)
6294c42296bSColomban Wendling {
6304c42296bSColomban Wendling size_t p_len;
6314c42296bSColomban Wendling size_t strip_len;
6324c42296bSColomban Wendling
6334c42296bSColomban Wendling p_len = str_len - (p - str);
6344c42296bSColomban Wendling strip_len = p_len < indent_len ? p_len : indent_len;
6354c42296bSColomban Wendling memmove (p, p + strip_len, p_len - strip_len);
6364c42296bSColomban Wendling p += strip_len;
6374c42296bSColomban Wendling new_len -= strip_len;
6384c42296bSColomban Wendling }
6394c42296bSColomban Wendling /* CRLF is already normalized as LF */
6404c42296bSColomban Wendling at_line_start = (*p == '\r' || *p == '\n');
6414c42296bSColomban Wendling p++;
6424c42296bSColomban Wendling }
6434c42296bSColomban Wendling vStringTruncate (string, new_len);
6444c42296bSColomban Wendling }
6454c42296bSColomban Wendling
64616798065SColomban Wendling /* reads a PHP >= 7.3 HereDoc or a NowDoc (the part after the <<<).
6473ae02089SMasatake YAMATO * <<<[ \t]*(ID|'ID'|"ID")
6483ae02089SMasatake YAMATO * ...
64916798065SColomban Wendling * [ \t]*ID[^:indent-char:];?
6503ae02089SMasatake YAMATO *
6513ae02089SMasatake YAMATO * note that:
6523ae02089SMasatake YAMATO * 1) starting ID must be immediately followed by a newline;
6533ae02089SMasatake YAMATO * 2) closing ID is the same as opening one;
65416798065SColomban Wendling * 3) closing ID must not be immediately followed by an identifier character;
65516798065SColomban Wendling * 4) optional indentation of the closing ID is stripped from body lines,
65616798065SColomban Wendling * which lines must have the exact same prefix indentation.
6573ae02089SMasatake YAMATO *
65816798065SColomban Wendling * This is slightly relaxed from PHP < 7.3, where the closing ID had to be the
65916798065SColomban Wendling * only thing on its line, with the only exception of a semicolon right after
66016798065SColomban Wendling * the ID.
66116798065SColomban Wendling *
66216798065SColomban Wendling * Example of a single valid heredoc:
6633ae02089SMasatake YAMATO * <<< FOO
6643ae02089SMasatake YAMATO * something
6653ae02089SMasatake YAMATO * something else
66616798065SColomban Wendling * FOO_this is not an end
6673ae02089SMasatake YAMATO * FOO;
6683ae02089SMasatake YAMATO * # previous line was the end, but the semicolon wasn't required
66916798065SColomban Wendling *
67016798065SColomban Wendling * Another example using indentation and more code after the heredoc:
67116798065SColomban Wendling * <<<FOO
67216798065SColomban Wendling * something
67316798065SColomban Wendling * something else
67416798065SColomban Wendling * FOO . 'hello';
67516798065SColomban Wendling * # the heredoc ends at FOO, and leading tabs are stripped from the body.
67616798065SColomban Wendling * # ". 'hello'" is a normal concatenation operator and the string "hello".
6773ae02089SMasatake YAMATO */
parseHeredoc(vString * const string)6783ae02089SMasatake YAMATO static void parseHeredoc (vString *const string)
6793ae02089SMasatake YAMATO {
6803ae02089SMasatake YAMATO int c;
6813ae02089SMasatake YAMATO unsigned int len;
6823ae02089SMasatake YAMATO char delimiter[64]; /* arbitrary limit, but more is crazy anyway */
6833ae02089SMasatake YAMATO int quote = 0;
6843ae02089SMasatake YAMATO
6853ae02089SMasatake YAMATO do
6863ae02089SMasatake YAMATO {
687018bce0bSMasatake YAMATO c = getcFromInputFile ();
6883ae02089SMasatake YAMATO }
6893ae02089SMasatake YAMATO while (c == ' ' || c == '\t');
6903ae02089SMasatake YAMATO
6913ae02089SMasatake YAMATO if (c == '\'' || c == '"')
6923ae02089SMasatake YAMATO {
6933ae02089SMasatake YAMATO quote = c;
694018bce0bSMasatake YAMATO c = getcFromInputFile ();
6953ae02089SMasatake YAMATO }
696158a3387SMasatake YAMATO for (len = 0; len < ARRAY_SIZE (delimiter) - 1; len++)
6973ae02089SMasatake YAMATO {
6983ae02089SMasatake YAMATO if (! isIdentChar (c))
6993ae02089SMasatake YAMATO break;
7003ae02089SMasatake YAMATO delimiter[len] = (char) c;
701018bce0bSMasatake YAMATO c = getcFromInputFile ();
7023ae02089SMasatake YAMATO }
7033ae02089SMasatake YAMATO delimiter[len] = 0;
7043ae02089SMasatake YAMATO
7053ae02089SMasatake YAMATO if (len == 0) /* no delimiter, give up */
7063ae02089SMasatake YAMATO goto error;
7073ae02089SMasatake YAMATO if (quote)
7083ae02089SMasatake YAMATO {
7093ae02089SMasatake YAMATO if (c != quote) /* no closing quote for quoted identifier, give up */
7103ae02089SMasatake YAMATO goto error;
711018bce0bSMasatake YAMATO c = getcFromInputFile ();
7123ae02089SMasatake YAMATO }
7133ae02089SMasatake YAMATO if (c != '\r' && c != '\n') /* missing newline, give up */
7143ae02089SMasatake YAMATO goto error;
7153ae02089SMasatake YAMATO
7163ae02089SMasatake YAMATO do
7173ae02089SMasatake YAMATO {
718018bce0bSMasatake YAMATO c = getcFromInputFile ();
7193ae02089SMasatake YAMATO
7203ae02089SMasatake YAMATO vStringPut (string, (char) c);
7214c42296bSColomban Wendling if (c == '\r' || c == '\n')
7223ae02089SMasatake YAMATO {
7234c42296bSColomban Wendling /* new line, check for a delimiter right after. No need to handle
7244c42296bSColomban Wendling * CRLF, getcFromInputFile() normalizes it to LF already. */
7254c42296bSColomban Wendling const size_t prev_string_len = vStringLength (string) - 1;
7264c42296bSColomban Wendling size_t indent_len = 0;
7273ae02089SMasatake YAMATO
728018bce0bSMasatake YAMATO c = getcFromInputFile ();
72916798065SColomban Wendling while (c == ' ' || c == '\t')
73016798065SColomban Wendling {
73116798065SColomban Wendling vStringPut (string, (char) c);
73216798065SColomban Wendling c = getcFromInputFile ();
7334c42296bSColomban Wendling indent_len++;
73416798065SColomban Wendling }
73516798065SColomban Wendling
7363ae02089SMasatake YAMATO for (len = 0; c != 0 && (c - delimiter[len]) == 0; len++)
737018bce0bSMasatake YAMATO c = getcFromInputFile ();
7383ae02089SMasatake YAMATO
7393ae02089SMasatake YAMATO if (delimiter[len] != 0)
74061f14fa5SMasatake YAMATO ungetcToInputFile (c);
74116798065SColomban Wendling else if (! isIdentChar (c))
7423ae02089SMasatake YAMATO {
74316798065SColomban Wendling /* line start matched the delimiter and has a separator, we're done */
74461f14fa5SMasatake YAMATO ungetcToInputFile (c);
7454c42296bSColomban Wendling
7464c42296bSColomban Wendling /* strip trailing newline and indent of the end delimiter */
7474c42296bSColomban Wendling vStringTruncate (string, prev_string_len);
7484c42296bSColomban Wendling
7494c42296bSColomban Wendling /* strip indent from the value if needed */
7504c42296bSColomban Wendling if (indent_len > 0)
7514c42296bSColomban Wendling stripHeredocIndent (string, indent_len);
7523ae02089SMasatake YAMATO break;
7533ae02089SMasatake YAMATO }
7543ae02089SMasatake YAMATO /* if we are here it wasn't a delimiter, so put everything in the
7553ae02089SMasatake YAMATO * string */
7563ae02089SMasatake YAMATO vStringNCatS (string, delimiter, len);
7573ae02089SMasatake YAMATO }
7583ae02089SMasatake YAMATO }
7593ae02089SMasatake YAMATO while (c != EOF);
7603ae02089SMasatake YAMATO
7613ae02089SMasatake YAMATO return;
7623ae02089SMasatake YAMATO
7633ae02089SMasatake YAMATO error:
76461f14fa5SMasatake YAMATO ungetcToInputFile (c);
7653ae02089SMasatake YAMATO }
7663ae02089SMasatake YAMATO
parseIdentifier(vString * const string,const int firstChar)7673ae02089SMasatake YAMATO static void parseIdentifier (vString *const string, const int firstChar)
7683ae02089SMasatake YAMATO {
7693ae02089SMasatake YAMATO int c = firstChar;
7703ae02089SMasatake YAMATO do
7713ae02089SMasatake YAMATO {
7723ae02089SMasatake YAMATO vStringPut (string, (char) c);
773018bce0bSMasatake YAMATO c = getcFromInputFile ();
7743ae02089SMasatake YAMATO } while (isIdentChar (c));
77561f14fa5SMasatake YAMATO ungetcToInputFile (c);
7763ae02089SMasatake YAMATO }
7773ae02089SMasatake YAMATO
isSpace(int c)778ce990805SThomas Braun static bool isSpace (int c)
7793ae02089SMasatake YAMATO {
7803ae02089SMasatake YAMATO return (c == '\t' || c == ' ' || c == '\v' ||
7813ae02089SMasatake YAMATO c == '\n' || c == '\r' || c == '\f');
7823ae02089SMasatake YAMATO }
7833ae02089SMasatake YAMATO
skipWhitespaces(int c)7843ae02089SMasatake YAMATO static int skipWhitespaces (int c)
7853ae02089SMasatake YAMATO {
7863ae02089SMasatake YAMATO while (isSpace (c))
787018bce0bSMasatake YAMATO c = getcFromInputFile ();
7883ae02089SMasatake YAMATO return c;
7893ae02089SMasatake YAMATO }
7903ae02089SMasatake YAMATO
7913ae02089SMasatake YAMATO /* <script[:white:]+language[:white:]*=[:white:]*(php|'php'|"php")[:white:]*>
7923ae02089SMasatake YAMATO *
7933ae02089SMasatake YAMATO * This is ugly, but the whole "<script language=php>" tag is and we can't
7943ae02089SMasatake YAMATO * really do better without adding a lot of code only for this */
isOpenScriptLanguagePhp(int c)795ce990805SThomas Braun static bool isOpenScriptLanguagePhp (int c)
7963ae02089SMasatake YAMATO {
7973ae02089SMasatake YAMATO int quote = 0;
7983ae02089SMasatake YAMATO
7993ae02089SMasatake YAMATO /* <script[:white:]+language[:white:]*= */
8003ae02089SMasatake YAMATO if (c != '<' ||
801018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 's' ||
802018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'c' ||
803018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'r' ||
804018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'i' ||
805018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'p' ||
806018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 't' ||
807018bce0bSMasatake YAMATO ! isSpace ((c = getcFromInputFile ())) ||
8083ae02089SMasatake YAMATO tolower ((c = skipWhitespaces (c))) != 'l' ||
809018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'a' ||
810018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'n' ||
811018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'g' ||
812018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'u' ||
813018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'a' ||
814018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'g' ||
815018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'e' ||
816018bce0bSMasatake YAMATO (c = skipWhitespaces (getcFromInputFile ())) != '=')
817ce990805SThomas Braun return false;
8183ae02089SMasatake YAMATO
8193ae02089SMasatake YAMATO /* (php|'php'|"php")> */
820018bce0bSMasatake YAMATO c = skipWhitespaces (getcFromInputFile ());
8213ae02089SMasatake YAMATO if (c == '"' || c == '\'')
8223ae02089SMasatake YAMATO {
8233ae02089SMasatake YAMATO quote = c;
824018bce0bSMasatake YAMATO c = getcFromInputFile ();
8253ae02089SMasatake YAMATO }
8263ae02089SMasatake YAMATO if (tolower (c) != 'p' ||
827018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'h' ||
828018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'p' ||
829018bce0bSMasatake YAMATO (quote != 0 && (c = getcFromInputFile ()) != quote) ||
830018bce0bSMasatake YAMATO (c = skipWhitespaces (getcFromInputFile ())) != '>')
831ce990805SThomas Braun return false;
8323ae02089SMasatake YAMATO
833ce990805SThomas Braun return true;
8343ae02089SMasatake YAMATO }
8353ae02089SMasatake YAMATO
findPhpStart(void)8363ae02089SMasatake YAMATO static int findPhpStart (void)
8373ae02089SMasatake YAMATO {
8383ae02089SMasatake YAMATO int c;
8393ae02089SMasatake YAMATO do
8403ae02089SMasatake YAMATO {
841018bce0bSMasatake YAMATO if ((c = getcFromInputFile ()) == '<')
8423ae02089SMasatake YAMATO {
843018bce0bSMasatake YAMATO c = getcFromInputFile ();
844a34c80d3SColomban Wendling /* <?, <?= and <?php, but not <?xml */
8453ae02089SMasatake YAMATO if (c == '?')
8463ae02089SMasatake YAMATO {
847a34c80d3SColomban Wendling c = getcFromInputFile ();
848a34c80d3SColomban Wendling /* echo tag */
849a34c80d3SColomban Wendling if (c == '=')
850a34c80d3SColomban Wendling c = getcFromInputFile ();
8513ae02089SMasatake YAMATO /* don't enter PHP mode on "<?xml", yet still support short open tags (<?) */
852a34c80d3SColomban Wendling else if (tolower (c) != 'x' ||
853018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'm' ||
854018bce0bSMasatake YAMATO tolower ((c = getcFromInputFile ())) != 'l')
8553ae02089SMasatake YAMATO {
8563ae02089SMasatake YAMATO break;
8573ae02089SMasatake YAMATO }
8583ae02089SMasatake YAMATO }
8593ae02089SMasatake YAMATO /* <script language="php"> */
8603ae02089SMasatake YAMATO else
8613ae02089SMasatake YAMATO {
86261f14fa5SMasatake YAMATO ungetcToInputFile (c);
8633ae02089SMasatake YAMATO if (isOpenScriptLanguagePhp ('<'))
8643ae02089SMasatake YAMATO break;
8653ae02089SMasatake YAMATO }
8663ae02089SMasatake YAMATO }
8673ae02089SMasatake YAMATO }
8683ae02089SMasatake YAMATO while (c != EOF);
8693ae02089SMasatake YAMATO
8703ae02089SMasatake YAMATO return c;
8713ae02089SMasatake YAMATO }
8723ae02089SMasatake YAMATO
skipSingleComment(void)8733ae02089SMasatake YAMATO static int skipSingleComment (void)
8743ae02089SMasatake YAMATO {
8753ae02089SMasatake YAMATO int c;
8763ae02089SMasatake YAMATO do
8773ae02089SMasatake YAMATO {
878018bce0bSMasatake YAMATO c = getcFromInputFile ();
8793ae02089SMasatake YAMATO /* ?> in single-line comments leaves PHP mode */
88005d5ad5fSColomban Wendling if (c == '?')
8813ae02089SMasatake YAMATO {
882018bce0bSMasatake YAMATO int next = getcFromInputFile ();
8833ae02089SMasatake YAMATO if (next == '>')
884ce990805SThomas Braun InPhp = false;
8853ae02089SMasatake YAMATO else
88661f14fa5SMasatake YAMATO ungetcToInputFile (next);
8873ae02089SMasatake YAMATO }
8883ae02089SMasatake YAMATO } while (InPhp && c != EOF && c != '\n' && c != '\r');
8893ae02089SMasatake YAMATO return c;
8903ae02089SMasatake YAMATO }
8913ae02089SMasatake YAMATO
readToken(tokenInfo * const token)8923ae02089SMasatake YAMATO static void readToken (tokenInfo *const token)
8933ae02089SMasatake YAMATO {
8943ae02089SMasatake YAMATO int c;
89575ba24d4SColomban Wendling bool nextMayBeKeyword = true;
8963ae02089SMasatake YAMATO
8973ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
8983ae02089SMasatake YAMATO token->keyword = KEYWORD_NONE;
8993ae02089SMasatake YAMATO vStringClear (token->string);
9003ae02089SMasatake YAMATO
9013ae02089SMasatake YAMATO getNextChar:
9023ae02089SMasatake YAMATO
9033ae02089SMasatake YAMATO if (! InPhp)
9043ae02089SMasatake YAMATO {
905*f476dfe1SMasatake YAMATO unsigned long startSourceLineNumber = getSourceLineNumber ();
906*f476dfe1SMasatake YAMATO unsigned long startLineNumber = startSourceLineNumber;
907*f476dfe1SMasatake YAMATO int startLineOffset = getInputLineOffset ();
908*f476dfe1SMasatake YAMATO
9093ae02089SMasatake YAMATO c = findPhpStart ();
9103ae02089SMasatake YAMATO if (c != EOF)
911ce990805SThomas Braun InPhp = true;
912*f476dfe1SMasatake YAMATO
913*f476dfe1SMasatake YAMATO unsigned long endLineNumber = getInputLineNumber ();
914*f476dfe1SMasatake YAMATO int endLineOffset = getInputLineOffset ();
915*f476dfe1SMasatake YAMATO
916*f476dfe1SMasatake YAMATO if ((startLineNumber != endLineNumber)
917*f476dfe1SMasatake YAMATO || (startLineOffset != endLineOffset))
918*f476dfe1SMasatake YAMATO makePromise ("HTML", startLineNumber, startLineOffset,
919*f476dfe1SMasatake YAMATO endLineNumber, endLineOffset, startSourceLineNumber);
9203ae02089SMasatake YAMATO }
9213ae02089SMasatake YAMATO else
922018bce0bSMasatake YAMATO c = getcFromInputFile ();
9233ae02089SMasatake YAMATO
9243ae02089SMasatake YAMATO c = skipWhitespaces (c);
9253ae02089SMasatake YAMATO
926a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
9273ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
9283ae02089SMasatake YAMATO
9293ae02089SMasatake YAMATO switch (c)
9303ae02089SMasatake YAMATO {
9313ae02089SMasatake YAMATO case EOF: token->type = TOKEN_EOF; break;
9323ae02089SMasatake YAMATO case '(': token->type = TOKEN_OPEN_PAREN; break;
9333ae02089SMasatake YAMATO case ')': token->type = TOKEN_CLOSE_PAREN; break;
9343ae02089SMasatake YAMATO case ';': token->type = TOKEN_SEMICOLON; break;
9353ae02089SMasatake YAMATO case ',': token->type = TOKEN_COMMA; break;
9363ae02089SMasatake YAMATO case '.': token->type = TOKEN_PERIOD; break;
9373ae02089SMasatake YAMATO case '{': token->type = TOKEN_OPEN_CURLY; break;
9383ae02089SMasatake YAMATO case '}': token->type = TOKEN_CLOSE_CURLY; break;
9393ae02089SMasatake YAMATO case '[': token->type = TOKEN_OPEN_SQUARE; break;
9403ae02089SMasatake YAMATO case ']': token->type = TOKEN_CLOSE_SQUARE; break;
9413ae02089SMasatake YAMATO case '&': token->type = TOKEN_AMPERSAND; break;
942acbcd162SColomban Wendling case '\\': token->type = TOKEN_BACKSLASH; break;
9433ae02089SMasatake YAMATO
94475ba24d4SColomban Wendling case ':':
94575ba24d4SColomban Wendling {
94675ba24d4SColomban Wendling int d = getcFromInputFile ();
94775ba24d4SColomban Wendling if (d == c) /* :: */
94875ba24d4SColomban Wendling {
94975ba24d4SColomban Wendling nextMayBeKeyword = false;
95075ba24d4SColomban Wendling token->type = TOKEN_OPERATOR;
95175ba24d4SColomban Wendling }
95275ba24d4SColomban Wendling else
95375ba24d4SColomban Wendling {
95475ba24d4SColomban Wendling ungetcToInputFile (d);
95575ba24d4SColomban Wendling token->type = TOKEN_COLON;
95675ba24d4SColomban Wendling }
95775ba24d4SColomban Wendling break;
95875ba24d4SColomban Wendling }
95975ba24d4SColomban Wendling
9603ae02089SMasatake YAMATO case '=':
9613ae02089SMasatake YAMATO {
962018bce0bSMasatake YAMATO int d = getcFromInputFile ();
9633ae02089SMasatake YAMATO if (d == '=' || d == '>')
9643ae02089SMasatake YAMATO token->type = TOKEN_OPERATOR;
9653ae02089SMasatake YAMATO else
9663ae02089SMasatake YAMATO {
96761f14fa5SMasatake YAMATO ungetcToInputFile (d);
9683ae02089SMasatake YAMATO token->type = TOKEN_EQUAL_SIGN;
9693ae02089SMasatake YAMATO }
9703ae02089SMasatake YAMATO break;
9713ae02089SMasatake YAMATO }
9723ae02089SMasatake YAMATO
9733ae02089SMasatake YAMATO case '\'':
9743ae02089SMasatake YAMATO case '"':
9753ae02089SMasatake YAMATO token->type = TOKEN_STRING;
9763ae02089SMasatake YAMATO parseString (token->string, c);
977a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
9783ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
9793ae02089SMasatake YAMATO break;
9803ae02089SMasatake YAMATO
9813ae02089SMasatake YAMATO case '<':
9823ae02089SMasatake YAMATO {
983018bce0bSMasatake YAMATO int d = getcFromInputFile ();
9843ae02089SMasatake YAMATO if (d == '/')
9853ae02089SMasatake YAMATO {
9863ae02089SMasatake YAMATO /* </script[:white:]*> */
987018bce0bSMasatake YAMATO if (tolower ((d = getcFromInputFile ())) == 's' &&
988018bce0bSMasatake YAMATO tolower ((d = getcFromInputFile ())) == 'c' &&
989018bce0bSMasatake YAMATO tolower ((d = getcFromInputFile ())) == 'r' &&
990018bce0bSMasatake YAMATO tolower ((d = getcFromInputFile ())) == 'i' &&
991018bce0bSMasatake YAMATO tolower ((d = getcFromInputFile ())) == 'p' &&
992018bce0bSMasatake YAMATO tolower ((d = getcFromInputFile ())) == 't' &&
993018bce0bSMasatake YAMATO (d = skipWhitespaces (getcFromInputFile ())) == '>')
9943ae02089SMasatake YAMATO {
995ce990805SThomas Braun InPhp = false;
9963ae02089SMasatake YAMATO goto getNextChar;
9973ae02089SMasatake YAMATO }
9983ae02089SMasatake YAMATO else
9993ae02089SMasatake YAMATO {
100061f14fa5SMasatake YAMATO ungetcToInputFile (d);
10013ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
10023ae02089SMasatake YAMATO }
10033ae02089SMasatake YAMATO }
1004018bce0bSMasatake YAMATO else if (d == '<' && (d = getcFromInputFile ()) == '<')
10053ae02089SMasatake YAMATO {
10063ae02089SMasatake YAMATO token->type = TOKEN_STRING;
10073ae02089SMasatake YAMATO parseHeredoc (token->string);
10083ae02089SMasatake YAMATO }
10093ae02089SMasatake YAMATO else
10103ae02089SMasatake YAMATO {
101161f14fa5SMasatake YAMATO ungetcToInputFile (d);
10123ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
10133ae02089SMasatake YAMATO }
10143ae02089SMasatake YAMATO break;
10153ae02089SMasatake YAMATO }
10163ae02089SMasatake YAMATO
10173ae02089SMasatake YAMATO case '#': /* comment */
10183ae02089SMasatake YAMATO skipSingleComment ();
10193ae02089SMasatake YAMATO goto getNextChar;
10203ae02089SMasatake YAMATO break;
10213ae02089SMasatake YAMATO
10223ae02089SMasatake YAMATO case '+':
10233ae02089SMasatake YAMATO case '-':
10243ae02089SMasatake YAMATO case '*':
10253ae02089SMasatake YAMATO case '%':
10263ae02089SMasatake YAMATO {
1027018bce0bSMasatake YAMATO int d = getcFromInputFile ();
102875ba24d4SColomban Wendling if (c == '-' && d == '>')
102975ba24d4SColomban Wendling nextMayBeKeyword = false;
103075ba24d4SColomban Wendling else if (d != '=')
103161f14fa5SMasatake YAMATO ungetcToInputFile (d);
10323ae02089SMasatake YAMATO token->type = TOKEN_OPERATOR;
10333ae02089SMasatake YAMATO break;
10343ae02089SMasatake YAMATO }
10353ae02089SMasatake YAMATO
10363ae02089SMasatake YAMATO case '/': /* division or comment start */
10373ae02089SMasatake YAMATO {
1038018bce0bSMasatake YAMATO int d = getcFromInputFile ();
10393ae02089SMasatake YAMATO if (d == '/') /* single-line comment */
10403ae02089SMasatake YAMATO {
10413ae02089SMasatake YAMATO skipSingleComment ();
10423ae02089SMasatake YAMATO goto getNextChar;
10433ae02089SMasatake YAMATO }
10443ae02089SMasatake YAMATO else if (d == '*')
10453ae02089SMasatake YAMATO {
10463ae02089SMasatake YAMATO do
10473ae02089SMasatake YAMATO {
10483ae02089SMasatake YAMATO c = skipToCharacter ('*');
10493ae02089SMasatake YAMATO if (c != EOF)
10503ae02089SMasatake YAMATO {
1051018bce0bSMasatake YAMATO c = getcFromInputFile ();
10523ae02089SMasatake YAMATO if (c == '/')
10533ae02089SMasatake YAMATO break;
10543ae02089SMasatake YAMATO else
105561f14fa5SMasatake YAMATO ungetcToInputFile (c);
10563ae02089SMasatake YAMATO }
10573ae02089SMasatake YAMATO } while (c != EOF && c != '\0');
10583ae02089SMasatake YAMATO goto getNextChar;
10593ae02089SMasatake YAMATO }
10603ae02089SMasatake YAMATO else
10613ae02089SMasatake YAMATO {
10623ae02089SMasatake YAMATO if (d != '=')
106361f14fa5SMasatake YAMATO ungetcToInputFile (d);
10643ae02089SMasatake YAMATO token->type = TOKEN_OPERATOR;
10653ae02089SMasatake YAMATO }
10663ae02089SMasatake YAMATO break;
10673ae02089SMasatake YAMATO }
10683ae02089SMasatake YAMATO
10693ae02089SMasatake YAMATO case '$': /* variable start */
10703ae02089SMasatake YAMATO {
1071018bce0bSMasatake YAMATO int d = getcFromInputFile ();
10723ae02089SMasatake YAMATO if (! isIdentChar (d))
10733ae02089SMasatake YAMATO {
107461f14fa5SMasatake YAMATO ungetcToInputFile (d);
10753ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
10763ae02089SMasatake YAMATO }
10773ae02089SMasatake YAMATO else
10783ae02089SMasatake YAMATO {
10793ae02089SMasatake YAMATO parseIdentifier (token->string, d);
10803ae02089SMasatake YAMATO token->type = TOKEN_VARIABLE;
10813ae02089SMasatake YAMATO }
10823ae02089SMasatake YAMATO break;
10833ae02089SMasatake YAMATO }
10843ae02089SMasatake YAMATO
10853ae02089SMasatake YAMATO case '?': /* maybe the end of the PHP chunk */
10863ae02089SMasatake YAMATO {
1087018bce0bSMasatake YAMATO int d = getcFromInputFile ();
10883ae02089SMasatake YAMATO if (d == '>')
10893ae02089SMasatake YAMATO {
1090ce990805SThomas Braun InPhp = false;
10913ae02089SMasatake YAMATO goto getNextChar;
10923ae02089SMasatake YAMATO }
10933ae02089SMasatake YAMATO else
10943ae02089SMasatake YAMATO {
109561f14fa5SMasatake YAMATO ungetcToInputFile (d);
109651f37d45SMasatake YAMATO token->type = TOKEN_QMARK;
10973ae02089SMasatake YAMATO }
10983ae02089SMasatake YAMATO break;
10993ae02089SMasatake YAMATO }
11003ae02089SMasatake YAMATO
11013ae02089SMasatake YAMATO default:
11023ae02089SMasatake YAMATO if (! isIdentChar (c))
11033ae02089SMasatake YAMATO token->type = TOKEN_UNDEFINED;
11043ae02089SMasatake YAMATO else
11053ae02089SMasatake YAMATO {
11063ae02089SMasatake YAMATO parseIdentifier (token->string, c);
110775ba24d4SColomban Wendling if (MayBeKeyword)
110831a85388SJiří Techet token->keyword = lookupCaseKeyword (vStringValue (token->string), getInputLanguage ());
110975ba24d4SColomban Wendling else
111075ba24d4SColomban Wendling token->keyword = KEYWORD_NONE;
111175ba24d4SColomban Wendling
11123ae02089SMasatake YAMATO if (token->keyword == KEYWORD_NONE)
11133ae02089SMasatake YAMATO token->type = TOKEN_IDENTIFIER;
11143ae02089SMasatake YAMATO else
11153ae02089SMasatake YAMATO token->type = TOKEN_KEYWORD;
11163ae02089SMasatake YAMATO }
11173ae02089SMasatake YAMATO break;
11183ae02089SMasatake YAMATO }
11193ae02089SMasatake YAMATO
11203ae02089SMasatake YAMATO if (token->type == TOKEN_SEMICOLON ||
11213ae02089SMasatake YAMATO token->type == TOKEN_OPEN_CURLY ||
11223ae02089SMasatake YAMATO token->type == TOKEN_CLOSE_CURLY)
11233ae02089SMasatake YAMATO {
11243ae02089SMasatake YAMATO /* reset current statement details on statement end, and when entering
11253ae02089SMasatake YAMATO * a deeper scope.
11263ae02089SMasatake YAMATO * it is a bit ugly to do this in readToken(), but it makes everything
11273ae02089SMasatake YAMATO * a lot simpler. */
11283ae02089SMasatake YAMATO CurrentStatement.access = ACCESS_UNDEFINED;
11293ae02089SMasatake YAMATO CurrentStatement.impl = IMPL_UNDEFINED;
11303ae02089SMasatake YAMATO }
113175ba24d4SColomban Wendling
113275ba24d4SColomban Wendling MayBeKeyword = nextMayBeKeyword;
11333ae02089SMasatake YAMATO }
11343ae02089SMasatake YAMATO
readQualifiedName(tokenInfo * const token,vString * name,tokenInfo * const lastToken)1135c74b5ff0SMasatake YAMATO static void readQualifiedName (tokenInfo *const token, vString *name,
1136c74b5ff0SMasatake YAMATO tokenInfo *const lastToken)
1137c74b5ff0SMasatake YAMATO {
1138c74b5ff0SMasatake YAMATO while (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_BACKSLASH)
1139c74b5ff0SMasatake YAMATO {
1140c74b5ff0SMasatake YAMATO if (name)
1141c74b5ff0SMasatake YAMATO {
1142c74b5ff0SMasatake YAMATO if (token->type == TOKEN_BACKSLASH)
1143c74b5ff0SMasatake YAMATO vStringPut (name, '\\');
1144c74b5ff0SMasatake YAMATO else
1145c74b5ff0SMasatake YAMATO vStringCat (name, token->string);
1146c74b5ff0SMasatake YAMATO }
1147c74b5ff0SMasatake YAMATO if (lastToken)
1148c74b5ff0SMasatake YAMATO copyToken (lastToken, token, true);
1149c74b5ff0SMasatake YAMATO readToken (token);
1150c74b5ff0SMasatake YAMATO }
1151c74b5ff0SMasatake YAMATO }
1152c74b5ff0SMasatake YAMATO
11533ae02089SMasatake YAMATO static void enterScope (tokenInfo *const parentToken,
11543ae02089SMasatake YAMATO const vString *const extraScope,
11553ae02089SMasatake YAMATO const int parentKind);
11563ae02089SMasatake YAMATO
skipOverParens(tokenInfo * token)1157d0d29d63SColomban Wendling static void skipOverParens (tokenInfo *token)
1158d0d29d63SColomban Wendling {
1159d0d29d63SColomban Wendling if (token->type == TOKEN_OPEN_PAREN)
1160d0d29d63SColomban Wendling {
1161d0d29d63SColomban Wendling int depth = 1;
1162d0d29d63SColomban Wendling
1163d0d29d63SColomban Wendling do
1164d0d29d63SColomban Wendling {
1165d0d29d63SColomban Wendling readToken (token);
1166d0d29d63SColomban Wendling switch (token->type)
1167d0d29d63SColomban Wendling {
1168d0d29d63SColomban Wendling case TOKEN_OPEN_PAREN: depth++; break;
1169d0d29d63SColomban Wendling case TOKEN_CLOSE_PAREN: depth--; break;
1170d0d29d63SColomban Wendling default: break;
1171d0d29d63SColomban Wendling }
1172d0d29d63SColomban Wendling }
1173d0d29d63SColomban Wendling while (token->type != TOKEN_EOF && depth > 0);
1174d0d29d63SColomban Wendling
1175d0d29d63SColomban Wendling readToken (token);
1176d0d29d63SColomban Wendling }
1177d0d29d63SColomban Wendling }
1178d0d29d63SColomban Wendling
11793ae02089SMasatake YAMATO /* parses a class or an interface:
11803ae02089SMasatake YAMATO * class Foo {}
11813ae02089SMasatake YAMATO * class Foo extends Bar {}
11823ae02089SMasatake YAMATO * class Foo extends Bar implements iFoo, iBar {}
11833ae02089SMasatake YAMATO * interface iFoo {}
1184d0d29d63SColomban Wendling * interface iBar extends iFoo {}
1185d0d29d63SColomban Wendling *
1186d0d29d63SColomban Wendling * if @name is not NULL, parses an anonymous class with name @name
1187d0d29d63SColomban Wendling * new class {}
1188d0d29d63SColomban Wendling * new class(1, 2) {}
1189d0d29d63SColomban Wendling * new class(1, 2) extends Foo implements iFoo, iBar {} */
parseClassOrIface(tokenInfo * const token,const phpKind kind,const tokenInfo * name)1190ce990805SThomas Braun static bool parseClassOrIface (tokenInfo *const token, const phpKind kind,
1191d0d29d63SColomban Wendling const tokenInfo *name)
11923ae02089SMasatake YAMATO {
1193ce990805SThomas Braun bool readNext = true;
11943ae02089SMasatake YAMATO implType impl = CurrentStatement.impl;
1195d0d29d63SColomban Wendling tokenInfo *nameFree = NULL;
11963ae02089SMasatake YAMATO vString *inheritance = NULL;
1197f176923cSMasatake YAMATO vString *parent = NULL;
11983ae02089SMasatake YAMATO
11993ae02089SMasatake YAMATO readToken (token);
1200d0d29d63SColomban Wendling if (name) /* anonymous class */
1201d0d29d63SColomban Wendling {
1202d0d29d63SColomban Wendling /* skip possible construction arguments */
1203d0d29d63SColomban Wendling skipOverParens (token);
1204d0d29d63SColomban Wendling }
1205d0d29d63SColomban Wendling else /* normal, named class */
1206d0d29d63SColomban Wendling {
12073ae02089SMasatake YAMATO if (token->type != TOKEN_IDENTIFIER)
1208ce990805SThomas Braun return false;
12093ae02089SMasatake YAMATO
1210d0d29d63SColomban Wendling name = nameFree = newToken ();
1211ce990805SThomas Braun copyToken (nameFree, token, true);
1212d0d29d63SColomban Wendling
1213d0d29d63SColomban Wendling readToken (token);
1214d0d29d63SColomban Wendling }
12153ae02089SMasatake YAMATO
12163ae02089SMasatake YAMATO inheritance = vStringNew ();
121759282227SMasatake YAMATO /* read every identifiers, keywords and commas, and assume each
121859282227SMasatake YAMATO * identifier (not keyword) is an inheritance
121959282227SMasatake YAMATO * (like in "class Foo extends Bar implements iA, iB") */
1220f176923cSMasatake YAMATO enum { inheritance_initial,
1221f176923cSMasatake YAMATO inheritance_extends,
1222f176923cSMasatake YAMATO inheritance_implements
1223f176923cSMasatake YAMATO } istat = inheritance_initial;
12242c4744daSColomban Wendling while (token->type == TOKEN_IDENTIFIER ||
1225810c6fdfSColomban Wendling token->type == TOKEN_BACKSLASH ||
12262c4744daSColomban Wendling token->type == TOKEN_KEYWORD ||
12272c4744daSColomban Wendling token->type == TOKEN_COMMA)
12283ae02089SMasatake YAMATO {
1229810c6fdfSColomban Wendling if (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_BACKSLASH)
12303ae02089SMasatake YAMATO {
1231810c6fdfSColomban Wendling vString *qualifiedName = vStringNew ();
1232810c6fdfSColomban Wendling
1233810c6fdfSColomban Wendling readQualifiedName (token, qualifiedName, NULL);
12343ae02089SMasatake YAMATO if (vStringLength (inheritance) > 0)
12353ae02089SMasatake YAMATO vStringPut (inheritance, ',');
1236810c6fdfSColomban Wendling vStringCat (inheritance, qualifiedName);
1237810c6fdfSColomban Wendling if (istat == inheritance_extends && !parent)
1238810c6fdfSColomban Wendling parent = qualifiedName;
1239810c6fdfSColomban Wendling else
1240810c6fdfSColomban Wendling vStringDelete (qualifiedName);
1241f176923cSMasatake YAMATO }
1242810c6fdfSColomban Wendling else
1243810c6fdfSColomban Wendling {
1244810c6fdfSColomban Wendling if (token->type == TOKEN_KEYWORD)
1245f176923cSMasatake YAMATO {
1246f176923cSMasatake YAMATO if (token->keyword == KEYWORD_extends)
1247f176923cSMasatake YAMATO istat = inheritance_extends;
1248f176923cSMasatake YAMATO else if (token->keyword == KEYWORD_implements)
1249f176923cSMasatake YAMATO istat = inheritance_implements;
12503ae02089SMasatake YAMATO }
1251d0d29d63SColomban Wendling readToken (token);
12523ae02089SMasatake YAMATO }
1253810c6fdfSColomban Wendling }
12543ae02089SMasatake YAMATO
12553ae02089SMasatake YAMATO makeClassOrIfaceTag (kind, name, inheritance, impl);
12563ae02089SMasatake YAMATO
12573ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
1258f176923cSMasatake YAMATO {
1259f176923cSMasatake YAMATO vString *backup = ParentClass;
1260f176923cSMasatake YAMATO ParentClass = parent;
1261bc9f0d91SColomban Wendling enterScope (token, name->string, kind);
1262f176923cSMasatake YAMATO ParentClass = backup;
1263f176923cSMasatake YAMATO }
12643ae02089SMasatake YAMATO else
1265ce990805SThomas Braun readNext = false;
12663ae02089SMasatake YAMATO
1267d0d29d63SColomban Wendling if (nameFree)
1268d0d29d63SColomban Wendling deleteToken (nameFree);
1269f176923cSMasatake YAMATO vStringDelete (parent);
12703ae02089SMasatake YAMATO vStringDelete (inheritance);
12713ae02089SMasatake YAMATO
12723ae02089SMasatake YAMATO return readNext;
12733ae02089SMasatake YAMATO }
12743ae02089SMasatake YAMATO
12753ae02089SMasatake YAMATO /* parses a trait:
12763ae02089SMasatake YAMATO * trait Foo {} */
parseTrait(tokenInfo * const token)1277ce990805SThomas Braun static bool parseTrait (tokenInfo *const token)
12783ae02089SMasatake YAMATO {
1279ce990805SThomas Braun bool readNext = true;
12803ae02089SMasatake YAMATO tokenInfo *name;
12813ae02089SMasatake YAMATO
12823ae02089SMasatake YAMATO readToken (token);
12833ae02089SMasatake YAMATO if (token->type != TOKEN_IDENTIFIER)
1284ce990805SThomas Braun return false;
12853ae02089SMasatake YAMATO
12863ae02089SMasatake YAMATO name = newToken ();
1287ce990805SThomas Braun copyToken (name, token, true);
12883ae02089SMasatake YAMATO
12893ae02089SMasatake YAMATO makeSimplePhpTag (name, K_TRAIT, ACCESS_UNDEFINED);
12903ae02089SMasatake YAMATO
12913ae02089SMasatake YAMATO readToken (token);
12923ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
12933ae02089SMasatake YAMATO enterScope (token, name->string, K_TRAIT);
12943ae02089SMasatake YAMATO else
1295ce990805SThomas Braun readNext = false;
12963ae02089SMasatake YAMATO
12973ae02089SMasatake YAMATO deleteToken (name);
12983ae02089SMasatake YAMATO
12993ae02089SMasatake YAMATO return readNext;
13003ae02089SMasatake YAMATO }
13013ae02089SMasatake YAMATO
13023ae02089SMasatake YAMATO /* parse a function
13033ae02089SMasatake YAMATO *
13043ae02089SMasatake YAMATO * if @name is NULL, parses a normal function
13053ae02089SMasatake YAMATO * function myfunc($foo, $bar) {}
13063ae02089SMasatake YAMATO * function &myfunc($foo, $bar) {}
1307bf43dadcSColomban Wendling * function myfunc($foo, $bar) : type {}
130884dbaf52SMasatake YAMATO * function myfunc($foo, $bar) : ?type {}
13093ae02089SMasatake YAMATO *
13103ae02089SMasatake YAMATO * if @name is not NULL, parses an anonymous function with name @name
13113ae02089SMasatake YAMATO * $foo = function($foo, $bar) {}
13123ae02089SMasatake YAMATO * $foo = function&($foo, $bar) {}
1313bf43dadcSColomban Wendling * $foo = function($foo, $bar) use ($x, &$y) {}
131484dbaf52SMasatake YAMATO * $foo = function($foo, $bar) use ($x, &$y) : type {}
131584dbaf52SMasatake YAMATO * $foo = function($foo, $bar) use ($x, &$y) : ?type {} */
parseFunction(tokenInfo * const token,const tokenInfo * name)1316ce990805SThomas Braun static bool parseFunction (tokenInfo *const token, const tokenInfo *name)
13173ae02089SMasatake YAMATO {
1318ce990805SThomas Braun bool readNext = true;
13193ae02089SMasatake YAMATO accessType access = CurrentStatement.access;
13203ae02089SMasatake YAMATO implType impl = CurrentStatement.impl;
13213ae02089SMasatake YAMATO tokenInfo *nameFree = NULL;
1322c74b5ff0SMasatake YAMATO vString *rtype = NULL;
1323c74b5ff0SMasatake YAMATO vString *arglist = NULL;
13243ae02089SMasatake YAMATO
13253ae02089SMasatake YAMATO readToken (token);
13263ae02089SMasatake YAMATO /* skip a possible leading ampersand (return by reference) */
13273ae02089SMasatake YAMATO if (token->type == TOKEN_AMPERSAND)
13283ae02089SMasatake YAMATO readToken (token);
13293ae02089SMasatake YAMATO
13303ae02089SMasatake YAMATO if (! name)
13313ae02089SMasatake YAMATO {
1332a1f68541SColomban Wendling if (token->type != TOKEN_IDENTIFIER && token->type != TOKEN_KEYWORD)
1333ce990805SThomas Braun return false;
13343ae02089SMasatake YAMATO
13353ae02089SMasatake YAMATO name = nameFree = newToken ();
1336ce990805SThomas Braun copyToken (nameFree, token, true);
13373ae02089SMasatake YAMATO readToken (token);
13383ae02089SMasatake YAMATO }
13393ae02089SMasatake YAMATO
13403ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_PAREN)
13413ae02089SMasatake YAMATO {
13423ae02089SMasatake YAMATO int depth = 1;
13433ae02089SMasatake YAMATO
1344c74b5ff0SMasatake YAMATO arglist = vStringNew ();
13453ae02089SMasatake YAMATO vStringPut (arglist, '(');
13463ae02089SMasatake YAMATO do
13473ae02089SMasatake YAMATO {
13483ae02089SMasatake YAMATO readToken (token);
13493ae02089SMasatake YAMATO
13503ae02089SMasatake YAMATO switch (token->type)
13513ae02089SMasatake YAMATO {
13523ae02089SMasatake YAMATO case TOKEN_OPEN_PAREN: depth++; break;
13533ae02089SMasatake YAMATO case TOKEN_CLOSE_PAREN: depth--; break;
13543ae02089SMasatake YAMATO default: break;
13553ae02089SMasatake YAMATO }
13563ae02089SMasatake YAMATO /* display part */
13573ae02089SMasatake YAMATO switch (token->type)
13583ae02089SMasatake YAMATO {
13593ae02089SMasatake YAMATO case TOKEN_AMPERSAND: vStringPut (arglist, '&'); break;
13603ae02089SMasatake YAMATO case TOKEN_CLOSE_CURLY: vStringPut (arglist, '}'); break;
13613ae02089SMasatake YAMATO case TOKEN_CLOSE_PAREN: vStringPut (arglist, ')'); break;
13623ae02089SMasatake YAMATO case TOKEN_CLOSE_SQUARE: vStringPut (arglist, ']'); break;
13633ae02089SMasatake YAMATO case TOKEN_COLON: vStringPut (arglist, ':'); break;
13643ae02089SMasatake YAMATO case TOKEN_COMMA: vStringCatS (arglist, ", "); break;
13653ae02089SMasatake YAMATO case TOKEN_EQUAL_SIGN: vStringCatS (arglist, " = "); break;
13663ae02089SMasatake YAMATO case TOKEN_OPEN_CURLY: vStringPut (arglist, '{'); break;
13673ae02089SMasatake YAMATO case TOKEN_OPEN_PAREN: vStringPut (arglist, '('); break;
13683ae02089SMasatake YAMATO case TOKEN_OPEN_SQUARE: vStringPut (arglist, '['); break;
13693ae02089SMasatake YAMATO case TOKEN_PERIOD: vStringPut (arglist, '.'); break;
13703ae02089SMasatake YAMATO case TOKEN_SEMICOLON: vStringPut (arglist, ';'); break;
1371acbcd162SColomban Wendling case TOKEN_BACKSLASH: vStringPut (arglist, '\\'); break;
13723ae02089SMasatake YAMATO case TOKEN_STRING:
13733ae02089SMasatake YAMATO {
13741da6e7e4SMasatake YAMATO vStringPut (arglist, '\'');
13753ae02089SMasatake YAMATO vStringCat (arglist, token->string);
13761da6e7e4SMasatake YAMATO vStringPut (arglist, '\'');
13773ae02089SMasatake YAMATO break;
13783ae02089SMasatake YAMATO }
13793ae02089SMasatake YAMATO
13803ae02089SMasatake YAMATO case TOKEN_IDENTIFIER:
13813ae02089SMasatake YAMATO case TOKEN_KEYWORD:
13823ae02089SMasatake YAMATO case TOKEN_VARIABLE:
13833ae02089SMasatake YAMATO {
13843ae02089SMasatake YAMATO switch (vStringLast (arglist))
13853ae02089SMasatake YAMATO {
13863ae02089SMasatake YAMATO case 0:
13873ae02089SMasatake YAMATO case ' ':
13883ae02089SMasatake YAMATO case '{':
13893ae02089SMasatake YAMATO case '(':
13903ae02089SMasatake YAMATO case '[':
13913ae02089SMasatake YAMATO case '.':
1392acbcd162SColomban Wendling case '\\':
13933ae02089SMasatake YAMATO /* no need for a space between those and the identifier */
13943ae02089SMasatake YAMATO break;
13953ae02089SMasatake YAMATO
13963ae02089SMasatake YAMATO default:
13973ae02089SMasatake YAMATO vStringPut (arglist, ' ');
13983ae02089SMasatake YAMATO break;
13993ae02089SMasatake YAMATO }
14003ae02089SMasatake YAMATO if (token->type == TOKEN_VARIABLE)
14013ae02089SMasatake YAMATO vStringPut (arglist, '$');
14023ae02089SMasatake YAMATO vStringCat (arglist, token->string);
14033ae02089SMasatake YAMATO break;
14043ae02089SMasatake YAMATO }
14053ae02089SMasatake YAMATO
14063ae02089SMasatake YAMATO default: break;
14073ae02089SMasatake YAMATO }
14083ae02089SMasatake YAMATO }
14093ae02089SMasatake YAMATO while (token->type != TOKEN_EOF && depth > 0);
14103ae02089SMasatake YAMATO
14113ae02089SMasatake YAMATO readToken (token); /* normally it's an open brace or "use" keyword */
14123ae02089SMasatake YAMATO }
14133ae02089SMasatake YAMATO
14143ae02089SMasatake YAMATO /* skip use(...) */
14153ae02089SMasatake YAMATO if (token->type == TOKEN_KEYWORD && token->keyword == KEYWORD_use)
14163ae02089SMasatake YAMATO {
14173ae02089SMasatake YAMATO readToken (token);
1418d0d29d63SColomban Wendling skipOverParens (token);
14193ae02089SMasatake YAMATO }
14203ae02089SMasatake YAMATO
1421c74b5ff0SMasatake YAMATO /* PHP7 return type declaration or if parsing Zephir, gather function return
1422c74b5ff0SMasatake YAMATO * type hint to fill typeRef. */
1423bf43dadcSColomban Wendling if ((getInputLanguage () == Lang_php && token->type == TOKEN_COLON) ||
1424bf43dadcSColomban Wendling (getInputLanguage () == Lang_zephir && token->type == TOKEN_OPERATOR))
1425bf43dadcSColomban Wendling {
1426c74b5ff0SMasatake YAMATO if (arglist)
1427c74b5ff0SMasatake YAMATO rtype = vStringNew ();
1428c74b5ff0SMasatake YAMATO
1429bf43dadcSColomban Wendling readToken (token);
143051f37d45SMasatake YAMATO if (token->type == TOKEN_QMARK)
143151f37d45SMasatake YAMATO {
143251f37d45SMasatake YAMATO if (rtype)
143351f37d45SMasatake YAMATO vStringPut (rtype, '?');
143451f37d45SMasatake YAMATO readToken (token);
143551f37d45SMasatake YAMATO }
1436c74b5ff0SMasatake YAMATO readQualifiedName (token, rtype, NULL);
1437c74b5ff0SMasatake YAMATO
1438c74b5ff0SMasatake YAMATO if (rtype && vStringIsEmpty (rtype))
1439c74b5ff0SMasatake YAMATO {
1440c74b5ff0SMasatake YAMATO vStringDelete (rtype);
1441c74b5ff0SMasatake YAMATO rtype = NULL;
1442bf43dadcSColomban Wendling }
1443c74b5ff0SMasatake YAMATO }
1444c74b5ff0SMasatake YAMATO
1445c74b5ff0SMasatake YAMATO if (arglist)
1446c74b5ff0SMasatake YAMATO makeFunctionTag (name, arglist, rtype, access, impl);
1447bf43dadcSColomban Wendling
14483ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
14493ae02089SMasatake YAMATO enterScope (token, name->string, K_FUNCTION);
14503ae02089SMasatake YAMATO else
1451ce990805SThomas Braun readNext = false;
14523ae02089SMasatake YAMATO
1453c74b5ff0SMasatake YAMATO vStringDelete (rtype);
1454c74b5ff0SMasatake YAMATO vStringDelete (arglist);
14553ae02089SMasatake YAMATO if (nameFree)
14563ae02089SMasatake YAMATO deleteToken (nameFree);
14573ae02089SMasatake YAMATO
14583ae02089SMasatake YAMATO return readNext;
14593ae02089SMasatake YAMATO }
14603ae02089SMasatake YAMATO
14613ae02089SMasatake YAMATO /* parses declarations of the form
14623ae02089SMasatake YAMATO * const NAME = VALUE */
parseConstant(tokenInfo * const token)1463ce990805SThomas Braun static bool parseConstant (tokenInfo *const token)
14643ae02089SMasatake YAMATO {
14653ae02089SMasatake YAMATO tokenInfo *name;
14663ae02089SMasatake YAMATO
14673ae02089SMasatake YAMATO readToken (token); /* skip const keyword */
1468a1f68541SColomban Wendling if (token->type != TOKEN_IDENTIFIER && token->type != TOKEN_KEYWORD)
1469ce990805SThomas Braun return false;
14703ae02089SMasatake YAMATO
14713ae02089SMasatake YAMATO name = newToken ();
1472ce990805SThomas Braun copyToken (name, token, true);
14733ae02089SMasatake YAMATO
14743ae02089SMasatake YAMATO readToken (token);
14753ae02089SMasatake YAMATO if (token->type == TOKEN_EQUAL_SIGN)
14763ae02089SMasatake YAMATO makeSimplePhpTag (name, K_DEFINE, ACCESS_UNDEFINED);
14773ae02089SMasatake YAMATO
14783ae02089SMasatake YAMATO deleteToken (name);
14793ae02089SMasatake YAMATO
14803ae02089SMasatake YAMATO return token->type == TOKEN_EQUAL_SIGN;
14813ae02089SMasatake YAMATO }
14823ae02089SMasatake YAMATO
14833ae02089SMasatake YAMATO /* parses declarations of the form
14843ae02089SMasatake YAMATO * define('NAME', 'VALUE')
14853ae02089SMasatake YAMATO * define(NAME, 'VALUE) */
parseDefine(tokenInfo * const token)1486ce990805SThomas Braun static bool parseDefine (tokenInfo *const token)
14873ae02089SMasatake YAMATO {
14883ae02089SMasatake YAMATO int depth = 1;
14893ae02089SMasatake YAMATO
14903ae02089SMasatake YAMATO readToken (token); /* skip "define" identifier */
14913ae02089SMasatake YAMATO if (token->type != TOKEN_OPEN_PAREN)
1492ce990805SThomas Braun return false;
14933ae02089SMasatake YAMATO
14943ae02089SMasatake YAMATO readToken (token);
14953ae02089SMasatake YAMATO if (token->type == TOKEN_STRING ||
14963ae02089SMasatake YAMATO token->type == TOKEN_IDENTIFIER)
14973ae02089SMasatake YAMATO {
14983ae02089SMasatake YAMATO makeSimplePhpTag (token, K_DEFINE, ACCESS_UNDEFINED);
14993ae02089SMasatake YAMATO readToken (token);
15003ae02089SMasatake YAMATO }
15013ae02089SMasatake YAMATO
15023ae02089SMasatake YAMATO /* skip until the close parenthesis.
15033ae02089SMasatake YAMATO * no need to handle nested blocks since they would be invalid
15043ae02089SMasatake YAMATO * in this context anyway (the VALUE may only be a scalar, like
15053ae02089SMasatake YAMATO * 42
15063ae02089SMasatake YAMATO * (42)
15073ae02089SMasatake YAMATO * and alike) */
15083ae02089SMasatake YAMATO while (token->type != TOKEN_EOF && depth > 0)
15093ae02089SMasatake YAMATO {
15103ae02089SMasatake YAMATO switch (token->type)
15113ae02089SMasatake YAMATO {
15123ae02089SMasatake YAMATO case TOKEN_OPEN_PAREN: depth++; break;
15133ae02089SMasatake YAMATO case TOKEN_CLOSE_PAREN: depth--; break;
15143ae02089SMasatake YAMATO default: break;
15153ae02089SMasatake YAMATO }
15163ae02089SMasatake YAMATO readToken (token);
15173ae02089SMasatake YAMATO }
15183ae02089SMasatake YAMATO
1519ce990805SThomas Braun return false;
15203ae02089SMasatake YAMATO }
15213ae02089SMasatake YAMATO
15223ae02089SMasatake YAMATO /* parses declarations of the form
1523c65c05feSColomban Wendling * use Foo
1524c65c05feSColomban Wendling * use Foo\Bar\Class
1525c65c05feSColomban Wendling * use Foo\Bar\Class as FooBarClass
1526c65c05feSColomban Wendling * use function Foo\Bar\func
1527c65c05feSColomban Wendling * use function Foo\Bar\func as foobarfunc
1528c65c05feSColomban Wendling * use const Foo\Bar\CONST
1529c65c05feSColomban Wendling * use const Foo\Bar\CONST as FOOBARCONST
1530c65c05feSColomban Wendling * use Foo, Bar
1531c65c05feSColomban Wendling * use Foo, Bar as Baz
153250d1ddbaSColomban Wendling * use Foo as Test, Bar as Baz
153350d1ddbaSColomban Wendling * use Foo\{Bar, Baz as Child, Nested\Other, Even\More as Something} */
parseUse(tokenInfo * const token)1534ce990805SThomas Braun static bool parseUse (tokenInfo *const token)
1535c65c05feSColomban Wendling {
1536ce990805SThomas Braun bool readNext = false;
1537c65c05feSColomban Wendling /* we can't know the use type, because class, interface and namespaces
1538c65c05feSColomban Wendling * aliases are the same, and the only difference is the referenced name's
1539c65c05feSColomban Wendling * type */
1540c65c05feSColomban Wendling const char *refType = "unknown";
154150d1ddbaSColomban Wendling vString *refName = vStringNew ();
154250d1ddbaSColomban Wendling tokenInfo *nameToken = newToken ();
1543ce990805SThomas Braun bool grouped = false;
1544c65c05feSColomban Wendling
1545c65c05feSColomban Wendling readToken (token); /* skip use keyword itself */
1546c65c05feSColomban Wendling if (token->type == TOKEN_KEYWORD && (token->keyword == KEYWORD_function ||
1547c65c05feSColomban Wendling token->keyword == KEYWORD_const))
1548c65c05feSColomban Wendling {
1549c65c05feSColomban Wendling switch (token->keyword)
1550c65c05feSColomban Wendling {
1551c65c05feSColomban Wendling case KEYWORD_function: refType = PhpKinds[K_FUNCTION].name; break;
1552c65c05feSColomban Wendling case KEYWORD_const: refType = PhpKinds[K_DEFINE].name; break;
1553c65c05feSColomban Wendling default: break; /* silence compilers */
1554c65c05feSColomban Wendling }
1555ce990805SThomas Braun readNext = true;
1556c65c05feSColomban Wendling }
1557c65c05feSColomban Wendling
1558c65c05feSColomban Wendling if (readNext)
1559c65c05feSColomban Wendling readToken (token);
1560c65c05feSColomban Wendling
156150d1ddbaSColomban Wendling readQualifiedName (token, refName, nameToken);
156250d1ddbaSColomban Wendling grouped = readNext = (token->type == TOKEN_OPEN_CURLY);
156350d1ddbaSColomban Wendling
156450d1ddbaSColomban Wendling do
1565c65c05feSColomban Wendling {
156650d1ddbaSColomban Wendling size_t refNamePrefixLength = grouped ? vStringLength (refName) : 0;
156750d1ddbaSColomban Wendling
156850d1ddbaSColomban Wendling /* if it's either not the first name in a comma-separated list, or we
156950d1ddbaSColomban Wendling * are in a grouped alias and need to read the leaf name */
157050d1ddbaSColomban Wendling if (readNext)
157150d1ddbaSColomban Wendling {
1572c65c05feSColomban Wendling readToken (token);
157323121268SColomban Wendling /* in case of a trailing comma (or an empty group) */
157423121268SColomban Wendling if (token->type == TOKEN_CLOSE_CURLY)
157523121268SColomban Wendling break;
157650d1ddbaSColomban Wendling readQualifiedName (token, refName, nameToken);
1577c65c05feSColomban Wendling }
1578c65c05feSColomban Wendling
1579c65c05feSColomban Wendling if (token->type == TOKEN_KEYWORD && token->keyword == KEYWORD_as)
1580c65c05feSColomban Wendling {
1581c65c05feSColomban Wendling readToken (token);
1582ce990805SThomas Braun copyToken (nameToken, token, true);
1583c65c05feSColomban Wendling readToken (token);
1584c65c05feSColomban Wendling }
1585c65c05feSColomban Wendling
1586169a661fSDawid Zamirski if (nameToken->type == TOKEN_IDENTIFIER && PhpKinds[K_ALIAS].enabled)
1587c65c05feSColomban Wendling {
1588c65c05feSColomban Wendling tagEntryInfo entry;
1589c65c05feSColomban Wendling
1590c65c05feSColomban Wendling initPhpEntry (&entry, nameToken, K_ALIAS, ACCESS_UNDEFINED);
1591c65c05feSColomban Wendling
1592c65c05feSColomban Wendling entry.extensionFields.typeRef[0] = refType;
1593c65c05feSColomban Wendling entry.extensionFields.typeRef[1] = vStringValue (refName);
1594c65c05feSColomban Wendling
1595c65c05feSColomban Wendling makePhpTagEntry (&entry);
1596c65c05feSColomban Wendling }
1597c65c05feSColomban Wendling
159850d1ddbaSColomban Wendling vStringTruncate (refName, refNamePrefixLength);
1599c65c05feSColomban Wendling
1600ce990805SThomas Braun readNext = true;
1601c65c05feSColomban Wendling }
1602c65c05feSColomban Wendling while (token->type == TOKEN_COMMA);
1603c65c05feSColomban Wendling
160450d1ddbaSColomban Wendling if (grouped && token->type == TOKEN_CLOSE_CURLY)
160550d1ddbaSColomban Wendling readToken (token);
160650d1ddbaSColomban Wendling
160750d1ddbaSColomban Wendling vStringDelete (refName);
160850d1ddbaSColomban Wendling deleteToken (nameToken);
160950d1ddbaSColomban Wendling
1610c65c05feSColomban Wendling return (token->type == TOKEN_SEMICOLON);
1611c65c05feSColomban Wendling }
1612c65c05feSColomban Wendling
1613c65c05feSColomban Wendling /* parses declarations of the form
16143ae02089SMasatake YAMATO * $var = VALUE
16153ae02089SMasatake YAMATO * $var; */
parseVariable(tokenInfo * const token,vString * typeName)16165ed230b0SMasatake YAMATO static bool parseVariable (tokenInfo *const token, vString * typeName)
16173ae02089SMasatake YAMATO {
16183ae02089SMasatake YAMATO tokenInfo *name;
1619ce990805SThomas Braun bool readNext = true;
16203ae02089SMasatake YAMATO accessType access = CurrentStatement.access;
16213ae02089SMasatake YAMATO
16223ae02089SMasatake YAMATO name = newToken ();
1623ce990805SThomas Braun copyToken (name, token, true);
16243ae02089SMasatake YAMATO
16253ae02089SMasatake YAMATO readToken (token);
16263ae02089SMasatake YAMATO if (token->type == TOKEN_EQUAL_SIGN)
16273ae02089SMasatake YAMATO {
16283ae02089SMasatake YAMATO phpKind kind = K_VARIABLE;
16293ae02089SMasatake YAMATO
16303ae02089SMasatake YAMATO if (token->parentKind == K_FUNCTION)
16313ae02089SMasatake YAMATO kind = K_LOCAL_VARIABLE;
16323ae02089SMasatake YAMATO
16333ae02089SMasatake YAMATO readToken (token);
16343ae02089SMasatake YAMATO if (token->type == TOKEN_KEYWORD &&
16353ae02089SMasatake YAMATO token->keyword == KEYWORD_function &&
16363ae02089SMasatake YAMATO PhpKinds[kind].enabled)
16373ae02089SMasatake YAMATO {
16383ae02089SMasatake YAMATO if (parseFunction (token, name))
16393ae02089SMasatake YAMATO readToken (token);
1640ce990805SThomas Braun readNext = (bool) (token->type == TOKEN_SEMICOLON);
16413ae02089SMasatake YAMATO }
16423ae02089SMasatake YAMATO else
16433ae02089SMasatake YAMATO {
16443ae02089SMasatake YAMATO makeSimplePhpTag (name, kind, access);
1645ce990805SThomas Braun readNext = false;
16463ae02089SMasatake YAMATO }
16473ae02089SMasatake YAMATO }
16483ae02089SMasatake YAMATO else if (token->type == TOKEN_SEMICOLON)
16493ae02089SMasatake YAMATO {
16503ae02089SMasatake YAMATO /* generate tags for variable declarations in classes
16513ae02089SMasatake YAMATO * class Foo {
16523ae02089SMasatake YAMATO * protected $foo;
16533ae02089SMasatake YAMATO * }
16543ae02089SMasatake YAMATO * but don't get fooled by stuff like $foo = $bar; */
1655a5c4c7d1SColomban Wendling if (token->parentKind == K_CLASS ||
1656a5c4c7d1SColomban Wendling token->parentKind == K_INTERFACE ||
1657a5c4c7d1SColomban Wendling token->parentKind == K_TRAIT)
16585ed230b0SMasatake YAMATO makeTypedPhpTag (name, K_VARIABLE, access, typeName);
16593ae02089SMasatake YAMATO }
16603ae02089SMasatake YAMATO else
1661ce990805SThomas Braun readNext = false;
16623ae02089SMasatake YAMATO
16633ae02089SMasatake YAMATO deleteToken (name);
16643ae02089SMasatake YAMATO
16653ae02089SMasatake YAMATO return readNext;
16663ae02089SMasatake YAMATO }
16673ae02089SMasatake YAMATO
16683ae02089SMasatake YAMATO /* parses namespace declarations
16693ae02089SMasatake YAMATO * namespace Foo {}
16703ae02089SMasatake YAMATO * namespace Foo\Bar {}
16713ae02089SMasatake YAMATO * namespace Foo;
16723ae02089SMasatake YAMATO * namespace Foo\Bar;
16733ae02089SMasatake YAMATO * namespace;
1674759d281dSK.Takata * namespace {} */
parseNamespace(tokenInfo * const token)1675ce990805SThomas Braun static bool parseNamespace (tokenInfo *const token)
16763ae02089SMasatake YAMATO {
16773ae02089SMasatake YAMATO tokenInfo *nsToken = newToken ();
16783ae02089SMasatake YAMATO
16793ae02089SMasatake YAMATO vStringClear (CurrentNamesapce);
1680ce990805SThomas Braun copyToken (nsToken, token, false);
16813ae02089SMasatake YAMATO
16823ae02089SMasatake YAMATO do
16833ae02089SMasatake YAMATO {
16843ae02089SMasatake YAMATO readToken (token);
16853ae02089SMasatake YAMATO if (token->type == TOKEN_IDENTIFIER)
16863ae02089SMasatake YAMATO {
16873ae02089SMasatake YAMATO if (vStringLength (CurrentNamesapce) > 0)
1688a4af1067SMasatake YAMATO {
1689a4af1067SMasatake YAMATO const char *sep;
1690a4af1067SMasatake YAMATO
1691a4af1067SMasatake YAMATO sep = phpScopeSeparatorFor(K_NAMESPACE,
1692a4af1067SMasatake YAMATO K_NAMESPACE);
1693a4af1067SMasatake YAMATO vStringCatS (CurrentNamesapce, sep);
1694a4af1067SMasatake YAMATO }
16953ae02089SMasatake YAMATO vStringCat (CurrentNamesapce, token->string);
16963ae02089SMasatake YAMATO }
16973ae02089SMasatake YAMATO }
16983ae02089SMasatake YAMATO while (token->type != TOKEN_EOF &&
16993ae02089SMasatake YAMATO token->type != TOKEN_SEMICOLON &&
17003ae02089SMasatake YAMATO token->type != TOKEN_OPEN_CURLY);
17013ae02089SMasatake YAMATO
17023ae02089SMasatake YAMATO if (vStringLength (CurrentNamesapce) > 0)
17033ae02089SMasatake YAMATO makeNamespacePhpTag (nsToken, CurrentNamesapce);
17043ae02089SMasatake YAMATO
17053ae02089SMasatake YAMATO if (token->type == TOKEN_OPEN_CURLY)
17063ae02089SMasatake YAMATO enterScope (token, NULL, -1);
17073ae02089SMasatake YAMATO
17083ae02089SMasatake YAMATO deleteToken (nsToken);
17093ae02089SMasatake YAMATO
1710ce990805SThomas Braun return true;
17113ae02089SMasatake YAMATO }
17123ae02089SMasatake YAMATO
enterScope(tokenInfo * const parentToken,const vString * const extraScope,const int parentKind)17133ae02089SMasatake YAMATO static void enterScope (tokenInfo *const parentToken,
17143ae02089SMasatake YAMATO const vString *const extraScope,
17153ae02089SMasatake YAMATO const int parentKind)
17163ae02089SMasatake YAMATO {
17173ae02089SMasatake YAMATO tokenInfo *token = newToken ();
17185ed230b0SMasatake YAMATO vString *typeName = vStringNew ();
17193ae02089SMasatake YAMATO int origParentKind = parentToken->parentKind;
17203ae02089SMasatake YAMATO
1721ce990805SThomas Braun copyToken (token, parentToken, true);
17223ae02089SMasatake YAMATO
17233ae02089SMasatake YAMATO if (extraScope)
17243ae02089SMasatake YAMATO {
17253ae02089SMasatake YAMATO token->parentKind = parentKind;
1726a4af1067SMasatake YAMATO addToScope (token, extraScope, origParentKind);
17273ae02089SMasatake YAMATO }
17283ae02089SMasatake YAMATO
17293ae02089SMasatake YAMATO readToken (token);
17303ae02089SMasatake YAMATO while (token->type != TOKEN_EOF &&
17313ae02089SMasatake YAMATO token->type != TOKEN_CLOSE_CURLY)
17323ae02089SMasatake YAMATO {
1733ce990805SThomas Braun bool readNext = true;
17343ae02089SMasatake YAMATO
17353ae02089SMasatake YAMATO switch (token->type)
17363ae02089SMasatake YAMATO {
17373ae02089SMasatake YAMATO case TOKEN_OPEN_CURLY:
17383ae02089SMasatake YAMATO enterScope (token, NULL, -1);
17393ae02089SMasatake YAMATO break;
17403ae02089SMasatake YAMATO
17413ae02089SMasatake YAMATO case TOKEN_KEYWORD:
17423ae02089SMasatake YAMATO switch (token->keyword)
17433ae02089SMasatake YAMATO {
1744d0d29d63SColomban Wendling /* handle anonymous classes */
1745d0d29d63SColomban Wendling case KEYWORD_new:
1746d0d29d63SColomban Wendling readToken (token);
1747d0d29d63SColomban Wendling if (token->keyword != KEYWORD_class)
1748ce990805SThomas Braun readNext = false;
1749d0d29d63SColomban Wendling else
1750d0d29d63SColomban Wendling {
1751d0d29d63SColomban Wendling tokenInfo *name = newToken ();
1752d0d29d63SColomban Wendling
1753ce990805SThomas Braun copyToken (name, token, true);
17543165d268SMasatake YAMATO anonGenerate (name->string, "AnonymousClass", K_CLASS);
17553165d268SMasatake YAMATO name->anonymous = true;
1756d0d29d63SColomban Wendling readNext = parseClassOrIface (token, K_CLASS, name);
1757d0d29d63SColomban Wendling deleteToken (name);
1758d0d29d63SColomban Wendling }
1759d0d29d63SColomban Wendling break;
1760d0d29d63SColomban Wendling
1761d0d29d63SColomban Wendling case KEYWORD_class: readNext = parseClassOrIface (token, K_CLASS, NULL); break;
1762d0d29d63SColomban Wendling case KEYWORD_interface: readNext = parseClassOrIface (token, K_INTERFACE, NULL); break;
17633ae02089SMasatake YAMATO case KEYWORD_trait: readNext = parseTrait (token); break;
17643ae02089SMasatake YAMATO case KEYWORD_function: readNext = parseFunction (token, NULL); break;
17653ae02089SMasatake YAMATO case KEYWORD_const: readNext = parseConstant (token); break;
17663ae02089SMasatake YAMATO case KEYWORD_define: readNext = parseDefine (token); break;
17673ae02089SMasatake YAMATO
1768c65c05feSColomban Wendling case KEYWORD_use:
1769c65c05feSColomban Wendling /* aliases are only allowed at root scope, but the keyword
1770c65c05feSColomban Wendling * is also used to i.e. "import" traits into a class */
1771c65c05feSColomban Wendling if (vStringLength (token->scope) == 0)
1772c65c05feSColomban Wendling readNext = parseUse (token);
1773c65c05feSColomban Wendling break;
1774c65c05feSColomban Wendling
17753ae02089SMasatake YAMATO case KEYWORD_namespace: readNext = parseNamespace (token); break;
17763ae02089SMasatake YAMATO
17773ae02089SMasatake YAMATO case KEYWORD_private: CurrentStatement.access = ACCESS_PRIVATE; break;
17783ae02089SMasatake YAMATO case KEYWORD_protected: CurrentStatement.access = ACCESS_PROTECTED; break;
17793ae02089SMasatake YAMATO case KEYWORD_public: CurrentStatement.access = ACCESS_PUBLIC; break;
17803ae02089SMasatake YAMATO case KEYWORD_var: CurrentStatement.access = ACCESS_PUBLIC; break;
17813ae02089SMasatake YAMATO
17823ae02089SMasatake YAMATO case KEYWORD_abstract: CurrentStatement.impl = IMPL_ABSTRACT; break;
17833ae02089SMasatake YAMATO
17843ae02089SMasatake YAMATO default: break;
17853ae02089SMasatake YAMATO }
17863ae02089SMasatake YAMATO break;
17873ae02089SMasatake YAMATO
17885ed230b0SMasatake YAMATO case TOKEN_QMARK:
17895ed230b0SMasatake YAMATO vStringClear (typeName);
17905ed230b0SMasatake YAMATO vStringPut (typeName, '?');
17915ed230b0SMasatake YAMATO readNext = true;
17925ed230b0SMasatake YAMATO break;
17935ed230b0SMasatake YAMATO case TOKEN_IDENTIFIER:
17945ed230b0SMasatake YAMATO vStringCat (typeName, token->string);
17955ed230b0SMasatake YAMATO readNext = true;
17965ed230b0SMasatake YAMATO break;
17973ae02089SMasatake YAMATO case TOKEN_VARIABLE:
17985ed230b0SMasatake YAMATO readNext = parseVariable (token,
17995ed230b0SMasatake YAMATO vStringIsEmpty(typeName)
18005ed230b0SMasatake YAMATO ? NULL
18015ed230b0SMasatake YAMATO : typeName);
18025ed230b0SMasatake YAMATO vStringClear (typeName);
18033ae02089SMasatake YAMATO break;
18043ae02089SMasatake YAMATO
18053ae02089SMasatake YAMATO default: break;
18063ae02089SMasatake YAMATO }
18073ae02089SMasatake YAMATO
18083ae02089SMasatake YAMATO if (readNext)
18093ae02089SMasatake YAMATO readToken (token);
18103ae02089SMasatake YAMATO }
18113ae02089SMasatake YAMATO
1812ce990805SThomas Braun copyToken (parentToken, token, false);
18133ae02089SMasatake YAMATO parentToken->parentKind = origParentKind;
18145ed230b0SMasatake YAMATO vStringDelete (typeName);
18153ae02089SMasatake YAMATO deleteToken (token);
18163ae02089SMasatake YAMATO }
18173ae02089SMasatake YAMATO
findTags(bool startsInPhpMode)1818ce990805SThomas Braun static void findTags (bool startsInPhpMode)
18193ae02089SMasatake YAMATO {
18203ae02089SMasatake YAMATO tokenInfo *const token = newToken ();
18213ae02089SMasatake YAMATO
18223ae02089SMasatake YAMATO InPhp = startsInPhpMode;
182375ba24d4SColomban Wendling MayBeKeyword = true;
18243ae02089SMasatake YAMATO CurrentStatement.access = ACCESS_UNDEFINED;
18253ae02089SMasatake YAMATO CurrentStatement.impl = IMPL_UNDEFINED;
18263ae02089SMasatake YAMATO CurrentNamesapce = vStringNew ();
18273ae02089SMasatake YAMATO FullScope = vStringNew ();
1828f176923cSMasatake YAMATO Assert (ParentClass == NULL);
18293ae02089SMasatake YAMATO
18303ae02089SMasatake YAMATO do
18313ae02089SMasatake YAMATO {
18323ae02089SMasatake YAMATO enterScope (token, NULL, -1);
18333ae02089SMasatake YAMATO }
18343ae02089SMasatake YAMATO while (token->type != TOKEN_EOF); /* keep going even with unmatched braces */
18353ae02089SMasatake YAMATO
18363ae02089SMasatake YAMATO vStringDelete (FullScope);
18373ae02089SMasatake YAMATO vStringDelete (CurrentNamesapce);
18383ae02089SMasatake YAMATO deleteToken (token);
18393ae02089SMasatake YAMATO }
18403ae02089SMasatake YAMATO
findPhpTags(void)18413ae02089SMasatake YAMATO static void findPhpTags (void)
18423ae02089SMasatake YAMATO {
1843ce990805SThomas Braun findTags (false);
18443ae02089SMasatake YAMATO }
18453ae02089SMasatake YAMATO
findZephirTags(void)18463ae02089SMasatake YAMATO static void findZephirTags (void)
18473ae02089SMasatake YAMATO {
1848ce990805SThomas Braun findTags (true);
18493ae02089SMasatake YAMATO }
18503ae02089SMasatake YAMATO
initializePool(void)18510988269fSJiří Techet static void initializePool (void)
18520988269fSJiří Techet {
18530988269fSJiří Techet if (TokenPool == NULL)
1854e013efc1SMasatake YAMATO TokenPool = objPoolNew (16, newPoolToken, deletePoolToken, clearPoolToken, NULL);
18550988269fSJiří Techet }
18560988269fSJiří Techet
initializePhpParser(const langType language)18573ae02089SMasatake YAMATO static void initializePhpParser (const langType language)
18583ae02089SMasatake YAMATO {
18593ae02089SMasatake YAMATO Lang_php = language;
18600988269fSJiří Techet initializePool ();
18613ae02089SMasatake YAMATO }
18623ae02089SMasatake YAMATO
initializeZephirParser(const langType language)18633ae02089SMasatake YAMATO static void initializeZephirParser (const langType language)
18643ae02089SMasatake YAMATO {
18653ae02089SMasatake YAMATO Lang_zephir = language;
18660988269fSJiří Techet initializePool ();
18670988269fSJiří Techet }
18680988269fSJiří Techet
finalize(langType language CTAGS_ATTR_UNUSED,bool initialized)18690988269fSJiří Techet static void finalize (langType language CTAGS_ATTR_UNUSED, bool initialized)
18700988269fSJiří Techet {
18710988269fSJiří Techet if (!initialized)
18720988269fSJiří Techet return;
18730988269fSJiří Techet
18740988269fSJiří Techet if (TokenPool != NULL)
18750988269fSJiří Techet {
18760988269fSJiří Techet objPoolDelete (TokenPool);
18770988269fSJiří Techet TokenPool = NULL;
18780988269fSJiří Techet }
18793ae02089SMasatake YAMATO }
18803ae02089SMasatake YAMATO
PhpParser(void)18813ae02089SMasatake YAMATO extern parserDefinition* PhpParser (void)
18823ae02089SMasatake YAMATO {
1883ed38f7a3SColomban Wendling static const char *const extensions [] = { "php", "php3", "php4", "php5", "php7", "phtml", NULL };
18843ae02089SMasatake YAMATO parserDefinition* def = parserNew ("PHP");
188509ae690fSMasatake YAMATO def->kindTable = PhpKinds;
18863db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (PhpKinds);
18873ae02089SMasatake YAMATO def->extensions = extensions;
18883ae02089SMasatake YAMATO def->parser = findPhpTags;
18893ae02089SMasatake YAMATO def->initialize = initializePhpParser;
18900988269fSJiří Techet def->finalize = finalize;
1891c379c5d2SMasatake YAMATO def->keywordTable = PhpKeywordTable;
18923db72c21SMasatake YAMATO def->keywordCount = ARRAY_SIZE (PhpKeywordTable);
18933ae02089SMasatake YAMATO return def;
18943ae02089SMasatake YAMATO }
18953ae02089SMasatake YAMATO
ZephirParser(void)18963ae02089SMasatake YAMATO extern parserDefinition* ZephirParser (void)
18973ae02089SMasatake YAMATO {
18983ae02089SMasatake YAMATO static const char *const extensions [] = { "zep", NULL };
18993ae02089SMasatake YAMATO parserDefinition* def = parserNew ("Zephir");
190009ae690fSMasatake YAMATO def->kindTable = PhpKinds;
19013db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (PhpKinds);
19023ae02089SMasatake YAMATO def->extensions = extensions;
19033ae02089SMasatake YAMATO def->parser = findZephirTags;
19043ae02089SMasatake YAMATO def->initialize = initializeZephirParser;
19050988269fSJiří Techet def->finalize = finalize;
1906c379c5d2SMasatake YAMATO def->keywordTable = PhpKeywordTable;
19073db72c21SMasatake YAMATO def->keywordCount = ARRAY_SIZE (PhpKeywordTable);
19083ae02089SMasatake YAMATO return def;
19093ae02089SMasatake YAMATO }
1910