xref: /Universal-ctags/parsers/perl6.c (revision af24e4f7ca6d97cd3d2b09b20847e5b0bf239e81)
1acae9f99SDmitri Tikhonov /*
2acae9f99SDmitri Tikhonov  * perl6.c -- Perl6 parser.
3acae9f99SDmitri Tikhonov  * Author: Dmitri Tikhonov <dmitri@cpan.org>
4acae9f99SDmitri Tikhonov  *
5acae9f99SDmitri Tikhonov  * This is a very basic Perl 6 parser.  It does not know how to:
6acae9f99SDmitri Tikhonov  *   - skip POD;
7acae9f99SDmitri Tikhonov  *   - skip multiline comments;
8acae9f99SDmitri Tikhonov  *   - skip quoted strings;
9acae9f99SDmitri Tikhonov  *   - generate fully-qualified tags.
10acae9f99SDmitri Tikhonov  *
11acae9f99SDmitri Tikhonov  * This source code is released for free distribution under the terms of
120ce38835Sviccuad  * the GNU General Public License version 2 or (at your option) any later version.
13acae9f99SDmitri Tikhonov  */
14acae9f99SDmitri Tikhonov 
15792c8196SDmitri Tikhonov #include "general.h"    /* must always come first */
16792c8196SDmitri Tikhonov 
17acae9f99SDmitri Tikhonov #include <stdio.h>
18acae9f99SDmitri Tikhonov #include <string.h>
19acae9f99SDmitri Tikhonov 
20acae9f99SDmitri Tikhonov #include "debug.h"
21acae9f99SDmitri Tikhonov #include "entry.h"
220d502ef0SMasatake YAMATO #include "parse.h"
23acae9f99SDmitri Tikhonov #include "read.h"
24acae9f99SDmitri Tikhonov #include "routines.h"
25acae9f99SDmitri Tikhonov #include "selectors.h"
26acae9f99SDmitri Tikhonov #include "vstring.h"
27acae9f99SDmitri Tikhonov 
28acae9f99SDmitri Tikhonov enum perl6Kind {
29acae9f99SDmitri Tikhonov     K_NONE = -1,
30acae9f99SDmitri Tikhonov     K_CLASS,
31acae9f99SDmitri Tikhonov     K_GRAMMAR,
32acae9f99SDmitri Tikhonov     K_METHOD,
33acae9f99SDmitri Tikhonov     K_MODULE,
34ce3d88feSDmitri Tikhonov     K_PACKAGE,
35acae9f99SDmitri Tikhonov     K_ROLE,
36acae9f99SDmitri Tikhonov     K_RULE,
37acae9f99SDmitri Tikhonov     K_SUBMETHOD,
38acae9f99SDmitri Tikhonov     K_SUBROUTINE,
39acae9f99SDmitri Tikhonov     K_TOKEN,
40acae9f99SDmitri Tikhonov };
41acae9f99SDmitri Tikhonov 
42e112e8abSMasatake YAMATO static kindDefinition perl6Kinds[] = {
43ce990805SThomas Braun     [K_CLASS]       = { true,  'c', "class",      "classes" },
44ce990805SThomas Braun     [K_GRAMMAR]     = { true,  'g', "grammar",    "grammars" },
45ce990805SThomas Braun     [K_METHOD]      = { true,  'm', "method",     "methods" },
46ce990805SThomas Braun     [K_MODULE]      = { true,  'o', "module",     "modules" },
47ce990805SThomas Braun     [K_PACKAGE]     = { true,  'p', "package",    "packages" },
48ce990805SThomas Braun     [K_ROLE]        = { true,  'r', "role",       "roles" },
49ce990805SThomas Braun     [K_RULE]        = { true,  'u', "rule",       "rules" },
50ce990805SThomas Braun     [K_SUBMETHOD]   = { true,  'b', "submethod",  "submethods" },
51ce990805SThomas Braun     [K_SUBROUTINE]  = { true,  's', "subroutine", "subroutines" },
52ce990805SThomas Braun     [K_TOKEN]       = { true,  't', "token",      "tokens" },
53acae9f99SDmitri Tikhonov };
54acae9f99SDmitri Tikhonov 
55acae9f99SDmitri Tikhonov enum token {
56acae9f99SDmitri Tikhonov     T_CLASS,
57acae9f99SDmitri Tikhonov     T_GRAMMAR,
58acae9f99SDmitri Tikhonov     T_METHOD,
59acae9f99SDmitri Tikhonov     T_MODULE,
60acae9f99SDmitri Tikhonov     T_MULTI,
61acae9f99SDmitri Tikhonov     T_MY,
62acae9f99SDmitri Tikhonov     T_OUR,
63ce3d88feSDmitri Tikhonov     T_PACKAGE,
64acae9f99SDmitri Tikhonov     T_PROTO,
65acae9f99SDmitri Tikhonov     T_ROLE,
66acae9f99SDmitri Tikhonov     T_RULE,
67acae9f99SDmitri Tikhonov     T_SUB,
68acae9f99SDmitri Tikhonov     T_SUBMETHOD,
69acae9f99SDmitri Tikhonov     T_UNIT,
70acae9f99SDmitri Tikhonov     T_TOKEN,
71acae9f99SDmitri Tikhonov };
72acae9f99SDmitri Tikhonov 
73acae9f99SDmitri Tikhonov static const enum perl6Kind token2kind[] = {
74acae9f99SDmitri Tikhonov     [T_CLASS]       = K_CLASS,
75acae9f99SDmitri Tikhonov     [T_GRAMMAR]     = K_GRAMMAR,
76acae9f99SDmitri Tikhonov     [T_METHOD]      = K_METHOD,
77acae9f99SDmitri Tikhonov     [T_MODULE]      = K_MODULE,
78acae9f99SDmitri Tikhonov     [T_MULTI]       = K_SUBROUTINE,
79acae9f99SDmitri Tikhonov     [T_MY]          = K_NONE,
80acae9f99SDmitri Tikhonov     [T_OUR]         = K_NONE,
81ce3d88feSDmitri Tikhonov     [T_PACKAGE]     = K_PACKAGE,
82acae9f99SDmitri Tikhonov     [T_PROTO]       = K_NONE,
83acae9f99SDmitri Tikhonov     [T_ROLE]        = K_ROLE,
84acae9f99SDmitri Tikhonov     [T_RULE]        = K_RULE,
85acae9f99SDmitri Tikhonov     [T_SUB]         = K_SUBROUTINE,
86acae9f99SDmitri Tikhonov     [T_SUBMETHOD]   = K_SUBMETHOD,
87acae9f99SDmitri Tikhonov     [T_UNIT]        = K_NONE,
88acae9f99SDmitri Tikhonov     [T_TOKEN]       = K_TOKEN,
89acae9f99SDmitri Tikhonov };
90acae9f99SDmitri Tikhonov 
91acae9f99SDmitri Tikhonov #define STRLEN(s) (sizeof(s) - 1)
92acae9f99SDmitri Tikhonov #define STREQN(s, token) (0 == strncmp(s, token, STRLEN(token)))
93acae9f99SDmitri Tikhonov 
94acae9f99SDmitri Tikhonov static enum token
matchToken(const char * s,int len)95acae9f99SDmitri Tikhonov matchToken (const char *s, int len)
96acae9f99SDmitri Tikhonov {
97acae9f99SDmitri Tikhonov     switch (len) {
98acae9f99SDmitri Tikhonov         case 2:
99acae9f99SDmitri Tikhonov             if (STREQN(s, "my"))                return T_MY;
100acae9f99SDmitri Tikhonov             break;
101acae9f99SDmitri Tikhonov         case 3:
102acae9f99SDmitri Tikhonov             switch (s[0]) {
103acae9f99SDmitri Tikhonov                 case 'o':
104acae9f99SDmitri Tikhonov                     if (STREQN(s, "our"))       return T_OUR;
105acae9f99SDmitri Tikhonov                     break;
106acae9f99SDmitri Tikhonov                 case 's':
107acae9f99SDmitri Tikhonov                     if (STREQN(s, "sub"))       return T_SUB;
108acae9f99SDmitri Tikhonov                     break;
109acae9f99SDmitri Tikhonov             }
110acae9f99SDmitri Tikhonov             break;
111acae9f99SDmitri Tikhonov         case 4:
112acae9f99SDmitri Tikhonov             switch (s[1]) {
113acae9f99SDmitri Tikhonov                 case 'o':
114acae9f99SDmitri Tikhonov                     if (STREQN(s, "role"))      return T_ROLE;
115acae9f99SDmitri Tikhonov                     break;
116acae9f99SDmitri Tikhonov                 case 'u':
117acae9f99SDmitri Tikhonov                     if (STREQN(s, "rule"))      return T_RULE;
118acae9f99SDmitri Tikhonov                     break;
119acae9f99SDmitri Tikhonov                 case 'n':
120acae9f99SDmitri Tikhonov                     if (STREQN(s, "unit"))      return T_UNIT;
121acae9f99SDmitri Tikhonov                     break;
122acae9f99SDmitri Tikhonov             }
123acae9f99SDmitri Tikhonov             break;
124acae9f99SDmitri Tikhonov         case 5:
125acae9f99SDmitri Tikhonov             switch (s[0]) {
126acae9f99SDmitri Tikhonov                 case 'c':
127acae9f99SDmitri Tikhonov                     if (STREQN(s, "class"))     return T_CLASS;
128acae9f99SDmitri Tikhonov                     break;
129acae9f99SDmitri Tikhonov                 case 'm':
130acae9f99SDmitri Tikhonov                     if (STREQN(s, "multi"))     return T_MULTI;
131acae9f99SDmitri Tikhonov                     break;
132acae9f99SDmitri Tikhonov                 case 'p':
133acae9f99SDmitri Tikhonov                     if (STREQN(s, "proto"))     return T_PROTO;
134acae9f99SDmitri Tikhonov                     break;
135acae9f99SDmitri Tikhonov                 case 't':
136acae9f99SDmitri Tikhonov                     if (STREQN(s, "token"))     return T_TOKEN;
137acae9f99SDmitri Tikhonov                     break;
138acae9f99SDmitri Tikhonov             }
139acae9f99SDmitri Tikhonov             break;
140acae9f99SDmitri Tikhonov         case 6:
141acae9f99SDmitri Tikhonov             switch (s[1]) {
142acae9f99SDmitri Tikhonov                 case 'e':
143acae9f99SDmitri Tikhonov                     if (STREQN(s, "method"))    return T_METHOD;
144acae9f99SDmitri Tikhonov                     break;
145acae9f99SDmitri Tikhonov                 case 'o':
146acae9f99SDmitri Tikhonov                     if (STREQN(s, "module"))    return T_MODULE;
147acae9f99SDmitri Tikhonov                     break;
148acae9f99SDmitri Tikhonov             }
149acae9f99SDmitri Tikhonov             break;
150acae9f99SDmitri Tikhonov         case 7:
151ce3d88feSDmitri Tikhonov             switch (s[0]) {
152ce3d88feSDmitri Tikhonov                 case 'g':
153acae9f99SDmitri Tikhonov                     if (STREQN(s, "grammar"))   return T_GRAMMAR;
154acae9f99SDmitri Tikhonov                     break;
155ce3d88feSDmitri Tikhonov                 case 'p':
156ce3d88feSDmitri Tikhonov                     if (STREQN(s, "package"))   return T_PACKAGE;
157ce3d88feSDmitri Tikhonov                     break;
158ce3d88feSDmitri Tikhonov             }
159ce3d88feSDmitri Tikhonov             break;
160acae9f99SDmitri Tikhonov         case 9:
161acae9f99SDmitri Tikhonov             if (STREQN(s, "submethod"))         return T_SUBMETHOD;
162acae9f99SDmitri Tikhonov             break;
163acae9f99SDmitri Tikhonov     }
164acae9f99SDmitri Tikhonov     return -1;
165acae9f99SDmitri Tikhonov }
166acae9f99SDmitri Tikhonov 
167792c8196SDmitri Tikhonov static const int validPerl6Identifier[0x100] = {
168acae9f99SDmitri Tikhonov /* r!perl -e "print qq([(int)'\$_'] = 1,\n)for a..z,A..Z,0..9,':','-','_'"|fmt
169acae9f99SDmitri Tikhonov  */
170acae9f99SDmitri Tikhonov     [(int)'a'] = 1, [(int)'b'] = 1, [(int)'c'] = 1, [(int)'d'] = 1,
171acae9f99SDmitri Tikhonov     [(int)'e'] = 1, [(int)'f'] = 1, [(int)'g'] = 1, [(int)'h'] = 1,
172acae9f99SDmitri Tikhonov     [(int)'i'] = 1, [(int)'j'] = 1, [(int)'k'] = 1, [(int)'l'] = 1,
173acae9f99SDmitri Tikhonov     [(int)'m'] = 1, [(int)'n'] = 1, [(int)'o'] = 1, [(int)'p'] = 1,
174acae9f99SDmitri Tikhonov     [(int)'q'] = 1, [(int)'r'] = 1, [(int)'s'] = 1, [(int)'t'] = 1,
175acae9f99SDmitri Tikhonov     [(int)'u'] = 1, [(int)'v'] = 1, [(int)'w'] = 1, [(int)'x'] = 1,
176acae9f99SDmitri Tikhonov     [(int)'y'] = 1, [(int)'z'] = 1, [(int)'A'] = 1, [(int)'B'] = 1,
177acae9f99SDmitri Tikhonov     [(int)'C'] = 1, [(int)'D'] = 1, [(int)'E'] = 1, [(int)'F'] = 1,
178acae9f99SDmitri Tikhonov     [(int)'G'] = 1, [(int)'H'] = 1, [(int)'I'] = 1, [(int)'J'] = 1,
179acae9f99SDmitri Tikhonov     [(int)'K'] = 1, [(int)'L'] = 1, [(int)'M'] = 1, [(int)'N'] = 1,
180acae9f99SDmitri Tikhonov     [(int)'O'] = 1, [(int)'P'] = 1, [(int)'Q'] = 1, [(int)'R'] = 1,
181acae9f99SDmitri Tikhonov     [(int)'S'] = 1, [(int)'T'] = 1, [(int)'U'] = 1, [(int)'V'] = 1,
182acae9f99SDmitri Tikhonov     [(int)'W'] = 1, [(int)'X'] = 1, [(int)'Y'] = 1, [(int)'Z'] = 1,
183acae9f99SDmitri Tikhonov     [(int)'0'] = 1, [(int)'1'] = 1, [(int)'2'] = 1, [(int)'3'] = 1,
184acae9f99SDmitri Tikhonov     [(int)'4'] = 1, [(int)'5'] = 1, [(int)'6'] = 1, [(int)'7'] = 1,
185acae9f99SDmitri Tikhonov     [(int)'8'] = 1, [(int)'9'] = 1, [(int)':'] = 1, [(int)'-'] = 1,
186acae9f99SDmitri Tikhonov     [(int)'_'] = 1,
187acae9f99SDmitri Tikhonov };
188acae9f99SDmitri Tikhonov 
189792c8196SDmitri Tikhonov static const int validMethodPrefix[0x100] = {
190acae9f99SDmitri Tikhonov     [(int)'!'] = 1, [(int)'^'] = 1,
191acae9f99SDmitri Tikhonov };
192acae9f99SDmitri Tikhonov 
193acae9f99SDmitri Tikhonov static const int kindMayHaveMethodPrefix = (1 << K_SUBMETHOD) |
194acae9f99SDmitri Tikhonov                                            (1 << K_METHOD)    ;
195acae9f99SDmitri Tikhonov 
196acae9f99SDmitri Tikhonov /* Trim identifier pointed to by ps, possibly advancing it, and return
197acae9f99SDmitri Tikhonov  * the length of the valid portion.  If the returned value is zero, the
198acae9f99SDmitri Tikhonov  * identifier is invalid.
199acae9f99SDmitri Tikhonov  */
200acae9f99SDmitri Tikhonov static int
trimIdentifier(enum perl6Kind kind,const char ** ps,int len)201acae9f99SDmitri Tikhonov trimIdentifier (enum perl6Kind kind, const char **ps, int len)
202acae9f99SDmitri Tikhonov {
203acae9f99SDmitri Tikhonov     Assert(len > 0);
204acae9f99SDmitri Tikhonov     const char *const end = *ps + len;
205acae9f99SDmitri Tikhonov     const char *s = *ps;
206acae9f99SDmitri Tikhonov     /* Trim the front if possible: */
207acae9f99SDmitri Tikhonov     s += (kindMayHaveMethodPrefix & (1 << kind)) &&
208acae9f99SDmitri Tikhonov          validMethodPrefix[(int)*s];
209acae9f99SDmitri Tikhonov     /* Record the start of identifier: */
210acae9f99SDmitri Tikhonov     *ps = s;
211acae9f99SDmitri Tikhonov     /* Continuous string of valid characters: */
212acae9f99SDmitri Tikhonov     while (s < end && validPerl6Identifier[(int)*s])
213acae9f99SDmitri Tikhonov         ++s;
214acae9f99SDmitri Tikhonov     /* sub multi infix:<...>        -- we want the "infix" only */
215acae9f99SDmitri Tikhonov     while (s - *ps > 0 && ':' == s[-1])
216acae9f99SDmitri Tikhonov         --s;
217acae9f99SDmitri Tikhonov     /* It's ok if this is zero: */
218acae9f99SDmitri Tikhonov     return s - *ps;
219acae9f99SDmitri Tikhonov }
220acae9f99SDmitri Tikhonov 
221acae9f99SDmitri Tikhonov struct p6Ctx {
222acae9f99SDmitri Tikhonov     enum token  tokens[128 /* unlikely to need more than this */];
223e5f9cc19SMasatake YAMATO     unsigned int n_tokens;
224acae9f99SDmitri Tikhonov     vString    *name;
2251b312fe7SMasatake YAMATO     const char *line;      /* Saved from readLineFromInputFile() */
226acae9f99SDmitri Tikhonov };
227acae9f99SDmitri Tikhonov 
228acae9f99SDmitri Tikhonov static void
makeTag(struct p6Ctx * ctx,int kind,const char * name,int len)229acae9f99SDmitri Tikhonov makeTag (struct p6Ctx *ctx, int kind, const char *name, int len)
230acae9f99SDmitri Tikhonov {
231acae9f99SDmitri Tikhonov     tagEntryInfo entry;
232acae9f99SDmitri Tikhonov     vStringNCopyS(ctx->name, name, len);
23316a2541cSMasatake YAMATO     initTagEntry(&entry, vStringValue(ctx->name), kind);
234acae9f99SDmitri Tikhonov     makeTagEntry(&entry);
235acae9f99SDmitri Tikhonov }
236acae9f99SDmitri Tikhonov 
237acae9f99SDmitri Tikhonov static void
possiblyMakeTag(struct p6Ctx * ctx,const char * s,int len)238acae9f99SDmitri Tikhonov possiblyMakeTag (struct p6Ctx *ctx, const char *s, int len)
239acae9f99SDmitri Tikhonov {
240acae9f99SDmitri Tikhonov     Assert(ctx->n_tokens > 0);
241acae9f99SDmitri Tikhonov     enum perl6Kind kind = token2kind[ ctx->tokens[ctx->n_tokens - 1] ];
242acae9f99SDmitri Tikhonov     if (K_NONE != kind && perl6Kinds[kind].enabled
243acae9f99SDmitri Tikhonov                        && (len = trimIdentifier(kind, &s, len)) > 0)
244acae9f99SDmitri Tikhonov         makeTag(ctx, kind, s, len);
245acae9f99SDmitri Tikhonov }
246acae9f99SDmitri Tikhonov 
247acae9f99SDmitri Tikhonov static void
initP6Ctx(struct p6Ctx * ctx)248acae9f99SDmitri Tikhonov initP6Ctx (struct p6Ctx *ctx)
249acae9f99SDmitri Tikhonov {
250acae9f99SDmitri Tikhonov     ctx->n_tokens = 0;
251acae9f99SDmitri Tikhonov     ctx->name = vStringNew();
252acae9f99SDmitri Tikhonov     ctx->line = NULL;
253acae9f99SDmitri Tikhonov }
254acae9f99SDmitri Tikhonov 
255acae9f99SDmitri Tikhonov static void
deinitP6Ctx(struct p6Ctx * ctx)256acae9f99SDmitri Tikhonov deinitP6Ctx (struct p6Ctx *ctx)
257acae9f99SDmitri Tikhonov {
258acae9f99SDmitri Tikhonov     vStringDelete(ctx->name);
259acae9f99SDmitri Tikhonov }
260acae9f99SDmitri Tikhonov 
261acae9f99SDmitri Tikhonov /* Read next contiguous sequence of non-whitespace characters, store
262acae9f99SDmitri Tikhonov  * the address in `ptok', and return its length.  Return value of zero
263acae9f99SDmitri Tikhonov  * means EOF.
264acae9f99SDmitri Tikhonov  *
265acae9f99SDmitri Tikhonov  * TODO: Currently, POD and multi-line comments are not handled.
266acae9f99SDmitri Tikhonov  */
267acae9f99SDmitri Tikhonov static int
getNonSpaceStr(struct p6Ctx * ctx,const char ** ptok)268acae9f99SDmitri Tikhonov getNonSpaceStr (struct p6Ctx *ctx, const char **ptok)
269acae9f99SDmitri Tikhonov {
270acae9f99SDmitri Tikhonov     const char *s = ctx->line;
271acae9f99SDmitri Tikhonov     if (!s) {
272acae9f99SDmitri Tikhonov next_line:
2731b312fe7SMasatake YAMATO         s = (const char *) readLineFromInputFile();
274acae9f99SDmitri Tikhonov         if (!s)
275acae9f99SDmitri Tikhonov             return 0;                           /* EOF */
276acae9f99SDmitri Tikhonov     }
277acae9f99SDmitri Tikhonov     while (*s && isspace(*s))                   /* Skip whitespace */
278acae9f99SDmitri Tikhonov         ++s;
279acae9f99SDmitri Tikhonov     if ('#' == *s)
280acae9f99SDmitri Tikhonov         goto next_line;
281acae9f99SDmitri Tikhonov     int non_white_len = strcspn(s, ",; \t");
282acae9f99SDmitri Tikhonov     if (non_white_len) {
283acae9f99SDmitri Tikhonov         ctx->line = s + non_white_len;          /* Save state */
284acae9f99SDmitri Tikhonov         *ptok = s;
285acae9f99SDmitri Tikhonov         return non_white_len;
286acae9f99SDmitri Tikhonov     } else
287acae9f99SDmitri Tikhonov         goto next_line;
288acae9f99SDmitri Tikhonov }
289acae9f99SDmitri Tikhonov 
290acae9f99SDmitri Tikhonov static void
findPerl6Tags(void)291acae9f99SDmitri Tikhonov findPerl6Tags (void)
292acae9f99SDmitri Tikhonov {
293acae9f99SDmitri Tikhonov     struct p6Ctx ctx;
294acae9f99SDmitri Tikhonov 
295acae9f99SDmitri Tikhonov #define RESET_TOKENS() do { ctx.n_tokens = 0; } while (0)
296acae9f99SDmitri Tikhonov 
297acae9f99SDmitri Tikhonov #define PUSH_TOKEN(_t_) do {                                            \
298158a3387SMasatake YAMATO     if (ctx.n_tokens < ARRAY_SIZE(ctx.tokens)) {			\
299acae9f99SDmitri Tikhonov         ctx.tokens[ ctx.n_tokens ] = _t_;                               \
300acae9f99SDmitri Tikhonov         ++ctx.n_tokens;                                                 \
301acae9f99SDmitri Tikhonov     } else {                                                            \
302acae9f99SDmitri Tikhonov         Assert(!"Token stack overflown: this is quite odd");            \
303acae9f99SDmitri Tikhonov         RESET_TOKENS();                                                 \
304acae9f99SDmitri Tikhonov     }                                                                   \
305acae9f99SDmitri Tikhonov } while (0)
306acae9f99SDmitri Tikhonov 
307acae9f99SDmitri Tikhonov     initP6Ctx(&ctx);
308acae9f99SDmitri Tikhonov 
309acae9f99SDmitri Tikhonov     const char *s;
310acae9f99SDmitri Tikhonov     int len;
311acae9f99SDmitri Tikhonov 
312acae9f99SDmitri Tikhonov     while ((len = getNonSpaceStr(&ctx, &s)) > 0) {
313acae9f99SDmitri Tikhonov         enum token token = matchToken(s, len);
314acae9f99SDmitri Tikhonov         if ((int) token >= 0) {
315acae9f99SDmitri Tikhonov             PUSH_TOKEN(token);
316acae9f99SDmitri Tikhonov         } else if (ctx.n_tokens > 0) {
317acae9f99SDmitri Tikhonov             possiblyMakeTag(&ctx, s, len);
318acae9f99SDmitri Tikhonov             RESET_TOKENS();
319acae9f99SDmitri Tikhonov         }
320acae9f99SDmitri Tikhonov     }
321acae9f99SDmitri Tikhonov 
322acae9f99SDmitri Tikhonov     deinitP6Ctx(&ctx);
323acae9f99SDmitri Tikhonov }
324acae9f99SDmitri Tikhonov 
325acae9f99SDmitri Tikhonov parserDefinition *
Perl6Parser(void)326acae9f99SDmitri Tikhonov Perl6Parser (void)
327acae9f99SDmitri Tikhonov {
328*af24e4f7SJiří Techet     static const char *const extensions[] = { "p6", "pm6", "pm", "pl6",
329*af24e4f7SJiří Techet 		"t6", "raku", "rakumod", "rakutest", NULL };
3305a38b5ceSMasatake YAMATO     static selectLanguage selectors [] = { selectByPickingPerlVersion,
3315a38b5ceSMasatake YAMATO 					   NULL };
332acae9f99SDmitri Tikhonov     parserDefinition* def = parserNew("Perl6");
33309ae690fSMasatake YAMATO     def->kindTable      = perl6Kinds;
3343db72c21SMasatake YAMATO     def->kindCount  = ARRAY_SIZE(perl6Kinds);
335acae9f99SDmitri Tikhonov     def->extensions = extensions;
336acae9f99SDmitri Tikhonov     def->parser     = findPerl6Tags;
3375a38b5ceSMasatake YAMATO     def->selectLanguage = selectors;
338acae9f99SDmitri Tikhonov     return def;
339acae9f99SDmitri Tikhonov }
340