Skip to content

Commit 45dd046

Browse files
committed
Provide a flag for the integer base
1 parent 188d10c commit 45dd046

File tree

337 files changed

+1140
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

337 files changed

+1140
-22
lines changed

config.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,16 @@ flags:
333333
comment: "&. operator"
334334
- name: VARIABLE_CALL
335335
comment: "a call that could have been a local variable"
336+
- name: IntegerBaseFlags
337+
values:
338+
- name: BINARY
339+
comment: "0b prefix"
340+
- name: OCTAL
341+
comment: "0o or 0 prefix"
342+
- name: DECIMAL
343+
comment: "0d or no prefix"
344+
- name: HEXADECIMAL
345+
comment: "0x prefix"
336346
- name: LoopFlags
337347
values:
338348
- name: BEGIN_MODIFIER
@@ -1483,6 +1493,10 @@ nodes:
14831493
@foo = 1
14841494
^^^^^^^^
14851495
- name: IntegerNode
1496+
fields:
1497+
- name: flags
1498+
type: flags
1499+
kind: IntegerBaseFlags
14861500
comment: |
14871501
Represents an integer number literal.
14881502

include/yarp/parser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ struct yp_parser {
384384

385385
// This is the list of newline offsets in the source file.
386386
yp_newline_list_t newline_list;
387+
388+
// We want to add a flag to integer nodes that indicates their base. We only
389+
// want to parse these once, but we don't have space on the token itself to
390+
// communicate this information. So we store it here and pass it through
391+
// when we find tokens that we need it for.
392+
yp_node_flags_t integer_base;
387393
};
388394

389395
#endif // YARP_PARSER_H

src/yarp.c

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2673,16 +2673,22 @@ yp_else_node_end_keyword_loc_set(yp_else_node_t *node, const yp_token_t *keyword
26732673

26742674
// Allocate and initialize a new IntegerNode node.
26752675
static yp_integer_node_t *
2676-
yp_integer_node_create(yp_parser_t *parser, const yp_token_t *token) {
2676+
yp_integer_node_create(yp_parser_t *parser, yp_node_flags_t base, const yp_token_t *token) {
26772677
assert(token->type == YP_TOKEN_INTEGER);
26782678
yp_integer_node_t *node = YP_ALLOC_NODE(parser, yp_integer_node_t);
2679-
*node = (yp_integer_node_t) {{ .type = YP_INTEGER_NODE, .location = YP_LOCATION_TOKEN_VALUE(token) }};
2679+
2680+
*node = (yp_integer_node_t) {{
2681+
.type = YP_INTEGER_NODE,
2682+
.flags = base,
2683+
.location = YP_LOCATION_TOKEN_VALUE(token)
2684+
}};
2685+
26802686
return node;
26812687
}
26822688

26832689
// Allocate and initialize a new IntegerNode node from an INTEGER_IMAGINARY token.
26842690
static yp_imaginary_node_t *
2685-
yp_integer_node_imaginary_create(yp_parser_t *parser, const yp_token_t *token) {
2691+
yp_integer_node_imaginary_create(yp_parser_t *parser, yp_node_flags_t base, const yp_token_t *token) {
26862692
assert(token->type == YP_TOKEN_INTEGER_IMAGINARY);
26872693

26882694
yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t);
@@ -2691,7 +2697,7 @@ yp_integer_node_imaginary_create(yp_parser_t *parser, const yp_token_t *token) {
26912697
.type = YP_IMAGINARY_NODE,
26922698
.location = YP_LOCATION_TOKEN_VALUE(token)
26932699
},
2694-
.numeric = (yp_node_t *) yp_integer_node_create(parser, &((yp_token_t) {
2700+
.numeric = (yp_node_t *) yp_integer_node_create(parser, base, &((yp_token_t) {
26952701
.type = YP_TOKEN_INTEGER,
26962702
.start = token->start,
26972703
.end = token->end - 1
@@ -2703,7 +2709,7 @@ yp_integer_node_imaginary_create(yp_parser_t *parser, const yp_token_t *token) {
27032709

27042710
// Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL token.
27052711
static yp_rational_node_t *
2706-
yp_integer_node_rational_create(yp_parser_t *parser, const yp_token_t *token) {
2712+
yp_integer_node_rational_create(yp_parser_t *parser, yp_node_flags_t base, const yp_token_t *token) {
27072713
assert(token->type == YP_TOKEN_INTEGER_RATIONAL);
27082714

27092715
yp_rational_node_t *node = YP_ALLOC_NODE(parser, yp_rational_node_t);
@@ -2712,7 +2718,7 @@ yp_integer_node_rational_create(yp_parser_t *parser, const yp_token_t *token) {
27122718
.type = YP_RATIONAL_NODE,
27132719
.location = YP_LOCATION_TOKEN_VALUE(token)
27142720
},
2715-
.numeric = (yp_node_t *) yp_integer_node_create(parser, &((yp_token_t) {
2721+
.numeric = (yp_node_t *) yp_integer_node_create(parser, base, &((yp_token_t) {
27162722
.type = YP_TOKEN_INTEGER,
27172723
.start = token->start,
27182724
.end = token->end - 1
@@ -2724,7 +2730,7 @@ yp_integer_node_rational_create(yp_parser_t *parser, const yp_token_t *token) {
27242730

27252731
// Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL_IMAGINARY token.
27262732
static yp_imaginary_node_t *
2727-
yp_integer_node_rational_imaginary_create(yp_parser_t *parser, const yp_token_t *token) {
2733+
yp_integer_node_rational_imaginary_create(yp_parser_t *parser, yp_node_flags_t base, const yp_token_t *token) {
27282734
assert(token->type == YP_TOKEN_INTEGER_RATIONAL_IMAGINARY);
27292735

27302736
yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t);
@@ -2733,7 +2739,7 @@ yp_integer_node_rational_imaginary_create(yp_parser_t *parser, const yp_token_t
27332739
.type = YP_IMAGINARY_NODE,
27342740
.location = YP_LOCATION_TOKEN_VALUE(token)
27352741
},
2736-
.numeric = (yp_node_t *) yp_integer_node_rational_create(parser, &((yp_token_t) {
2742+
.numeric = (yp_node_t *) yp_integer_node_rational_create(parser, base, &((yp_token_t) {
27372743
.type = YP_TOKEN_INTEGER_RATIONAL,
27382744
.start = token->start,
27392745
.end = token->end - 1
@@ -5193,6 +5199,7 @@ lex_numeric_prefix(yp_parser_t *parser) {
51935199
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, YP_ERR_INVALID_NUMBER_BINARY);
51945200
}
51955201

5202+
parser->integer_base = YP_INTEGER_BASE_FLAGS_BINARY;
51965203
break;
51975204

51985205
// 0o1111 is an octal number
@@ -5205,6 +5212,7 @@ lex_numeric_prefix(yp_parser_t *parser) {
52055212
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, YP_ERR_INVALID_NUMBER_OCTAL);
52065213
}
52075214

5215+
parser->integer_base = YP_INTEGER_BASE_FLAGS_OCTAL;
52085216
break;
52095217

52105218
// 01111 is an octal number
@@ -5218,6 +5226,7 @@ lex_numeric_prefix(yp_parser_t *parser) {
52185226
case '6':
52195227
case '7':
52205228
parser->current.end += yp_strspn_octal_number(parser->current.end, parser->end - parser->current.end);
5229+
parser->integer_base = YP_INTEGER_BASE_FLAGS_OCTAL;
52215230
break;
52225231

52235232
// 0x1111 is a hexadecimal number
@@ -5230,6 +5239,7 @@ lex_numeric_prefix(yp_parser_t *parser) {
52305239
yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, YP_ERR_INVALID_NUMBER_HEXADECIMAL);
52315240
}
52325241

5242+
parser->integer_base = YP_INTEGER_BASE_FLAGS_HEXADECIMAL;
52335243
break;
52345244

52355245
// 0.xxx is a float
@@ -5266,6 +5276,7 @@ lex_numeric_prefix(yp_parser_t *parser) {
52665276
static yp_token_type_t
52675277
lex_numeric(yp_parser_t *parser) {
52685278
yp_token_type_t type = YP_TOKEN_INTEGER;
5279+
parser->integer_base = YP_INTEGER_BASE_FLAGS_DECIMAL;
52695280

52705281
if (parser->current.end < parser->end) {
52715282
type = lex_numeric_prefix(parser);
@@ -11272,18 +11283,26 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
1127211283

1127311284
return node;
1127411285
}
11275-
case YP_TOKEN_INTEGER:
11286+
case YP_TOKEN_INTEGER: {
11287+
yp_node_flags_t base = parser->integer_base;
1127611288
parser_lex(parser);
11277-
return (yp_node_t *) yp_integer_node_create(parser, &parser->previous);
11278-
case YP_TOKEN_INTEGER_IMAGINARY:
11289+
return (yp_node_t *) yp_integer_node_create(parser, base, &parser->previous);
11290+
}
11291+
case YP_TOKEN_INTEGER_IMAGINARY: {
11292+
yp_node_flags_t base = parser->integer_base;
1127911293
parser_lex(parser);
11280-
return (yp_node_t *) yp_integer_node_imaginary_create(parser, &parser->previous);
11281-
case YP_TOKEN_INTEGER_RATIONAL:
11294+
return (yp_node_t *) yp_integer_node_imaginary_create(parser, base, &parser->previous);
11295+
}
11296+
case YP_TOKEN_INTEGER_RATIONAL: {
11297+
yp_node_flags_t base = parser->integer_base;
1128211298
parser_lex(parser);
11283-
return (yp_node_t *) yp_integer_node_rational_create(parser, &parser->previous);
11284-
case YP_TOKEN_INTEGER_RATIONAL_IMAGINARY:
11299+
return (yp_node_t *) yp_integer_node_rational_create(parser, base, &parser->previous);
11300+
}
11301+
case YP_TOKEN_INTEGER_RATIONAL_IMAGINARY: {
11302+
yp_node_flags_t base = parser->integer_base;
1128511303
parser_lex(parser);
11286-
return (yp_node_t *) yp_integer_node_rational_imaginary_create(parser, &parser->previous);
11304+
return (yp_node_t *) yp_integer_node_rational_imaginary_create(parser, base, &parser->previous);
11305+
}
1128711306
case YP_TOKEN_KEYWORD___ENCODING__:
1128811307
parser_lex(parser);
1128911308
return (yp_node_t *) yp_source_encoding_node_create(parser, &parser->previous);
@@ -13816,7 +13835,8 @@ yp_parser_init(yp_parser_t *parser, const uint8_t *source, size_t size, const ch
1381613835
.in_keyword_arg = false,
1381713836
.filepath_string = filepath_string,
1381813837
.constant_pool = YP_CONSTANT_POOL_EMPTY,
13819-
.newline_list = YP_NEWLINE_LIST_EMPTY
13838+
.newline_list = YP_NEWLINE_LIST_EMPTY,
13839+
.integer_base = 0
1382013840
};
1382113841

1382213842
yp_accepts_block_stack_push(parser, true);

templates/ext/yarp/api_node.c.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) {
135135
<%- nodes.each do |node| -%>
136136
#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
137137
case <%= node.type %>: {
138-
<%- if node.fields.any? { |field| ![YARP::NodeField, YARP::OptionalNodeField].include?(field.class) } -%>
138+
<%- if node.fields.any? { |field| ![YARP::NodeField, YARP::OptionalNodeField, YARP::FlagsField].include?(field.class) } -%>
139139
yp_<%= node.human %>_t *cast = (yp_<%= node.human %>_t *) node;
140140
<%- end -%>
141141
VALUE argv[<%= node.fields.length + 1 %>];

test/yarp/errors_test.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,8 @@ def test_returning_to_optional_parameters_multiple_times
889889
ParametersNode(
890890
[RequiredParameterNode(:a)],
891891
[
892-
OptionalParameterNode(:b, Location(), Location(), IntegerNode()),
893-
OptionalParameterNode(:d, Location(), Location(), IntegerNode())
892+
OptionalParameterNode(:b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)),
893+
OptionalParameterNode(:d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL))
894894
],
895895
[RequiredParameterNode(:c), RequiredParameterNode(:e)],
896896
nil,
@@ -933,7 +933,7 @@ def test_setter_method_cannot_be_defined_in_an_endless_method_definition
933933
Location(),
934934
nil,
935935
nil,
936-
StatementsNode([IntegerNode()]),
936+
StatementsNode([IntegerNode(IntegerBaseFlags::DECIMAL)]),
937937
[],
938938
Location(),
939939
nil,
@@ -1123,7 +1123,7 @@ def test_duplicated_parameter_names
11231123
:foo,
11241124
Location(),
11251125
nil,
1126-
ParametersNode([], [OptionalParameterNode(:a, Location(), Location(), IntegerNode())], [RequiredParameterNode(:b)], RestParameterNode(:c, Location(), Location()), [], nil, nil),
1126+
ParametersNode([], [OptionalParameterNode(:a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL))], [RequiredParameterNode(:b)], RestParameterNode(:c, Location(), Location()), [], nil, nil),
11271127
nil,
11281128
[:a, :b, :c],
11291129
Location(),

test/yarp/snapshots/alias.txt

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/yarp/snapshots/arrays.txt

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/yarp/snapshots/blocks.txt

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)