Ruby 4.1.0dev (2026-10-14 revision d037ba85ef1ff1b8a503f240e5ed083b644f1ec5)
parser.h
1#ifndef PRISM_INTERNAL_PARSER_H
2#define PRISM_INTERNAL_PARSER_H
3
5
6#include "prism/internal/arena.h"
7#include "prism/internal/comments.h"
8#include "prism/internal/constant_pool.h"
9#include "prism/internal/encoding.h"
10#include "prism/internal/list.h"
11#include "prism/internal/options.h"
12#include "prism/internal/static_literals.h"
13#include "prism/internal/strpbrk.h"
14
15#include "prism/ast.h"
17#include "prism/parser.h"
18
19#include <stdbool.h>
20#include <stddef.h>
21#include <stdint.h>
22
23/*
24 * This enum provides various bits that represent different kinds of states that
25 * the lexer can track. This is used to determine which kind of token to return
26 * based on the context of the parser.
27 */
28typedef enum {
29 PM_LEX_STATE_BIT_BEG,
30 PM_LEX_STATE_BIT_END,
31 PM_LEX_STATE_BIT_ENDARG,
32 PM_LEX_STATE_BIT_ENDFN,
33 PM_LEX_STATE_BIT_ARG,
34 PM_LEX_STATE_BIT_CMDARG,
35 PM_LEX_STATE_BIT_MID,
36 PM_LEX_STATE_BIT_FNAME,
37 PM_LEX_STATE_BIT_DOT,
38 PM_LEX_STATE_BIT_CLASS,
39 PM_LEX_STATE_BIT_LABEL,
40 PM_LEX_STATE_BIT_LABELED,
41 PM_LEX_STATE_BIT_FITEM
42} pm_lex_state_bit_t;
43
44/*
45 * This enum combines the various bits from the above enum into individual
46 * values that represent the various states of the lexer.
47 */
48typedef enum {
49 PM_LEX_STATE_NONE = 0,
50 PM_LEX_STATE_BEG = (1 << PM_LEX_STATE_BIT_BEG),
51 PM_LEX_STATE_END = (1 << PM_LEX_STATE_BIT_END),
52 PM_LEX_STATE_ENDARG = (1 << PM_LEX_STATE_BIT_ENDARG),
53 PM_LEX_STATE_ENDFN = (1 << PM_LEX_STATE_BIT_ENDFN),
54 PM_LEX_STATE_ARG = (1 << PM_LEX_STATE_BIT_ARG),
55 PM_LEX_STATE_CMDARG = (1 << PM_LEX_STATE_BIT_CMDARG),
56 PM_LEX_STATE_MID = (1 << PM_LEX_STATE_BIT_MID),
57 PM_LEX_STATE_FNAME = (1 << PM_LEX_STATE_BIT_FNAME),
58 PM_LEX_STATE_DOT = (1 << PM_LEX_STATE_BIT_DOT),
59 PM_LEX_STATE_CLASS = (1 << PM_LEX_STATE_BIT_CLASS),
60 PM_LEX_STATE_LABEL = (1 << PM_LEX_STATE_BIT_LABEL),
61 PM_LEX_STATE_LABELED = (1 << PM_LEX_STATE_BIT_LABELED),
62 PM_LEX_STATE_FITEM = (1 << PM_LEX_STATE_BIT_FITEM),
63 PM_LEX_STATE_BEG_ANY = PM_LEX_STATE_BEG | PM_LEX_STATE_MID | PM_LEX_STATE_CLASS,
64 PM_LEX_STATE_ARG_ANY = PM_LEX_STATE_ARG | PM_LEX_STATE_CMDARG,
65 PM_LEX_STATE_END_ANY = PM_LEX_STATE_END | PM_LEX_STATE_ENDARG | PM_LEX_STATE_ENDFN
66} pm_lex_state_t;
67
68/*
69 * The type of quote that a heredoc uses.
70 */
71typedef enum {
72 PM_HEREDOC_QUOTE_NONE,
73 PM_HEREDOC_QUOTE_SINGLE = '\'',
74 PM_HEREDOC_QUOTE_DOUBLE = '"',
75 PM_HEREDOC_QUOTE_BACKTICK = '`',
76} pm_heredoc_quote_t;
77
78/*
79 * The type of indentation that a heredoc uses.
80 */
81typedef enum {
82 PM_HEREDOC_INDENT_NONE,
83 PM_HEREDOC_INDENT_DASH,
84 PM_HEREDOC_INDENT_TILDE,
85} pm_heredoc_indent_t;
86
87/*
88 * All of the information necessary to store to lexing a heredoc.
89 */
90typedef struct {
91 /* A pointer to the start of the heredoc identifier. */
92 const uint8_t *ident_start;
93
94 /* The length of the heredoc identifier. */
95 size_t ident_length;
96
97 /* The type of quote that the heredoc uses. */
98 pm_heredoc_quote_t quote;
99
100 /* The type of indentation that the heredoc uses. */
101 pm_heredoc_indent_t indent;
103
104/*
105 * When lexing Ruby source, the lexer has a small amount of state to tell which
106 * kind of token it is currently lexing. For example, when we find the start of
107 * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After
108 * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that
109 * are found as part of a string.
110 */
111typedef struct pm_lex_mode {
112 /* The type of this lex mode. */
113 enum {
114 /* This state is used when any given token is being lexed. */
115 PM_LEX_DEFAULT,
116
117 /*
118 * This state is used when we're lexing as normal but inside an embedded
119 * expression of a string.
120 */
121 PM_LEX_EMBEXPR,
122
123 /*
124 * This state is used when we're lexing a variable that is embedded
125 * directly inside of a string with the # shorthand.
126 */
127 PM_LEX_EMBVAR,
128
129 /* This state is used when you are inside the content of a heredoc. */
130 PM_LEX_HEREDOC,
131
132 /*
133 * This state is used when we are lexing a list of tokens, as in a %w
134 * word list literal or a %i symbol list literal.
135 */
136 PM_LEX_LIST,
137
138 /*
139 * This state is used when a regular expression has been begun and we
140 * are looking for the terminator.
141 */
142 PM_LEX_REGEXP,
143
144 /*
145 * This state is used when we are lexing a string or a string-like
146 * token, as in string content with either quote or an xstring.
147 */
148 PM_LEX_STRING
149 } mode;
150
151 /* The data associated with this type of lex mode. */
152 union {
153 struct {
154 /* This keeps track of the nesting level of the list. */
155 size_t nesting;
156
157 /* Whether or not interpolation is allowed in this list. */
158 bool interpolation;
159
160 /*
161 * Whether any token has been emitted from this list. A word
162 * separator delimits the opener from the first word, so one
163 * without source characters is emitted when the list does not
164 * start with whitespace.
165 */
166 bool started;
167
168 /*
169 * Whether the previously emitted token was a word separator. A
170 * word separator delimits the last word from the terminator, so
171 * one without source characters is emitted when the list does
172 * not end with whitespace.
173 */
174 bool separated;
175
176 /*
177 * When lexing a list, it takes into account balancing the
178 * terminator if the terminator is one of (), [], {}, or <>.
179 */
180 uint8_t incrementor;
181
182 /* This is the terminator of the list literal. */
183 uint8_t terminator;
184
185 /*
186 * This is the character set that should be used to delimit the
187 * tokens within the list.
188 */
189 uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE];
190 } list;
191
192 struct {
193 /*
194 * This keeps track of the nesting level of the regular expression.
195 */
196 size_t nesting;
197
198 /*
199 * When lexing a regular expression, it takes into account balancing
200 * the terminator if the terminator is one of (), [], {}, or <>.
201 */
202 uint8_t incrementor;
203
204 /* This is the terminator of the regular expression. */
205 uint8_t terminator;
206
207 /*
208 * This is the character set that should be used to delimit the
209 * tokens within the regular expression.
210 */
211 uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE];
212 } regexp;
213
214 struct {
215 /* This keeps track of the nesting level of the string. */
216 size_t nesting;
217
218 /* Whether or not interpolation is allowed in this string. */
219 bool interpolation;
220
221 /*
222 * Whether or not at the end of the string we should allow a :,
223 * which would indicate this was a dynamic symbol instead of a
224 * string.
225 */
226 bool label_allowed;
227
228 /*
229 * When lexing a string, it takes into account balancing the
230 * terminator if the terminator is one of (), [], {}, or <>.
231 */
232 uint8_t incrementor;
233
234 /*
235 * This is the terminator of the string. It is typically either a
236 * single or double quote.
237 */
238 uint8_t terminator;
239
240 /*
241 * This is the character set that should be used to delimit the
242 * tokens within the string.
243 */
244 uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE];
245 } string;
246
247 struct {
248 /*
249 * All of the data necessary to lex a heredoc.
250 */
252
253 /*
254 * This is the pointer to the character where lexing should resume
255 * once the heredoc has been completely processed.
256 */
257 const uint8_t *next_start;
258
259 /*
260 * This is used to track the amount of common whitespace on each
261 * line so that we know how much to dedent each line in the case of
262 * a tilde heredoc.
263 */
264 size_t *common_whitespace;
265
266 /* True if the previous token ended with a line continuation. */
267 bool line_continuation;
268 } heredoc;
269 } as;
270
271 /* The previous lex state so that it knows how to pop. */
272 struct pm_lex_mode *prev;
274
275/*
276 * We pre-allocate a certain number of lex states in order to avoid having to
277 * call malloc too many times while parsing. You really shouldn't need more than
278 * this because you only really nest deeply when doing string interpolation.
279 */
280#define PM_LEX_STACK_SIZE 4
281
282/*
283 * While parsing, we keep track of a stack of contexts. This is helpful for
284 * error recovery so that we can pop back to a previous context when we hit a
285 * token that is understood by a parent context but not by the current context.
286 */
287typedef enum {
288 /* a null context, used for returning a value from a function */
289 PM_CONTEXT_NONE = 0,
290
291 /* a begin statement */
292 PM_CONTEXT_BEGIN,
293
294 /* an ensure statement with an explicit begin */
295 PM_CONTEXT_BEGIN_ENSURE,
296
297 /* a rescue else statement with an explicit begin */
298 PM_CONTEXT_BEGIN_ELSE,
299
300 /* a rescue statement with an explicit begin */
301 PM_CONTEXT_BEGIN_RESCUE,
302
303 /* expressions in block arguments using braces */
304 PM_CONTEXT_BLOCK_BRACES,
305
306 /* expressions in block arguments using do..end */
307 PM_CONTEXT_BLOCK_KEYWORDS,
308
309 /* an ensure statement within a do..end block */
310 PM_CONTEXT_BLOCK_ENSURE,
311
312 /* a rescue else statement within a do..end block */
313 PM_CONTEXT_BLOCK_ELSE,
314
315 /* expressions in block parameters `foo do |...| end ` */
316 PM_CONTEXT_BLOCK_PARAMETERS,
317
318 /* a rescue statement within a do..end block */
319 PM_CONTEXT_BLOCK_RESCUE,
320
321 /* a case when statements */
322 PM_CONTEXT_CASE_WHEN,
323
324 /* a case in statements */
325 PM_CONTEXT_CASE_IN,
326
327 /* a class declaration */
328 PM_CONTEXT_CLASS,
329
330 /* an ensure statement within a class statement */
331 PM_CONTEXT_CLASS_ENSURE,
332
333 /* a rescue else statement within a class statement */
334 PM_CONTEXT_CLASS_ELSE,
335
336 /* a rescue statement within a class statement */
337 PM_CONTEXT_CLASS_RESCUE,
338
339 /* a method definition */
340 PM_CONTEXT_DEF,
341
342 /* an ensure statement within a method definition */
343 PM_CONTEXT_DEF_ENSURE,
344
345 /* a rescue else statement within a method definition */
346 PM_CONTEXT_DEF_ELSE,
347
348 /* a rescue statement within a method definition */
349 PM_CONTEXT_DEF_RESCUE,
350
351 /* a method definition's parameters */
352 PM_CONTEXT_DEF_PARAMS,
353
354 /* a defined? expression */
355 PM_CONTEXT_DEFINED,
356
357 /* a method definition's default parameter */
358 PM_CONTEXT_DEFAULT_PARAMS,
359
360 /* an else clause */
361 PM_CONTEXT_ELSE,
362
363 /* an elsif clause */
364 PM_CONTEXT_ELSIF,
365
366 /* an interpolated expression */
367 PM_CONTEXT_EMBEXPR,
368
369 /* a for loop */
370 PM_CONTEXT_FOR,
371
372 /* a for loop's index */
373 PM_CONTEXT_FOR_INDEX,
374
375 /* an if statement */
376 PM_CONTEXT_IF,
377
378 /* a lambda expression with braces */
379 PM_CONTEXT_LAMBDA_BRACES,
380
381 /* a lambda expression with do..end */
382 PM_CONTEXT_LAMBDA_DO_END,
383
384 /* an ensure statement within a lambda expression */
385 PM_CONTEXT_LAMBDA_ENSURE,
386
387 /* a rescue else statement within a lambda expression */
388 PM_CONTEXT_LAMBDA_ELSE,
389
390 /* a rescue statement within a lambda expression */
391 PM_CONTEXT_LAMBDA_RESCUE,
392
393 /* the predicate clause of a loop statement */
394 PM_CONTEXT_LOOP_PREDICATE,
395
396 /* the top level context */
397 PM_CONTEXT_MAIN,
398
399 /* a module declaration */
400 PM_CONTEXT_MODULE,
401
402 /* an ensure statement within a module statement */
403 PM_CONTEXT_MODULE_ENSURE,
404
405 /* a rescue else statement within a module statement */
406 PM_CONTEXT_MODULE_ELSE,
407
408 /* a rescue statement within a module statement */
409 PM_CONTEXT_MODULE_RESCUE,
410
411 /* a multiple target expression */
412 PM_CONTEXT_MULTI_TARGET,
413
414 /* a parenthesized expression */
415 PM_CONTEXT_PARENS,
416
417 /* an END block */
418 PM_CONTEXT_POSTEXE,
419
420 /* a predicate inside an if/elsif/unless statement */
421 PM_CONTEXT_PREDICATE,
422
423 /* a BEGIN block */
424 PM_CONTEXT_PREEXE,
425
426 /* a modifier rescue clause */
427 PM_CONTEXT_RESCUE_MODIFIER,
428
429 /* a singleton class definition */
430 PM_CONTEXT_SCLASS,
431
432 /* an ensure statement with a singleton class */
433 PM_CONTEXT_SCLASS_ENSURE,
434
435 /* a rescue else statement with a singleton class */
436 PM_CONTEXT_SCLASS_ELSE,
437
438 /* a rescue statement with a singleton class */
439 PM_CONTEXT_SCLASS_RESCUE,
440
441 /* a ternary expression */
442 PM_CONTEXT_TERNARY,
443
444 /* an unless statement */
445 PM_CONTEXT_UNLESS,
446
447 /* an until statement */
448 PM_CONTEXT_UNTIL,
449
450 /* a while statement */
451 PM_CONTEXT_WHILE,
452
453 /* the number of contexts, which is not itself a context */
454 PM_CONTEXT_MAXIMUM,
455} pm_context_t;
456
457/* This is a node in a linked list of contexts. */
458typedef struct pm_context_node {
459 /* The context that this node represents. */
460 pm_context_t context;
461
462 /* A pointer to the previous context in the linked list. */
463 struct pm_context_node *prev;
464
465 /* One bit set per context in this list, including one for this node. */
466 uint64_t mask;
468
469/* The type of shareable constant value that can be set. */
470typedef uint8_t pm_shareable_constant_value_t;
471static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0;
472static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL;
473static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING;
474static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY;
475
476/*
477 * This tracks an individual local variable in a certain lexical context, as
478 * well as the number of times is it read.
479 */
480typedef struct {
481 /* The name of the local variable. */
482 pm_constant_id_t name;
483
484 /* The location of the local variable in the source. */
485 pm_location_t location;
486
487 /* The index of the local variable in the local table. */
488 uint32_t index;
489
490 /* The number of times the local variable is read. */
491 uint32_t reads;
492
493 /* The hash of the local variable. */
494 uint32_t hash;
495} pm_local_t;
496
497/*
498 * This is a set of local variables in a certain lexical context (method, class,
499 * module, etc.). We need to track how many times these variables are read in
500 * order to warn if they only get written.
501 */
502typedef struct pm_locals {
503 /* The number of local variables in the set. */
504 uint32_t size;
505
506 /* The capacity of the local variables set. */
507 uint32_t capacity;
508
509 /*
510 * A bloom filter over constant IDs stored in this set. Used to quickly
511 * reject lookups for names that are definitely not present, avoiding the
512 * cost of a linear scan or hash probe.
513 */
514 uint32_t bloom;
515
516 /* The nullable allocated memory for the local variables in the set. */
517 pm_local_t *locals;
519
520/* The flags about scope parameters that can be set. */
521typedef uint8_t pm_scope_parameters_t;
522static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0;
523static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1;
524static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x2;
525static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x4;
526static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x8;
527static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x10;
528static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20;
529static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40;
530
531/*
532 * This struct represents a node in a linked list of scopes. Some scopes can see
533 * into their parent scopes, while others cannot.
534 */
535typedef struct pm_scope {
536 /* A pointer to the previous scope in the linked list. */
537 struct pm_scope *previous;
538
539 /* The IDs of the locals in the given scope. */
540 pm_locals_t locals;
541
542 /*
543 * This is a list of the implicit parameters contained within the block.
544 * These will be processed after the block is parsed to determine the kind
545 * of parameters node that should be used and to check if any errors need to
546 * be added.
547 */
548 pm_node_list_t implicit_parameters;
549
550 /*
551 * This is a bitfield that indicates the parameters that are being used in
552 * this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants.
553 * There are three different kinds of parameters that can be used in a
554 * scope:
555 *
556 * - Ordinary parameters (e.g., def foo(bar); end)
557 * - Numbered parameters (e.g., def foo; _1; end)
558 * - The it parameter (e.g., def foo; it; end)
559 *
560 * If ordinary parameters are being used, then certain parameters can be
561 * forwarded to another method/structure. Those are indicated by four
562 * additional bits in the params field. For example, some combinations of:
563 *
564 * - def foo(*); end
565 * - def foo(**); end
566 * - def foo(&); end
567 * - def foo(...); end
568 */
569 pm_scope_parameters_t parameters;
570
571 /*
572 * The current state of constant shareability for this scope. This is
573 * changed by magic shareable_constant_value comments.
574 */
575 pm_shareable_constant_value_t shareable_constant;
576
577 /*
578 * A boolean indicating whether or not this scope can see into its parent.
579 * If closed is true, then the scope cannot see into its parent.
580 */
581 bool closed;
582} pm_scope_t;
583
584/*
585 * A struct that represents a stack of boolean values.
586 */
587typedef uint32_t pm_state_stack_t;
588
589/*
590 * This struct represents the overall parser. It contains a reference to the
591 * source file, as well as pointers that indicate where in the source it's
592 * currently parsing. It also contains the most recent and current token that
593 * it's considering.
594 */
596 /* The arena used for all AST-lifetime allocations. Caller-owned. */
597 pm_arena_t *arena;
598
599 /* The arena used for parser metadata (comments, diagnostics, etc.). */
600 pm_arena_t metadata_arena;
601
602 /*
603 * The next node identifier that will be assigned. This is a unique
604 * identifier used to track nodes such that the syntax tree can be dropped
605 * but the node can be found through another parse.
606 */
607 uint32_t node_id;
608
609 /*
610 * A single-entry cache for pm_parser_constant_id_raw. Avoids redundant
611 * constant pool lookups when the same token is resolved multiple times
612 * (e.g., once during lexing for local variable detection, and again
613 * during parsing for node creation).
614 */
615 struct {
616 const uint8_t *start;
617 const uint8_t *end;
619 } constant_cache;
620
621 /* The current state of the lexer. */
622 pm_lex_state_t lex_state;
623
624 /* Tracks the current nesting of (), [], and {}. */
625 int enclosure_nesting;
626
627 /*
628 * Used to temporarily track the nesting of enclosures to determine if a {
629 * is the beginning of a lambda following the parameters of a lambda.
630 */
631 int lambda_enclosure_nesting;
632
633 /*
634 * Used to track the nesting of braces to ensure we get the correct value
635 * when we are interpolating blocks with braces.
636 */
637 int brace_nesting;
638
639 /*
640 * The stack used to determine if a do keyword belongs to the predicate of a
641 * while, until, or for loop.
642 */
643 pm_state_stack_t do_loop_stack;
644
645 /*
646 * The stack used to determine if a do keyword belongs to the beginning of a
647 * block.
648 */
649 pm_state_stack_t accepts_block_stack;
650
651 /* A stack of lex modes. */
652 struct {
653 /* The current mode of the lexer. */
654 pm_lex_mode_t *current;
655
656 /* The stack of lexer modes. */
657 pm_lex_mode_t stack[PM_LEX_STACK_SIZE];
658
659 /* The current index into the lexer mode stack. */
660 size_t index;
661 } lex_modes;
662
663 /* The pointer to the start of the source. */
664 const uint8_t *start;
665
666 /* The pointer to the end of the source. */
667 const uint8_t *end;
668
669 /* The previous token we were considering. */
670 pm_token_t previous;
671
672 /* The current token we're considering. */
673 pm_token_t current;
674
675 /*
676 * This is a special field set on the parser when we need the parser to jump
677 * to a specific location when lexing the next token, as opposed to just
678 * using the end of the previous token. Normally this is NULL.
679 */
680 const uint8_t *next_start;
681
682 /*
683 * This field indicates the end of a heredoc whose identifier was found on
684 * the current line. If another heredoc is found on the same line, then this
685 * will be moved forward to the end of that heredoc. If no heredocs are
686 * found on a line then this is NULL.
687 */
688 const uint8_t *heredoc_end;
689
690 /* The list of comments that have been found while parsing. */
691 pm_list_t comment_list;
692
693 /*
694 * The attachments of comments to the nodes that own them, populated after
695 * parsing when the attach_comments option is set.
696 */
697 pm_comment_attachments_t comment_attachments;
698
699 /* The list of magic comments that have been found while parsing. */
700 pm_list_t magic_comment_list;
701
702 /*
703 * An optional location that represents the location of the __END__ marker
704 * and the rest of the content of the file. This content is loaded into the
705 * DATA constant when the file being parsed is the main file being executed.
706 */
707 pm_location_t data_loc;
708
709 /* The list of warnings that have been found while parsing. */
710 pm_list_t warning_list;
711
712 /* The list of errors that have been found while parsing. */
713 pm_list_t error_list;
714
715 /* The current local scope. */
716 pm_scope_t *current_scope;
717
718 /* The current parsing context. */
719 pm_context_node_t *current_context;
720
721 /*
722 * The encoding functions for the current file is attached to the parser as
723 * it's parsing so that it can change with a magic comment.
724 */
725 const pm_encoding_t *encoding;
726
727 /*
728 * When the encoding that is being used to parse the source is changed by
729 * prism, we provide the ability here to call out to a user-defined
730 * function.
731 */
732 pm_encoding_changed_callback_t encoding_changed_callback;
733
734 /*
735 * This pointer indicates where a comment must start if it is to be
736 * considered an encoding comment.
737 */
738 const uint8_t *encoding_comment_start;
739
740 /*
741 * When you are lexing through a file, the lexer needs all of the information
742 * that the parser additionally provides (for example, the local table). So if
743 * you want to properly lex Ruby, you need to actually lex it in the context of
744 * the parser. In order to provide this functionality, we optionally allow a
745 * struct to be attached to the parser that calls back out to a user-provided
746 * callback when each token is lexed.
747 */
748 struct {
749 /*
750 * This is the callback that is called when a token is lexed. It is
751 * passed the opaque data pointer, the parser, and the token that was
752 * lexed.
753 */
754 pm_lex_callback_t callback;
755
756 /*
757 * This opaque pointer is used to provide whatever information the user
758 * deemed necessary to the callback. In our case we use it to pass the
759 * array that the tokens get appended into.
760 */
761 void *data;
762 } lex_callback;
763
764 /*
765 * This is the path of the file being parsed. We use the filepath when
766 * constructing SourceFileNodes.
767 */
768 pm_string_t filepath;
769
770 /*
771 * This constant pool keeps all of the constants defined throughout the file
772 * so that we can reference them later.
773 */
774 pm_constant_pool_t constant_pool;
775
776 /* This is the list of line offsets in the source file. */
777 pm_line_offset_list_t line_offsets;
778
779 /*
780 * State communicated from the lexer to the parser for integer tokens.
781 */
782 struct {
783 /*
784 * A flag indicating the base of the integer (binary, octal, decimal,
785 * hexadecimal). Set during lexing and read during node creation.
786 */
787 pm_node_flags_t base;
788
789 /*
790 * When lexing a decimal integer that fits in a uint32_t, we compute
791 * the value during lexing to avoid re-scanning the digits during
792 * parsing. If lexed is true, this holds the result and
793 * pm_integer_parse can be skipped.
794 */
795 uint32_t value;
796
797 /* Whether value holds a valid pre-computed integer. */
798 bool lexed;
799 } integer;
800
801 /*
802 * This string is used to pass information from the lexer to the parser. It
803 * is particularly necessary because of escape sequences.
804 */
805 pm_string_t current_string;
806
807 /*
808 * The line number at the start of the parse. This will be used to offset
809 * the line numbers of all of the locations.
810 */
811 int32_t start_line;
812
813 /*
814 * When a string-like expression is being lexed, any byte or escape sequence
815 * that resolves to a value whose top bit is set (i.e., >= 0x80) will
816 * explicitly set the encoding to the same encoding as the source.
817 * Alternatively, if a unicode escape sequence is used (e.g., \\u{80}) that
818 * resolves to a value whose top bit is set, then the encoding will be
819 * explicitly set to UTF-8.
820 *
821 * The _next_ time this happens, if the encoding that is about to become the
822 * explicitly set encoding does not match the previously set explicit
823 * encoding, a mixed encoding error will be emitted.
824 *
825 * When the expression is finished being lexed, the explicit encoding
826 * controls the encoding of the expression. For the most part this means
827 * that the expression will either be encoded in the source encoding or
828 * UTF-8. This holds for all encodings except US-ASCII. If the source is
829 * US-ASCII and an explicit encoding was set that was _not_ UTF-8, then the
830 * expression will be encoded as ASCII-8BIT.
831 *
832 * Note that if the expression is a list, different elements within the same
833 * list can have different encodings, so this will get reset between each
834 * element. Furthermore all of this only applies to lists that support
835 * interpolation, because otherwise escapes that could change the encoding
836 * are ignored.
837 *
838 * At first glance, it may make more sense for this to live on the lexer
839 * mode, but we need it here to communicate back to the parser for character
840 * literals that do not push a new lexer mode.
841 */
842 const pm_encoding_t *explicit_encoding;
843
844 /*
845 * When parsing block exits (e.g., break, next, redo), we need to validate
846 * that they are in correct contexts. For the most part we can do this by
847 * looking at our parent contexts. However, modifier while and until
848 * expressions can change that context to make block exits valid. In these
849 * cases, we need to keep track of the block exits and then validate them
850 * after the expression has been parsed.
851 *
852 * We use a pointer here because we don't want to keep a whole list attached
853 * since this will only be used in the context of begin/end expressions.
854 */
855 pm_node_list_t *current_block_exits;
856
857 /* The version of prism that we should use to parse. */
858 pm_options_version_t version;
859
860 /* The command line flags given from the options. */
861 uint8_t command_line;
862
863 /*
864 * Whether or not we have found a frozen_string_literal magic comment with
865 * a true or false value.
866 * May be:
867 * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED
868 * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED
869 * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET
870 */
871 int8_t frozen_string_literal;
872
873 /*
874 * Whether or not we are parsing an eval string. This impacts whether or not
875 * we should evaluate if block exits/yields are valid.
876 */
877 bool parsing_eval;
878
879 /*
880 * Whether or not we are parsing a "partial" script, which is a script that
881 * will be evaluated in the context of another script, so we should not
882 * check jumps (next/break/etc.) for validity.
883 */
884 bool partial_script;
885
886 /*
887 * Whether or not comments should be attached to their owning nodes once
888 * parsing has finished.
889 */
890 bool attach_comments;
891
892 /* Whether or not we're at the beginning of a command. */
893 bool command_start;
894
895 /*
896 * Whether or not we're currently parsing the body of an endless method
897 * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be
898 * consumed by commands (it should bubble up to the outer context).
899 */
900 bool in_endless_def_body;
901
902 /* Whether or not we're currently recovering from a syntax error. */
903 bool recovering;
904
905 /*
906 * Whether or not the source being parsed could become valid if more input
907 * were appended. This is set to false when the parser encounters a token
908 * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to
909 * merely incomplete.
910 */
911 bool continuable;
912
913 /*
914 * This is very specialized behavior for when you want to parse in a context
915 * that does not respect encoding comments. Its main use case is translating
916 * into the whitequark/parser AST which re-encodes source files in UTF-8
917 * before they are parsed and ignores encoding comments.
918 */
919 bool encoding_locked;
920
921 /*
922 * Whether or not the encoding has been changed by a magic comment. We use
923 * this to provide a fast path for the lexer instead of going through the
924 * function pointer.
925 */
926 bool encoding_changed;
927
928 /*
929 * This flag indicates that we are currently parsing a pattern matching
930 * expression and impacts that calculation of newlines.
931 */
932 bool pattern_matching_newlines;
933
934 /* This flag indicates that we are currently parsing a keyword argument. */
935 bool in_keyword_arg;
936
937 /*
938 * Whether or not the parser has seen a token that has semantic meaning
939 * (i.e., a token that is not a comment or whitespace).
940 */
941 bool semantic_token_seen;
942
943 /*
944 * By default, Ruby always warns about mismatched indentation. This can be
945 * toggled with a magic comment.
946 */
947 bool warn_mismatched_indentation;
948
949#if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSE2) || defined(PRISM_HAS_SWAR)
950 /*
951 * Cached lookup tables for pm_strpbrk's SIMD fast path. Avoids rebuilding
952 * the nibble-based tables on every call when the charset hasn't changed
953 * (which is the common case during string/regex/list lexing).
954 */
955 struct {
956 /* The cached charset (null-terminated, max 11 chars + NUL). */
957 uint8_t charset[12];
958
959 /* Nibble-based low lookup table for SIMD matching. */
960 uint8_t low_lut[16];
961
962 /* Nibble-based high lookup table for SIMD matching. */
963 uint8_t high_lut[16];
964
965 /* Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */
966 uint64_t table[4];
967 } strpbrk_cache;
968#endif
969};
970
971/*
972 * Initialize a parser with the given start and end pointers.
973 */
974void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options);
975
976/*
977 * Free the memory held by the given parser.
978 *
979 * This does not free the `pm_options_t` object that was used to initialize the
980 * parser.
981 */
982void pm_parser_cleanup(pm_parser_t *parser);
983
984#endif
uint32_t pm_constant_id_t
A constant id is a unique identifier for a constant in the constant pool.
A list of byte offsets of newlines in a string.
The parser used to parse Ruby source.
void(* pm_lex_callback_t)(pm_parser_t *parser, pm_token_t *token, void *data)
This is the callback that is called when a token is lexed.
Definition parser.h:55
void(* pm_encoding_changed_callback_t)(pm_parser_t *parser)
When the encoding that is being used to parse the source is changed by prism, we provide the ability ...
Definition parser.h:49
C99 shim for <stdbool.h>
A list of offsets of the start of lines in a string.
This struct represents a slice in the source code, defined by an offset and a length.
Definition ast.h:575
A list of nodes in the source, most often used for lists of children.
Definition ast.h:588
A generic string type that can have various ownership semantics.
Definition stringy.h:18
This struct represents a token in the Ruby source.
Definition ast.h:547