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_cons(struct Token current_token)
30 if (*current_token.begin != '(') {
31 return parse_failure("Expected (", current_token.begin);
34 current_token = next_token(current_token.end);
36 if (*current_token.begin == ')') {
37 return parse_success(atom_as_expr(create_symbol_atom("nil", NULL)), current_token.end);
40 struct ParseResult car = parse_expr(current_token);
45 struct ParseResult cdr = parse_cdr(next_token(car.end));
47 destroy_expr(car.expr);
51 return parse_success(cons_as_expr(create_cons(car.expr, cdr.expr)), cdr.end);
54 static struct ParseResult parse_string(struct Token current_token)
56 if (*current_token.begin != '"') {
57 return parse_failure("Expected \"", current_token.begin);
60 if (*(current_token.end - 1) != '"') {
61 return parse_failure("Unclosed string", current_token.begin);
64 if (current_token.begin + 1 == current_token.end) {
65 return parse_success(atom_as_expr(create_string_atom("", NULL)),
71 create_string_atom(current_token.begin + 1, current_token.end - 1)),
75 static struct ParseResult parse_number(struct Token current_token)
78 const float x = strtof(current_token.begin, &endptr);
80 if (current_token.begin == endptr || current_token.end != endptr) {
81 return parse_failure("Expected number", current_token.begin);
85 atom_as_expr(create_number_atom(x)),
89 static struct ParseResult parse_symbol(struct Token current_token)
91 if (*current_token.begin == 0) {
92 return parse_failure("EOF", current_token.begin);
96 atom_as_expr(create_symbol_atom(current_token.begin, current_token.end)),
100 struct ParseResult parse_expr(struct Token current_token)
102 if (*current_token.begin == 0) {
103 return parse_failure("EOF", current_token.begin);
106 /* TODO(#301): parse_expr doesn't parse lists */
108 switch (*current_token.begin) {
109 case '(': return parse_cons(current_token);
110 /* TODO(#292): parser does not support escaped string characters */
111 case '"': return parse_string(current_token);
115 if (isdigit(*current_token.begin)) {
116 return parse_number(current_token);
119 return parse_symbol(current_token);
122 struct ParseResult parse_success(struct Expr expr,
125 struct ParseResult result = {
134 struct ParseResult parse_failure(const char *error_message,
137 struct ParseResult result = {
139 .error_message = error_message,
146 void print_parse_error(FILE *stream,
148 struct ParseResult result)
150 /* TODO(#293): print_parse_error doesn't support colors */
151 /* TODO(#294): print_parse_error doesn't support multiple lines */
152 if (!result.is_error) {
156 fprintf(stream, "%s\n", str);
157 for (size_t i = 0; i < (size_t) (result.end - str); ++i) {
158 fprintf(stream, " ");
160 fprintf(stream, "^\n");
161 fprintf(stream, "%s\n", result.error_message);