Ruby 4.1.0dev (2026-10-21 revision b4ae8a7189739966cdeedba609512617af45e211)
dump_ast.c
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <inttypes.h>
5
6/*
7 * When prism is compiled as part of CRuby, the xmalloc/xfree/etc. macros are
8 * redirected to ruby_xmalloc/ruby_xfree/etc. Since this is a standalone
9 * program that links against those same object files, we need to provide
10 * implementations of these functions.
11 */
12void *ruby_xmalloc(size_t size) { return malloc(size); }
13void *ruby_xcalloc(size_t nelems, size_t elemsiz) { return calloc(nelems, elemsiz); }
14void *ruby_xrealloc(void *ptr, size_t newsiz) { return realloc(ptr, newsiz); }
15void ruby_xfree(void *ptr) { free(ptr); }
16void ruby_xfree_sized(void *ptr, size_t _oldsize) { free(ptr); }
17void *ruby_xrealloc_sized(void *ptr, size_t newsiz, size_t _oldsiz) { return realloc(ptr, newsiz); }
18
19#include "prism.h"
20
21static void
22usage(const char *prog)
23{
24 fprintf(stderr, "Usage: %s [options]... <filename>\n"
25 "Options:\n"
26 " -v, --version: show Prism version\n"
27 " -h, --help: show this message\n"
28 "", prog);
29}
30
31int
32main(int argc, const char *argv[])
33{
34 const char *filepath = 0;
35
36 for (int i = 1; i < argc; ++i) {
37 const char *arg = argv[i];
38 if (arg[0] != '-') {
39 if (filepath) {
40 fprintf(stderr, "too many filename\n");
41 goto usage;
42 }
43 filepath = arg;
44 }
45 else if (arg[1] == '-') {
46 if (!arg[2]) break;
47 if (strcmp(arg + 2, "version") == 0) {
48 version:
49 fputs("Prism " PRISM_VERSION "\n", stdout);
50 return EXIT_SUCCESS;
51 }
52 if (strcmp(arg + 2, "help") == 0) {
53 help:
54 usage(argv[0]);
55 return EXIT_SUCCESS;
56 }
57 fprintf(stderr, "unknown option %s\n", arg);
58 goto usage;
59 }
60 else {
61 while (*++arg) {
62 switch (*arg) {
63 case 'v':
64 goto version;
65 case 'h':
66 goto help;
67 default:
68 fprintf(stderr, "unknown option -%c\n", *arg);
69 goto usage;
70 }
71 }
72 }
73 }
74
75 if (!filepath) {
76 usage:
77 usage(argv[0]);
78 return EXIT_FAILURE;
79 }
80
81 pm_source_init_result_t init_result;
82 pm_source_t *source = pm_source_mapped_new(filepath, 0, &init_result);
83
84 if (init_result != PM_SOURCE_INIT_SUCCESS) {
85 fprintf(stderr, "unable to map file: %s\n", filepath);
86 return EXIT_FAILURE;
87 }
88
89 pm_options_t *options = pm_options_new();
90 pm_options_line_set(options, 1);
91 pm_options_filepath_set(options, filepath);
92
93 pm_arena_t *arena = pm_arena_new();
94 pm_parser_t *parser = pm_parser_new(arena, pm_source_source(source), pm_source_length(source), options);
95
96 pm_node_t *node = pm_parse(parser);
97 int exit_status;
98
99 if (pm_parser_errors_size(parser) > 0) {
100 fprintf(stderr, "error parsing %s\n", filepath);
101
102 for (
103 const pm_diagnostic_t *diagnostic = pm_parser_errors_first(parser);
104 diagnostic != NULL;
105 diagnostic = pm_diagnostic_next(diagnostic)
106 ) {
107 pm_location_t loc = pm_diagnostic_location(diagnostic);
108 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));
109 fprintf(stderr, "%" PRIi32 ":%" PRIu32 ":%s\n", line_column.line, line_column.column, pm_diagnostic_message(diagnostic));
110 }
111
112 exit_status = EXIT_FAILURE;
113 }
114 else {
115 pm_buffer_t *json = pm_buffer_new();
116 pm_dump_json(json, parser, node);
117 printf("%.*s\n", (int) pm_buffer_length(json), pm_buffer_value(json));
118 pm_buffer_free(json);
119 exit_status = EXIT_SUCCESS;
120 }
121
122 pm_parser_free(parser);
123 pm_arena_free(arena);
124 pm_source_free(source);
125 pm_options_free(options);
126
127 return exit_status;
128}
PRISM_NODISCARD PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NONNULL(1)
Allocate and initialize a parser with the given start and end pointers.
Definition prism.c:23538
PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) PRISM_NONNULL(1)
Free both the memory held by the given parser and the parser itself.
Definition prism.c:23562
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) PRISM_NONNULL(1)
Initiate the parser with the given parser.
Definition prism.c:23733
pm_line_column_t line_column(const pm_parser_t *parser, std::uint32_t offset) noexcept
The line and column of the given byte offset into the source.
Definition parser.hpp:91
#define PRISM_VERSION
The version of the Prism library as a constant string.
Definition version.h:33
The main header file for the prism parser.
pm_source_init_result_t
Represents the result of initializing a source from a file.
Definition source.h:50
@ PM_SOURCE_INIT_SUCCESS
Indicates that the source was successfully initialized.
Definition source.h:52
A line and column in a string.
uint32_t column
The column in bytes.
int32_t line
The line number.
This struct represents a slice in the source code, defined by an offset and a length.
Definition ast.h:579
uint32_t start
The offset of the location from the start of the source.
Definition ast.h:581
This is the base structure that represents a node in the syntax tree.
Definition ast.h:1090