5 #include "script/parser.h"
7 static struct ParseResult parse_cdr(struct Token current_token)
9 if (*current_token.begin != '.') {
10 return parse_failure("Expected .", current_token.begin);
13 struct ParseResult cdr = parse_expr(next_token(current_token.end));
18 current_token = next_token(cdr.end);
20 if (*current_token.begin != ')') {
21 destroy_expr(cdr.expr);
22 return parse_failure("Expected )", current_token.begin);
25 return parse_success(cdr.expr, current_token.end);
28 static struct ParseResult parse_list_end(struct Token current_token)
30 if (*current_token.begin != ')') {
31 return parse_failure("Expected )", current_token.begin);
34 return parse_success(atom_as_expr(create_symbol_atom("nil", NULL)),
38 static struct ParseResult parse_list(struct Token current_token)
40 if (*current_token.begin != '(') {
41 return parse_failure("Expected (", current_token.begin);
44 current_token = next_token(current_token.end);
46 if (*current_token.begin == ')') {
47 return parse_list_end(current_token);
50 struct ParseResult car = parse_expr(current_token);
55 struct Cons *list = create_cons(car.expr, void_expr());
56 struct Cons *cons = list;
57 current_token = next_token(car.end);
59 while (*current_token.begin != '.' &&
60 *current_token.begin != ')' &&
61 *current_token.begin != 0) {
62 car = parse_expr(current_token);
68 cons->cdr = cons_as_expr(create_cons(car.expr, void_expr()));
69 cons = cons->cdr.cons;
71 current_token = next_token(car.end);
74 struct ParseResult cdr = *current_token.begin == '.'
75 ? parse_cdr(current_token)
76 : parse_list_end(current_token);
85 return parse_success(cons_as_expr(list), cdr.end);
88 static struct ParseResult parse_string(struct Token current_token)
90 if (*current_token.begin != '"') {
91 return parse_failure("Expected \"", current_token.begin);
94 if (*(current_token.end - 1) != '"') {
95 return parse_failure("Unclosed string", current_token.begin);
98 if (current_token.begin + 1 == current_token.end) {
99 return parse_success(atom_as_expr(create_string_atom("", NULL)),
103 return parse_success(
105 create_string_atom(current_token.begin + 1, current_token.end - 1)),
109 static struct ParseResult parse_number(struct Token current_token)
112 const float x = strtof(current_token.begin, &endptr);
114 if (current_token.begin == endptr || current_token.end != endptr) {
115 return parse_failure("Expected number", current_token.begin);
118 return parse_success(
119 atom_as_expr(create_number_atom(x)),
123 static struct ParseResult parse_symbol(struct Token current_token)
125 if (*current_token.begin == 0) {
126 return parse_failure("EOF", current_token.begin);
129 return parse_success(
130 atom_as_expr(create_symbol_atom(current_token.begin, current_token.end)),
134 struct ParseResult parse_expr(struct Token current_token)
136 if (*current_token.begin == 0) {
137 return parse_failure("EOF", current_token.begin);
140 switch (*current_token.begin) {
141 case '(': return parse_list(current_token);
142 /* TODO(#292): parser does not support escaped string characters */
143 case '"': return parse_string(current_token);
147 if (isdigit(*current_token.begin)) {
148 return parse_number(current_token);
151 return parse_symbol(current_token);
154 struct ParseResult parse_success(struct Expr expr,
157 struct ParseResult result = {
166 struct ParseResult parse_failure(const char *error_message,
169 struct ParseResult result = {
171 .error_message = error_message,
178 void print_parse_error(FILE *stream,
180 struct ParseResult result)
182 /* TODO(#293): print_parse_error doesn't support colors */
183 /* TODO(#294): print_parse_error doesn't support multiple lines */
184 if (!result.is_error) {
188 fprintf(stream, "%s\n", str);
189 for (size_t i = 0; i < (size_t) (result.end - str); ++i) {
190 fprintf(stream, " ");
192 fprintf(stream, "^\n");
193 fprintf(stream, "%s\n", result.error_message);