зеркало из https://github.com/github/ruby.git
[ruby/prism] Create an options struct for passing all of the possible options
https://github.com/ruby/prism/commit/99e81619de
This commit is contained in:
Родитель
a43a52d415
Коммит
2a0f2b7763
|
@ -45,6 +45,7 @@ Gem::Specification.new do |spec|
|
|||
"include/prism/diagnostic.h",
|
||||
"include/prism/enc/pm_encoding.h",
|
||||
"include/prism/node.h",
|
||||
"include/prism/options.h",
|
||||
"include/prism/pack.h",
|
||||
"include/prism/parser.h",
|
||||
"include/prism/prettyprint.h",
|
||||
|
@ -106,6 +107,7 @@ Gem::Specification.new do |spec|
|
|||
"src/util/pm_string_list.c",
|
||||
"src/util/pm_strncasecmp.c",
|
||||
"src/util/pm_strpbrk.c",
|
||||
"src/options.c",
|
||||
"src/prism.c",
|
||||
"prism.gemspec",
|
||||
"sig/prism.rbs",
|
||||
|
|
|
@ -61,14 +61,14 @@ input_load_string(pm_string_t *input, VALUE string) {
|
|||
* Dump the AST corresponding to the given input to a string.
|
||||
*/
|
||||
static VALUE
|
||||
dump_input(pm_string_t *input, const char *filepath) {
|
||||
dump_input(pm_string_t *input, const pm_options_t *options) {
|
||||
pm_buffer_t buffer;
|
||||
if (!pm_buffer_init(&buffer)) {
|
||||
rb_raise(rb_eNoMemError, "failed to allocate memory");
|
||||
}
|
||||
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
||||
|
||||
pm_node_t *node = pm_parse(&parser);
|
||||
pm_serialize(&parser, node, &buffer);
|
||||
|
@ -103,7 +103,11 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|||
pm_string_constant_init(&input, dup, length);
|
||||
#endif
|
||||
|
||||
VALUE value = dump_input(&input, check_string(filepath));
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, check_string(filepath));
|
||||
|
||||
VALUE value = dump_input(&input, &options);
|
||||
pm_options_free(&options);
|
||||
|
||||
#ifdef PRISM_DEBUG_MODE_BUILD
|
||||
free(dup);
|
||||
|
@ -125,7 +129,12 @@ dump_file(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
VALUE value = dump_input(&input, checked);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
VALUE value = dump_input(&input, &options);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -316,9 +325,9 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) {
|
|||
* the nodes and tokens.
|
||||
*/
|
||||
static VALUE
|
||||
parse_lex_input(pm_string_t *input, const char *filepath, bool return_nodes) {
|
||||
parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) {
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
||||
pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback);
|
||||
|
||||
VALUE offsets = rb_ary_new();
|
||||
|
@ -385,7 +394,13 @@ lex(int argc, VALUE *argv, VALUE self) {
|
|||
pm_string_t input;
|
||||
input_load_string(&input, string);
|
||||
|
||||
return parse_lex_input(&input, check_string(filepath), false);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, check_string(filepath));
|
||||
|
||||
VALUE result = parse_lex_input(&input, &options, false);
|
||||
pm_options_free(&options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,7 +416,12 @@ lex_file(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
VALUE value = parse_lex_input(&input, checked, false);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
VALUE value = parse_lex_input(&input, &options, false);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -415,9 +435,9 @@ lex_file(VALUE self, VALUE filepath) {
|
|||
* Parse the given input and return a ParseResult instance.
|
||||
*/
|
||||
static VALUE
|
||||
parse_input(pm_string_t *input, const char *filepath) {
|
||||
parse_input(pm_string_t *input, const pm_options_t *options) {
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
||||
|
||||
pm_node_t *node = pm_parse(&parser);
|
||||
rb_encoding *encoding = rb_enc_find(parser.encoding.name);
|
||||
|
@ -462,7 +482,11 @@ parse(int argc, VALUE *argv, VALUE self) {
|
|||
pm_string_constant_init(&input, dup, length);
|
||||
#endif
|
||||
|
||||
VALUE value = parse_input(&input, check_string(filepath));
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, check_string(filepath));
|
||||
|
||||
VALUE value = parse_input(&input, &options);
|
||||
pm_options_free(&options);
|
||||
|
||||
#ifdef PRISM_DEBUG_MODE_BUILD
|
||||
free(dup);
|
||||
|
@ -484,7 +508,11 @@ parse_file(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
VALUE value = parse_input(&input, checked);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
VALUE value = parse_input(&input, &options);
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -494,9 +522,9 @@ parse_file(VALUE self, VALUE filepath) {
|
|||
* Parse the given input and return an array of Comment objects.
|
||||
*/
|
||||
static VALUE
|
||||
parse_input_comments(pm_string_t *input, const char *filepath) {
|
||||
parse_input_comments(pm_string_t *input, const pm_options_t *options) {
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
|
||||
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
||||
|
||||
pm_node_t *node = pm_parse(&parser);
|
||||
rb_encoding *encoding = rb_enc_find(parser.encoding.name);
|
||||
|
@ -525,7 +553,13 @@ parse_comments(int argc, VALUE *argv, VALUE self) {
|
|||
pm_string_t input;
|
||||
input_load_string(&input, string);
|
||||
|
||||
return parse_input_comments(&input, check_string(filepath));
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, check_string(filepath));
|
||||
|
||||
VALUE result = parse_input_comments(&input, &options);
|
||||
pm_options_free(&options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -541,7 +575,12 @@ parse_file_comments(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
VALUE value = parse_input_comments(&input, checked);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
VALUE value = parse_input_comments(&input, &options);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -568,7 +607,12 @@ parse_lex(int argc, VALUE *argv, VALUE self) {
|
|||
pm_string_t input;
|
||||
input_load_string(&input, string);
|
||||
|
||||
VALUE value = parse_lex_input(&input, check_string(filepath), true);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, check_string(filepath));
|
||||
|
||||
VALUE value = parse_lex_input(&input, &options, true);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -593,7 +637,12 @@ parse_lex_file(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
VALUE value = parse_lex_input(&input, checked, true);
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
VALUE value = parse_lex_input(&input, &options, true);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return value;
|
||||
|
@ -670,13 +719,16 @@ profile_file(VALUE self, VALUE filepath) {
|
|||
const char *checked = check_string(filepath);
|
||||
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
||||
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, checked);
|
||||
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), checked);
|
||||
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
|
||||
|
||||
pm_node_t *node = pm_parse(&parser);
|
||||
pm_node_destroy(&parser, node);
|
||||
pm_parser_free(&parser);
|
||||
|
||||
pm_options_free(&options);
|
||||
pm_string_free(&input);
|
||||
|
||||
return Qnil;
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
#include "prism/options.h"
|
||||
|
||||
/**
|
||||
* Set the filepath option on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_filepath_set(pm_options_t *options, const char *filepath) {
|
||||
options->filepath = filepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encoding option on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_encoding_set(pm_options_t *options, const char *encoding) {
|
||||
options->encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line option on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_line_set(pm_options_t *options, uint32_t line) {
|
||||
options->line = line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frozen string literal option on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) {
|
||||
options->frozen_string_literal = frozen_string_literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the suppress warnings option on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_suppress_warnings_set(pm_options_t *options, bool suppress_warnings) {
|
||||
options->suppress_warnings = suppress_warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and zero out the scopes array on the given options struct.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_scopes_init(pm_options_t *options, size_t scopes_count) {
|
||||
options->scopes_count = scopes_count;
|
||||
options->scopes = calloc(scopes_count, sizeof(pm_options_scope_t));
|
||||
if (options->scopes == NULL) abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the scope at the given index within the given options.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION const pm_options_scope_t *
|
||||
pm_options_scope_get(const pm_options_t *options, size_t index) {
|
||||
return &options->scopes[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new options scope struct. This will hold a set of locals that are in
|
||||
* scope surrounding the code that is being parsed.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) {
|
||||
scope->locals_count = locals_count;
|
||||
scope->locals = calloc(locals_count, sizeof(pm_string_t));
|
||||
if (scope->locals == NULL) abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the local at the given index within the given scope.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION const pm_string_t *
|
||||
pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) {
|
||||
return &scope->locals[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the internal memory associated with the options.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_free(pm_options_t *options) {
|
||||
for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) {
|
||||
pm_options_scope_t *scope = &options->scopes[scope_index];
|
||||
|
||||
for (size_t local_index = 0; local_index < scope->locals_count; local_index++) {
|
||||
pm_string_free(&scope->locals[local_index]);
|
||||
}
|
||||
|
||||
free(scope->locals);
|
||||
}
|
||||
|
||||
free(options->scopes);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* @file options.h
|
||||
*
|
||||
* The options that can be passed to parsing.
|
||||
*/
|
||||
#ifndef PRISM_OPTIONS_H
|
||||
#define PRISM_OPTIONS_H
|
||||
|
||||
#include "prism/defines.h"
|
||||
#include "prism/util/pm_string.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* A scope of locals surrounding the code that is being parsed.
|
||||
*/
|
||||
typedef struct pm_options_scope {
|
||||
/** The number of locals in the scope. */
|
||||
size_t locals_count;
|
||||
|
||||
/** The names of the locals in the scope. */
|
||||
pm_string_t *locals;
|
||||
} pm_options_scope_t;
|
||||
|
||||
/**
|
||||
* The options that can be passed to the parser.
|
||||
*/
|
||||
typedef struct {
|
||||
/** The name of the file that is currently being parsed. */
|
||||
const char *filepath;
|
||||
|
||||
/**
|
||||
* The name of the encoding that the source file is in. Note that this must
|
||||
* correspond to a name that can be found with Encoding.find in Ruby.
|
||||
*/
|
||||
const char *encoding;
|
||||
|
||||
/**
|
||||
* The line within the file that the parse starts on. This value is
|
||||
* 0-indexed.
|
||||
*/
|
||||
uint32_t line;
|
||||
|
||||
/**
|
||||
* The number of scopes surrounding the code that is being parsed.
|
||||
*/
|
||||
size_t scopes_count;
|
||||
|
||||
/**
|
||||
* The scopes surrounding the code that is being parsed. For most parses
|
||||
* this will be NULL, but for evals it will be the locals that are in scope
|
||||
* surrounding the eval.
|
||||
*/
|
||||
pm_options_scope_t *scopes;
|
||||
|
||||
/** Whether or not the frozen string literal option has been set. */
|
||||
bool frozen_string_literal;
|
||||
|
||||
/**
|
||||
* Whether or not we should suppress warnings. This is purposefully negated
|
||||
* so that the default is to not suppress warnings, which allows us to still
|
||||
* create an options struct with zeroed memory.
|
||||
*/
|
||||
bool suppress_warnings;
|
||||
} pm_options_t;
|
||||
|
||||
/**
|
||||
* Set the filepath option on the given options struct.
|
||||
*
|
||||
* @param options The options struct to set the filepath on.
|
||||
* @param filepath The filepath to set.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_filepath_set(pm_options_t *options, const char *filepath);
|
||||
|
||||
/**
|
||||
* Set the encoding option on the given options struct.
|
||||
*
|
||||
* @param options The options struct to set the encoding on.
|
||||
* @param encoding The encoding to set.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_encoding_set(pm_options_t *options, const char *encoding);
|
||||
|
||||
/**
|
||||
* Set the line option on the given options struct.
|
||||
*
|
||||
* @param options The options struct to set the line on.
|
||||
* @param line The line to set.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_line_set(pm_options_t *options, uint32_t line);
|
||||
|
||||
/**
|
||||
* Set the frozen string literal option on the given options struct.
|
||||
*
|
||||
* @param options The options struct to set the frozen string literal value on.
|
||||
* @param frozen_string_literal The frozen string literal value to set.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);
|
||||
|
||||
/**
|
||||
* Set the suppress warnings option on the given options struct.
|
||||
*
|
||||
* @param options The options struct to set the suppress warnings value on.
|
||||
* @param suppress_warnings The suppress warnings value to set.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_suppress_warnings_set(pm_options_t *options, bool suppress_warnings);
|
||||
|
||||
/**
|
||||
* Allocate and zero out the scopes array on the given options struct.
|
||||
*
|
||||
* @param options The options struct to initialize the scopes array on.
|
||||
* @param scopes_count The number of scopes to allocate.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_scopes_init(pm_options_t *options, size_t scopes_count);
|
||||
|
||||
/**
|
||||
* Return a pointer to the scope at the given index within the given options.
|
||||
*
|
||||
* @param options The options struct to get the scope from.
|
||||
* @param index The index of the scope to get.
|
||||
* @return A pointer to the scope at the given index.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION const pm_options_scope_t *
|
||||
pm_options_scope_get(const pm_options_t *options, size_t index);
|
||||
|
||||
/**
|
||||
* Create a new options scope struct. This will hold a set of locals that are in
|
||||
* scope surrounding the code that is being parsed.
|
||||
*
|
||||
* @param scope The scope struct to initialize.
|
||||
* @param locals_count The number of locals to allocate.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count);
|
||||
|
||||
/**
|
||||
* Return a pointer to the local at the given index within the given scope.
|
||||
*
|
||||
* @param scope The scope struct to get the local from.
|
||||
* @param index The index of the local to get.
|
||||
* @return A pointer to the local at the given index.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION const pm_string_t *
|
||||
pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index);
|
||||
|
||||
/**
|
||||
* Free the internal memory associated with the options.
|
||||
*
|
||||
* @param options The options struct whose internal memory should be freed.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_options_free(pm_options_t *options);
|
||||
|
||||
#endif
|
|
@ -16319,14 +16319,9 @@ pm_parser_metadata(pm_parser_t *parser, const char *metadata) {
|
|||
* Initialize a parser with the given start and end pointers.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const char *filepath) {
|
||||
pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) {
|
||||
assert(source != NULL);
|
||||
|
||||
// Set filepath to the file that was passed
|
||||
if (!filepath) filepath = "";
|
||||
pm_string_t filepath_string;
|
||||
pm_string_constant_init(&filepath_string, filepath, strlen(filepath));
|
||||
|
||||
*parser = (pm_parser_t) {
|
||||
.lex_state = PM_LEX_STATE_BEG,
|
||||
.enclosure_nesting = 0,
|
||||
|
@ -16356,7 +16351,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const ch
|
|||
.encoding_decode_callback = NULL,
|
||||
.encoding_comment_start = source,
|
||||
.lex_callback = NULL,
|
||||
.filepath_string = filepath_string,
|
||||
.filepath_string = { 0 },
|
||||
.constant_pool = { 0 },
|
||||
.newline_list = { 0 },
|
||||
.integer_base = 0,
|
||||
|
@ -16370,8 +16365,6 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const ch
|
|||
.frozen_string_literal = false
|
||||
};
|
||||
|
||||
pm_accepts_block_stack_push(parser, true);
|
||||
|
||||
// Initialize the constant pool. We're going to completely guess as to the
|
||||
// number of constants that we'll need based on the size of the input. The
|
||||
// ratio we chose here is actually less arbitrary than you might think.
|
||||
|
@ -16395,6 +16388,53 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const ch
|
|||
size_t newline_size = size / 22;
|
||||
pm_newline_list_init(&parser->newline_list, source, newline_size < 4 ? 4 : newline_size);
|
||||
|
||||
// If options were provided to this parse, establish them here.
|
||||
if (options != NULL) {
|
||||
// filepath option
|
||||
if (options->filepath == NULL) {
|
||||
pm_string_constant_init(&parser->filepath_string, "", 0);
|
||||
} else {
|
||||
pm_string_constant_init(&parser->filepath_string, options->filepath, strlen(options->filepath));
|
||||
}
|
||||
|
||||
// line option
|
||||
if (options->line > 0) {
|
||||
pm_newline_list_force(&parser->newline_list, options->line);
|
||||
}
|
||||
|
||||
// encoding option
|
||||
// if (options->encoding != NULL) {}
|
||||
|
||||
// frozen_string_literal option
|
||||
if (options->frozen_string_literal) {
|
||||
parser->frozen_string_literal = true;
|
||||
}
|
||||
|
||||
// suppress_warnings option
|
||||
// if (options->suppress_warnings) {}
|
||||
|
||||
// scopes option
|
||||
for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) {
|
||||
const pm_options_scope_t *scope = pm_options_scope_get(options, scope_index);
|
||||
pm_parser_scope_push(parser, scope_index == 0);
|
||||
|
||||
for (size_t local_index = 0; local_index < scope->locals_count; local_index++) {
|
||||
const pm_string_t *local = pm_options_scope_local_get(scope, local_index);
|
||||
|
||||
const uint8_t *source = pm_string_source(local);
|
||||
size_t length = pm_string_length(local);
|
||||
|
||||
uint8_t *allocated = malloc(length);
|
||||
if (allocated == NULL) continue;
|
||||
|
||||
memcpy((void *) allocated, source, length);
|
||||
pm_parser_local_add_owned(parser, allocated, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pm_accepts_block_stack_push(parser, true);
|
||||
|
||||
// Skip past the UTF-8 BOM if it exists.
|
||||
if (size >= 3 && source[0] == 0xef && source[1] == 0xbb && source[2] == 0xbf) {
|
||||
parser->current.end += 3;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "prism/ast.h"
|
||||
#include "prism/diagnostic.h"
|
||||
#include "prism/node.h"
|
||||
#include "prism/options.h"
|
||||
#include "prism/pack.h"
|
||||
#include "prism/parser.h"
|
||||
#include "prism/prettyprint.h"
|
||||
|
@ -47,9 +48,9 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void);
|
|||
* @param parser The parser to initialize.
|
||||
* @param source The source to parse.
|
||||
* @param size The size of the source.
|
||||
* @param filepath The optional filepath to pass to the parser.
|
||||
* @param options The optional options to use when parsing.
|
||||
*/
|
||||
PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const char *filepath);
|
||||
PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options);
|
||||
|
||||
/**
|
||||
* Register a callback that will be called whenever prism changes the encoding
|
||||
|
|
|
@ -288,8 +288,11 @@ serialize_token(void *data, pm_parser_t *parser, pm_token_t *token) {
|
|||
*/
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_lex_serialize(const uint8_t *source, size_t size, const char *filepath, pm_buffer_t *buffer) {
|
||||
pm_options_t options = { 0 };
|
||||
pm_options_filepath_set(&options, filepath);
|
||||
|
||||
pm_parser_t parser;
|
||||
pm_parser_init(&parser, source, size, filepath);
|
||||
pm_parser_init(&parser, source, size, &options);
|
||||
|
||||
pm_lex_callback_t lex_callback = (pm_lex_callback_t) {
|
||||
.data = (void *) buffer,
|
||||
|
@ -310,6 +313,7 @@ pm_lex_serialize(const uint8_t *source, size_t size, const char *filepath, pm_bu
|
|||
|
||||
pm_node_destroy(&parser, node);
|
||||
pm_parser_free(&parser);
|
||||
pm_options_free(&options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,33 @@ pm_newline_list_init(pm_newline_list_t *list, const uint8_t *start, size_t capac
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the newline list such that it believes it is starting on a specific
|
||||
* line in the source. Basically this entails pushing on pointers to the start
|
||||
* of the string until we hit the desired line.
|
||||
*/
|
||||
bool
|
||||
pm_newline_list_force(pm_newline_list_t *list, size_t count) {
|
||||
size_t next_capacity = list->capacity == 0 ? 1 : list->capacity;
|
||||
while (count > next_capacity) {
|
||||
next_capacity *= 2;
|
||||
}
|
||||
|
||||
size_t *offsets = list->offsets;
|
||||
list->offsets = (size_t *) calloc(next_capacity, sizeof(size_t));
|
||||
if (list->offsets == NULL) return false;
|
||||
|
||||
if (offsets != NULL) {
|
||||
memcpy(list->offsets, offsets, list->size * sizeof(size_t));
|
||||
free(offsets);
|
||||
}
|
||||
|
||||
memset(list->offsets + list->size, 0, count * sizeof(size_t));
|
||||
list->size += count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a new offset to the newline list. Returns true if the reallocation of
|
||||
* the offsets succeeds (if one was necessary), otherwise returns false.
|
||||
|
|
|
@ -61,6 +61,18 @@ typedef struct {
|
|||
*/
|
||||
bool pm_newline_list_init(pm_newline_list_t *list, const uint8_t *start, size_t capacity);
|
||||
|
||||
/**
|
||||
* Set up the newline list such that it believes it is starting on a specific
|
||||
* line in the source. Basically this entails pushing on pointers to the start
|
||||
* of the string until we hit the desired line.
|
||||
*
|
||||
* @param list The list to set up.
|
||||
* @param count The number of lines to push onto the list.
|
||||
* @return True if no reallocation was needed or the reallocation of the offsets
|
||||
* succeeds (if one was necessary), otherwise false.
|
||||
*/
|
||||
bool pm_newline_list_force(pm_newline_list_t *list, size_t count);
|
||||
|
||||
/**
|
||||
* Append a new offset to the newline list. Returns true if the reallocation of
|
||||
* the offsets succeeds (if one was necessary), otherwise returns false.
|
||||
|
|
Загрузка…
Ссылка в новой задаче