summaryrefslogtreecommitdiff
path: root/tool/dump_ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'tool/dump_ast.c')
-rw-r--r--tool/dump_ast.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/tool/dump_ast.c b/tool/dump_ast.c
new file mode 100644
index 0000000000..58250e9b8c
--- /dev/null
+++ b/tool/dump_ast.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+/*
+ * When prism is compiled as part of CRuby, the xmalloc/xfree/etc. macros are
+ * redirected to ruby_xmalloc/ruby_xfree/etc. Since this is a standalone
+ * program that links against those same object files, we need to provide
+ * implementations of these functions.
+ */
+void *ruby_xmalloc(size_t size) { return malloc(size); }
+void *ruby_xcalloc(size_t nelems, size_t elemsiz) { return calloc(nelems, elemsiz); }
+void *ruby_xrealloc(void *ptr, size_t newsiz) { return realloc(ptr, newsiz); }
+void ruby_xfree(void *ptr) { free(ptr); }
+void ruby_xfree_sized(void *ptr, size_t _oldsize) { free(ptr); }
+void *ruby_xrealloc_sized(void *ptr, size_t newsiz, size_t _oldsiz) { return realloc(ptr, newsiz); }
+
+#include "prism.h"
+
+static void
+print_error(const pm_diagnostic_t *diagnostic, void *data)
+{
+ const pm_parser_t *parser = (const pm_parser_t *) data;
+ pm_location_t loc = pm_diagnostic_location(diagnostic);
+ const pm_line_column_t line_column = pm_line_offset_list_line_column(pm_parser_line_offsets(parser), loc.start, pm_parser_start_line(parser));
+ fprintf(stderr, "%" PRIi32 ":%" PRIu32 ":%s\n", line_column.line, line_column.column, pm_diagnostic_message(diagnostic));
+}
+
+int
+main(int argc, const char *argv[]) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ const char *filepath = argv[1];
+ pm_source_init_result_t init_result;
+ pm_source_t *source = pm_source_mapped_new(filepath, 0, &init_result);
+
+ if (init_result != PM_SOURCE_INIT_SUCCESS)
+ {
+ fprintf(stderr, "unable to map file: %s\n", filepath);
+ return EXIT_FAILURE;
+ }
+
+ pm_options_t *options = pm_options_new();
+ pm_options_line_set(options, 1);
+ pm_options_filepath_set(options, filepath);
+
+ pm_arena_t *arena = pm_arena_new();
+ pm_parser_t *parser = pm_parser_new(arena, pm_source_source(source), pm_source_length(source), options);
+
+ pm_node_t *node = pm_parse(parser);
+ int exit_status;
+
+ if (pm_parser_errors_size(parser) > 0)
+ {
+ fprintf(stderr, "error parsing %s\n", filepath);
+ pm_parser_errors_each(parser, print_error, parser);
+ exit_status = EXIT_FAILURE;
+ }
+ else {
+ pm_buffer_t *json = pm_buffer_new();
+ pm_dump_json(json, parser, node);
+ printf("%.*s\n", (int) pm_buffer_length(json), pm_buffer_value(json));
+ pm_buffer_free(json);
+ exit_status = EXIT_SUCCESS;
+ }
+
+ pm_parser_free(parser);
+ pm_arena_free(arena);
+ pm_source_free(source);
+ pm_options_free(options);
+
+ return exit_status;
+}