summaryrefslogtreecommitdiff
path: root/prism/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'prism/parser.c')
-rw-r--r--prism/parser.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/prism/parser.c b/prism/parser.c
new file mode 100644
index 0000000000..415cd31984
--- /dev/null
+++ b/prism/parser.c
@@ -0,0 +1,302 @@
+#include "prism/internal/parser.h"
+
+#include "prism/internal/allocator.h"
+#include "prism/internal/comments.h"
+#include "prism/internal/diagnostic.h"
+#include "prism/internal/encoding.h"
+#include "prism/internal/magic_comments.h"
+
+#include <stdlib.h>
+
+/**
+ * Register a callback that will be called whenever prism changes the encoding
+ * it is using to parse based on the magic comment.
+ */
+void
+pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback) {
+ parser->encoding_changed_callback = callback;
+}
+
+/**
+ * Register a callback that will be called whenever a token is lexed.
+ */
+void
+pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data) {
+ parser->lex_callback.callback = callback;
+ parser->lex_callback.data = data;
+}
+
+/**
+ * Returns the opaque data that is passed to the lex callback when it is called.
+ */
+void *
+pm_parser_lex_callback_data(const pm_parser_t *parser) {
+ return parser->lex_callback.data;
+}
+
+/**
+ * Returns the raw pointer to the start of the source that is being parsed.
+ */
+const uint8_t *
+pm_parser_start(const pm_parser_t *parser) {
+ return parser->start;
+}
+
+/**
+ * Returns the raw pointer to the end of the source that is being parsed.
+ */
+const uint8_t *
+pm_parser_end(const pm_parser_t *parser) {
+ return parser->end;
+}
+
+/**
+ * Returns the line that the parser was considered to have started on.
+ *
+ * @param parser the parser whose start line we want to get
+ * @return the line that the parser was considered to have started on
+ */
+int32_t
+pm_parser_start_line(const pm_parser_t *parser) {
+ return parser->start_line;
+}
+
+/**
+ * Returns the name of the encoding that is being used to parse the source.
+ */
+const char *
+pm_parser_encoding_name(const pm_parser_t *parser) {
+ return parser->encoding->name;
+}
+
+/**
+ * Returns the width of the character at the given pointer in the encoding that
+ * is being used to parse the source.
+ */
+size_t
+pm_parser_encoding_char_width(const pm_parser_t *parser, const uint8_t *start, ptrdiff_t remaining) {
+ return parser->encoding->char_width(start, remaining);
+}
+
+/**
+ * Returns whether or not the parser is using the US-ASCII encoding.
+ */
+bool
+pm_parser_encoding_us_ascii(const pm_parser_t *parser) {
+ return parser->encoding == PM_ENCODING_US_ASCII_ENTRY;
+}
+
+/**
+ * Returns the filepath that is being used to parse the source.
+ */
+const pm_string_t *
+pm_parser_filepath(const pm_parser_t *parser) {
+ return &parser->filepath;
+}
+
+/**
+ * Find a constant in the parser's constant pool. Returns the id of the
+ * constant, or 0 if the constant is not found.
+ */
+pm_constant_id_t
+pm_parser_constant_find(const pm_parser_t *parser, const uint8_t *start, size_t length) {
+ return pm_constant_pool_find(&parser->constant_pool, start, length);
+}
+
+/**
+ * Returns the frozen string literal value of the parser.
+ */
+int8_t
+pm_parser_frozen_string_literal(const pm_parser_t *parser) {
+ return parser->frozen_string_literal;
+}
+
+/**
+ * Returns the line offsets that are associated with the given parser.
+ *
+ * @param parser the parser whose line offsets we want to get
+ * @return the line offsets that are associated with the given parser
+ */
+const pm_line_offset_list_t *
+pm_parser_line_offsets(const pm_parser_t *parser) {
+ return &parser->line_offsets;
+}
+
+/**
+ * Returns the location of the __DATA__ section that is associated with the
+ * given parser, if it exists.
+ */
+const pm_location_t *
+pm_parser_data_loc(const pm_parser_t *parser) {
+ return &parser->data_loc;
+}
+
+/**
+ * Returns whether the given parser is continuable, meaning that it could become
+ * valid if more input were appended, as opposed to being definitively invalid.
+ */
+bool
+pm_parser_continuable(const pm_parser_t *parser) {
+ return parser->continuable;
+}
+
+/**
+ * Returns the lex state of the parser. Note that this is an internal detail,
+ * and we are purposefully not returning an instance of the internal enum that
+ * we use to track this. This is only exposed because we need it for some very
+ * niche use cases. Most consumers should avoid this function.
+ */
+int
+pm_parser_lex_state(const pm_parser_t *parser) {
+ return (int) parser->lex_state;
+}
+
+/**
+ * Returns the location associated with the given comment.
+ */
+pm_location_t
+pm_comment_location(const pm_comment_t *comment) {
+ return comment->location;
+}
+
+/**
+ * Returns the type associated with the given comment.
+ */
+pm_comment_type_t
+pm_comment_type(const pm_comment_t *comment) {
+ return comment->type;
+}
+
+/**
+ * Returns the number of comments associated with the given parser.
+ */
+size_t
+pm_parser_comments_size(const pm_parser_t *parser) {
+ return parser->comment_list.size;
+}
+
+/**
+ * Iterates over the comments associated with the given parser and calls the
+ * given callback for each comment.
+ */
+void
+pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callback, void *data) {
+ const pm_list_node_t *current = parser->comment_list.head;
+ while (current != NULL) {
+ const pm_comment_t *comment = (const pm_comment_t *) current;
+ callback(comment, data);
+ current = current->next;
+ }
+}
+
+/**
+ * Returns the location associated with the given magic comment key.
+ */
+pm_location_t
+pm_magic_comment_key(const pm_magic_comment_t *magic_comment) {
+ return magic_comment->key;
+}
+
+/**
+ * Returns the location associated with the given magic comment value.
+ */
+pm_location_t
+pm_magic_comment_value(const pm_magic_comment_t *magic_comment) {
+ return magic_comment->value;
+}
+
+/**
+ * Returns the number of magic comments associated with the given parser.
+ */
+size_t
+pm_parser_magic_comments_size(const pm_parser_t *parser) {
+ return parser->magic_comment_list.size;
+}
+
+/**
+ * Iterates over the magic comments associated with the given parser and calls
+ * the given callback for each magic comment.
+ */
+void
+pm_parser_magic_comments_each(const pm_parser_t *parser, pm_magic_comment_callback_t callback, void *data) {
+ const pm_list_node_t *current = parser->magic_comment_list.head;
+ while (current != NULL) {
+ const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) current;
+ callback(magic_comment, data);
+ current = current->next;
+ }
+}
+
+/**
+ * Returns the number of errors associated with the given parser.
+ */
+size_t
+pm_parser_errors_size(const pm_parser_t *parser) {
+ return parser->error_list.size;
+}
+
+/**
+ * Returns the number of warnings associated with the given parser.
+ */
+size_t
+pm_parser_warnings_size(const pm_parser_t *parser) {
+ return parser->warning_list.size;
+}
+
+static inline void
+pm_parser_diagnostics_each(const pm_list_t *list, pm_diagnostic_callback_t callback, void *data) {
+ const pm_list_node_t *current = list->head;
+ while (current != NULL) {
+ const pm_diagnostic_t *diagnostic = (const pm_diagnostic_t *) current;
+ callback(diagnostic, data);
+ current = current->next;
+ }
+}
+
+/**
+ * Iterates over the errors associated with the given parser and calls the
+ * given callback for each error.
+ */
+void
+pm_parser_errors_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) {
+ pm_parser_diagnostics_each(&parser->error_list, callback, data);
+}
+
+/**
+ * Iterates over the warnings associated with the given parser and calls the
+ * given callback for each warning.
+ */
+void
+pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) {
+ pm_parser_diagnostics_each(&parser->warning_list, callback, data);
+}
+
+/**
+ * Returns the number of constants in the constant pool associated with the
+ * given parser.
+ */
+size_t
+pm_parser_constants_size(const pm_parser_t *parser) {
+ return parser->constant_pool.size;
+}
+
+/**
+ * Iterates over the constants in the constant pool associated with the given
+ * parser and calls the given callback for each constant.
+ */
+void
+pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data) {
+ for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
+ const pm_constant_t *constant = &parser->constant_pool.constants[index];
+ callback(constant, data);
+ }
+}
+
+/**
+ * Returns a pointer to the constant at the given id in the constant pool
+ * associated with the given parser.
+ */
+const pm_constant_t *
+pm_parser_constant(const pm_parser_t *parser, pm_constant_id_t constant_id) {
+ return pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
+}