@@ -14,180 +14,6 @@ pm_version(void) {
14
14
*/
15
15
#define PM_TAB_WHITESPACE_SIZE 8
16
16
17
- #ifndef PM_DEBUG_LOGGING
18
- /**
19
- * Debugging logging will provide you with additional debugging functions as
20
- * well as automatically replace some functions with their debugging
21
- * counterparts.
22
- */
23
- #define PM_DEBUG_LOGGING 0
24
- #endif
25
-
26
- #if PM_DEBUG_LOGGING
27
-
28
- /******************************************************************************/
29
- /* Debugging */
30
- /******************************************************************************/
31
-
32
- PRISM_ATTRIBUTE_UNUSED static const char *
33
- debug_context(pm_context_t context) {
34
- switch (context) {
35
- case PM_CONTEXT_BEGIN: return "BEGIN";
36
- case PM_CONTEXT_BEGIN_ENSURE: return "BEGIN_ENSURE";
37
- case PM_CONTEXT_BEGIN_ELSE: return "BEGIN_ELSE";
38
- case PM_CONTEXT_BEGIN_RESCUE: return "BEGIN_RESCUE";
39
- case PM_CONTEXT_BLOCK_BRACES: return "BLOCK_BRACES";
40
- case PM_CONTEXT_BLOCK_KEYWORDS: return "BLOCK_KEYWORDS";
41
- case PM_CONTEXT_BLOCK_ENSURE: return "BLOCK_ENSURE";
42
- case PM_CONTEXT_BLOCK_ELSE: return "BLOCK_ELSE";
43
- case PM_CONTEXT_BLOCK_RESCUE: return "BLOCK_RESCUE";
44
- case PM_CONTEXT_CASE_IN: return "CASE_IN";
45
- case PM_CONTEXT_CASE_WHEN: return "CASE_WHEN";
46
- case PM_CONTEXT_CLASS: return "CLASS";
47
- case PM_CONTEXT_CLASS_ELSE: return "CLASS_ELSE";
48
- case PM_CONTEXT_CLASS_ENSURE: return "CLASS_ENSURE";
49
- case PM_CONTEXT_CLASS_RESCUE: return "CLASS_RESCUE";
50
- case PM_CONTEXT_DEF: return "DEF";
51
- case PM_CONTEXT_DEF_PARAMS: return "DEF_PARAMS";
52
- case PM_CONTEXT_DEF_ENSURE: return "DEF_ENSURE";
53
- case PM_CONTEXT_DEF_ELSE: return "DEF_ELSE";
54
- case PM_CONTEXT_DEF_RESCUE: return "DEF_RESCUE";
55
- case PM_CONTEXT_DEFAULT_PARAMS: return "DEFAULT_PARAMS";
56
- case PM_CONTEXT_DEFINED: return "DEFINED";
57
- case PM_CONTEXT_ELSE: return "ELSE";
58
- case PM_CONTEXT_ELSIF: return "ELSIF";
59
- case PM_CONTEXT_EMBEXPR: return "EMBEXPR";
60
- case PM_CONTEXT_FOR_INDEX: return "FOR_INDEX";
61
- case PM_CONTEXT_FOR: return "FOR";
62
- case PM_CONTEXT_IF: return "IF";
63
- case PM_CONTEXT_LAMBDA_BRACES: return "LAMBDA_BRACES";
64
- case PM_CONTEXT_LAMBDA_DO_END: return "LAMBDA_DO_END";
65
- case PM_CONTEXT_LAMBDA_ENSURE: return "LAMBDA_ENSURE";
66
- case PM_CONTEXT_LAMBDA_ELSE: return "LAMBDA_ELSE";
67
- case PM_CONTEXT_LAMBDA_RESCUE: return "LAMBDA_RESCUE";
68
- case PM_CONTEXT_MAIN: return "MAIN";
69
- case PM_CONTEXT_MODULE: return "MODULE";
70
- case PM_CONTEXT_MODULE_ELSE: return "MODULE_ELSE";
71
- case PM_CONTEXT_MODULE_ENSURE: return "MODULE_ENSURE";
72
- case PM_CONTEXT_MODULE_RESCUE: return "MODULE_RESCUE";
73
- case PM_CONTEXT_NONE: return "NONE";
74
- case PM_CONTEXT_PARENS: return "PARENS";
75
- case PM_CONTEXT_POSTEXE: return "POSTEXE";
76
- case PM_CONTEXT_PREDICATE: return "PREDICATE";
77
- case PM_CONTEXT_PREEXE: return "PREEXE";
78
- case PM_CONTEXT_RESCUE_MODIFIER: return "RESCUE_MODIFIER";
79
- case PM_CONTEXT_SCLASS: return "SCLASS";
80
- case PM_CONTEXT_SCLASS_ENSURE: return "SCLASS_ENSURE";
81
- case PM_CONTEXT_SCLASS_ELSE: return "SCLASS_ELSE";
82
- case PM_CONTEXT_SCLASS_RESCUE: return "SCLASS_RESCUE";
83
- case PM_CONTEXT_TERNARY: return "TERNARY";
84
- case PM_CONTEXT_UNLESS: return "UNLESS";
85
- case PM_CONTEXT_UNTIL: return "UNTIL";
86
- case PM_CONTEXT_WHILE: return "WHILE";
87
- }
88
- return NULL;
89
- }
90
-
91
- PRISM_ATTRIBUTE_UNUSED static void
92
- debug_contexts(pm_parser_t *parser) {
93
- pm_context_node_t *context_node = parser->current_context;
94
- fprintf(stderr, "CONTEXTS: ");
95
-
96
- if (context_node != NULL) {
97
- while (context_node != NULL) {
98
- fprintf(stderr, "%s", debug_context(context_node->context));
99
- context_node = context_node->prev;
100
- if (context_node != NULL) {
101
- fprintf(stderr, " <- ");
102
- }
103
- }
104
- } else {
105
- fprintf(stderr, "NONE");
106
- }
107
-
108
- fprintf(stderr, "\n");
109
- }
110
-
111
- PRISM_ATTRIBUTE_UNUSED static void
112
- debug_node(const pm_parser_t *parser, const pm_node_t *node) {
113
- pm_buffer_t output_buffer = { 0 };
114
- pm_prettyprint(&output_buffer, parser, node);
115
-
116
- fprintf(stderr, "%.*s", (int) output_buffer.length, output_buffer.value);
117
- pm_buffer_free(&output_buffer);
118
- }
119
-
120
- PRISM_ATTRIBUTE_UNUSED static void
121
- debug_lex_mode(pm_parser_t *parser) {
122
- pm_lex_mode_t *lex_mode = parser->lex_modes.current;
123
- bool first = true;
124
-
125
- while (lex_mode != NULL) {
126
- if (first) {
127
- first = false;
128
- } else {
129
- fprintf(stderr, " <- ");
130
- }
131
-
132
- switch (lex_mode->mode) {
133
- case PM_LEX_DEFAULT: fprintf(stderr, "DEFAULT"); break;
134
- case PM_LEX_EMBEXPR: fprintf(stderr, "EMBEXPR"); break;
135
- case PM_LEX_EMBVAR: fprintf(stderr, "EMBVAR"); break;
136
- case PM_LEX_HEREDOC: fprintf(stderr, "HEREDOC"); break;
137
- case PM_LEX_LIST: fprintf(stderr, "LIST (terminator=%c, interpolation=%d)", lex_mode->as.list.terminator, lex_mode->as.list.interpolation); break;
138
- case PM_LEX_REGEXP: fprintf(stderr, "REGEXP (terminator=%c)", lex_mode->as.regexp.terminator); break;
139
- case PM_LEX_STRING: fprintf(stderr, "STRING (terminator=%c, interpolation=%d)", lex_mode->as.string.terminator, lex_mode->as.string.interpolation); break;
140
- }
141
-
142
- lex_mode = lex_mode->prev;
143
- }
144
-
145
- fprintf(stderr, "\n");
146
- }
147
-
148
- PRISM_ATTRIBUTE_UNUSED static void
149
- debug_state(pm_parser_t *parser) {
150
- fprintf(stderr, "STATE: ");
151
- bool first = true;
152
-
153
- if (parser->lex_state == PM_LEX_STATE_NONE) {
154
- fprintf(stderr, "NONE\n");
155
- return;
156
- }
157
-
158
- #define CHECK_STATE(state) \
159
- if (parser->lex_state & state) { \
160
- if (!first) fprintf(stderr, "|"); \
161
- fprintf(stderr, "%s", #state); \
162
- first = false; \
163
- }
164
-
165
- CHECK_STATE(PM_LEX_STATE_BEG)
166
- CHECK_STATE(PM_LEX_STATE_END)
167
- CHECK_STATE(PM_LEX_STATE_ENDARG)
168
- CHECK_STATE(PM_LEX_STATE_ENDFN)
169
- CHECK_STATE(PM_LEX_STATE_ARG)
170
- CHECK_STATE(PM_LEX_STATE_CMDARG)
171
- CHECK_STATE(PM_LEX_STATE_MID)
172
- CHECK_STATE(PM_LEX_STATE_FNAME)
173
- CHECK_STATE(PM_LEX_STATE_DOT)
174
- CHECK_STATE(PM_LEX_STATE_CLASS)
175
- CHECK_STATE(PM_LEX_STATE_LABEL)
176
- CHECK_STATE(PM_LEX_STATE_LABELED)
177
- CHECK_STATE(PM_LEX_STATE_FITEM)
178
-
179
- #undef CHECK_STATE
180
-
181
- fprintf(stderr, "\n");
182
- }
183
-
184
- PRISM_ATTRIBUTE_UNUSED static void
185
- debug_token(pm_token_t * token) {
186
- fprintf(stderr, "%s: \"%.*s\"\n", pm_token_type_human(token->type), (int) (token->end - token->start), token->start);
187
- }
188
-
189
- #endif
190
-
191
17
// Macros for min/max.
192
18
#define MIN(a,b) (((a)<(b))?(a):(b))
193
19
#define MAX(a,b) (((a)>(b))?(a):(b))
@@ -491,8 +317,52 @@ lex_state_set(pm_parser_t *parser, pm_lex_state_t state) {
491
317
parser->lex_state = state;
492
318
}
493
319
320
+ #ifndef PM_DEBUG_LOGGING
321
+ /**
322
+ * Debugging logging will print additional information to stdout whenever the
323
+ * lexer state changes.
324
+ */
325
+ #define PM_DEBUG_LOGGING 0
326
+ #endif
327
+
494
328
#if PM_DEBUG_LOGGING
495
- static inline void
329
+ PRISM_ATTRIBUTE_UNUSED static void
330
+ debug_state(pm_parser_t *parser) {
331
+ fprintf(stderr, "STATE: ");
332
+ bool first = true;
333
+
334
+ if (parser->lex_state == PM_LEX_STATE_NONE) {
335
+ fprintf(stderr, "NONE\n");
336
+ return;
337
+ }
338
+
339
+ #define CHECK_STATE(state) \
340
+ if (parser->lex_state & state) { \
341
+ if (!first) fprintf(stderr, "|"); \
342
+ fprintf(stderr, "%s", #state); \
343
+ first = false; \
344
+ }
345
+
346
+ CHECK_STATE(PM_LEX_STATE_BEG)
347
+ CHECK_STATE(PM_LEX_STATE_END)
348
+ CHECK_STATE(PM_LEX_STATE_ENDARG)
349
+ CHECK_STATE(PM_LEX_STATE_ENDFN)
350
+ CHECK_STATE(PM_LEX_STATE_ARG)
351
+ CHECK_STATE(PM_LEX_STATE_CMDARG)
352
+ CHECK_STATE(PM_LEX_STATE_MID)
353
+ CHECK_STATE(PM_LEX_STATE_FNAME)
354
+ CHECK_STATE(PM_LEX_STATE_DOT)
355
+ CHECK_STATE(PM_LEX_STATE_CLASS)
356
+ CHECK_STATE(PM_LEX_STATE_LABEL)
357
+ CHECK_STATE(PM_LEX_STATE_LABELED)
358
+ CHECK_STATE(PM_LEX_STATE_FITEM)
359
+
360
+ #undef CHECK_STATE
361
+
362
+ fprintf(stderr, "\n");
363
+ }
364
+
365
+ static void
496
366
debug_lex_state_set(pm_parser_t *parser, pm_lex_state_t state, char const * caller_name, int line_number) {
497
367
fprintf(stderr, "Caller: %s:%d\nPrevious: ", caller_name, line_number);
498
368
debug_state(parser);
@@ -8492,6 +8362,8 @@ context_terminator(pm_context_t context, pm_token_t *token) {
8492
8362
case PM_CONTEXT_MODULE_ENSURE:
8493
8363
case PM_CONTEXT_SCLASS_ENSURE:
8494
8364
return token->type == PM_TOKEN_KEYWORD_END;
8365
+ case PM_CONTEXT_LOOP_PREDICATE:
8366
+ return token->type == PM_TOKEN_KEYWORD_DO || token->type == PM_TOKEN_KEYWORD_THEN;
8495
8367
case PM_CONTEXT_FOR_INDEX:
8496
8368
return token->type == PM_TOKEN_KEYWORD_IN;
8497
8369
case PM_CONTEXT_CASE_WHEN:
@@ -8664,6 +8536,7 @@ context_human(pm_context_t context) {
8664
8536
case PM_CONTEXT_IF: return "if statement";
8665
8537
case PM_CONTEXT_LAMBDA_BRACES: return "'{'..'}' lambda block";
8666
8538
case PM_CONTEXT_LAMBDA_DO_END: return "'do'..'end' lambda block";
8539
+ case PM_CONTEXT_LOOP_PREDICATE: return "loop predicate";
8667
8540
case PM_CONTEXT_MAIN: return "top level context";
8668
8541
case PM_CONTEXT_MODULE: return "module definition";
8669
8542
case PM_CONTEXT_PARENS: return "parentheses";
@@ -15170,6 +15043,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) {
15170
15043
case PM_CONTEXT_LAMBDA_ELSE:
15171
15044
case PM_CONTEXT_LAMBDA_ENSURE:
15172
15045
case PM_CONTEXT_LAMBDA_RESCUE:
15046
+ case PM_CONTEXT_LOOP_PREDICATE:
15173
15047
case PM_CONTEXT_POSTEXE:
15174
15048
case PM_CONTEXT_UNTIL:
15175
15049
case PM_CONTEXT_WHILE:
@@ -17318,6 +17192,7 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
17318
17192
case PM_CONTEXT_IF:
17319
17193
case PM_CONTEXT_LAMBDA_BRACES:
17320
17194
case PM_CONTEXT_LAMBDA_DO_END:
17195
+ case PM_CONTEXT_LOOP_PREDICATE:
17321
17196
case PM_CONTEXT_PARENS:
17322
17197
case PM_CONTEXT_POSTEXE:
17323
17198
case PM_CONTEXT_PREDICATE:
@@ -17396,6 +17271,7 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) {
17396
17271
case PM_CONTEXT_LAMBDA_ELSE:
17397
17272
case PM_CONTEXT_LAMBDA_ENSURE:
17398
17273
case PM_CONTEXT_LAMBDA_RESCUE:
17274
+ case PM_CONTEXT_LOOP_PREDICATE:
17399
17275
case PM_CONTEXT_PARENS:
17400
17276
case PM_CONTEXT_POSTEXE:
17401
17277
case PM_CONTEXT_PREDICATE:
@@ -19146,12 +19022,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
19146
19022
parser_lex(parser);
19147
19023
return (pm_node_t *) pm_true_node_create(parser, &parser->previous);
19148
19024
case PM_TOKEN_KEYWORD_UNTIL: {
19025
+ context_push(parser, PM_CONTEXT_LOOP_PREDICATE);
19149
19026
pm_do_loop_stack_push(parser, true);
19027
+
19150
19028
parser_lex(parser);
19151
19029
pm_token_t keyword = parser->previous;
19152
-
19153
19030
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
19031
+
19154
19032
pm_do_loop_stack_pop(parser);
19033
+ context_pop(parser);
19155
19034
19156
19035
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
19157
19036
pm_statements_node_t *statements = NULL;
@@ -19167,12 +19046,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
19167
19046
return (pm_node_t *) pm_until_node_create(parser, &keyword, &parser->previous, predicate, statements, 0);
19168
19047
}
19169
19048
case PM_TOKEN_KEYWORD_WHILE: {
19049
+ context_push(parser, PM_CONTEXT_LOOP_PREDICATE);
19170
19050
pm_do_loop_stack_push(parser, true);
19051
+
19171
19052
parser_lex(parser);
19172
19053
pm_token_t keyword = parser->previous;
19173
-
19174
19054
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
19055
+
19175
19056
pm_do_loop_stack_pop(parser);
19057
+ context_pop(parser);
19176
19058
19177
19059
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
19178
19060
pm_statements_node_t *statements = NULL;
0 commit comments