5 #include "script/parser.h"
7 static bool is_symbol_char(char x)
9 static const char forbidden_symbol_chars[] = {
10 '(', ')', '"', '\'', ';'
12 static const size_t n = sizeof(forbidden_symbol_chars) / sizeof(char);
14 for (size_t i = 0; i < n; ++i) {
15 if (x == forbidden_symbol_chars[i] || isspace(x)) {
23 static void skip_whitespaces(const char *str, size_t *cursor, size_t n)
28 while (*cursor < n && isspace(str[*cursor])) {
33 struct ParseResult create_expr_from_str(const char *str,
40 /* TODO(#297): create_expr_from_str doesn't parse lists */
41 /* TODO(#291): create_expr_from_str doesn't no support comments */
43 skip_whitespaces(str, cursor, n);
45 return parse_failure("EOF", *cursor);
48 switch (str[*cursor]) {
51 struct ParseResult car = create_expr_from_str(str, cursor, n);
56 skip_whitespaces(str, cursor, n);
58 return parse_failure("EOF", *cursor);
61 if (str[*cursor] != '.') {
62 return parse_failure("Expected .", *cursor);
66 skip_whitespaces(str, cursor, n);
68 return parse_failure("EOF", *cursor);
71 struct ParseResult cdr = create_expr_from_str(str, cursor, n);
76 skip_whitespaces(str, cursor, n);
78 return parse_failure("EOF", *cursor);
81 if (str[*cursor] != ')') {
82 return parse_failure("Expected )", *cursor);
87 return parse_success(cons_as_expr(create_cons(car.expr, cdr.expr)));
91 /* TODO(#292): parser does not support escaped string characters */
92 const size_t str_begin = *cursor + 1;
93 size_t str_end = str_begin;
95 while(str_end < n && str[str_end] != '"') {
100 return parse_failure("Unclosed string", str_begin);
103 *cursor = str_end + 1;
105 return parse_success(
107 create_string_atom(str + str_begin, str + str_end)));
111 if (isdigit(str[*cursor])) {
112 const char *nptr = str + *cursor;
114 const float x = strtof(nptr, &endptr);
116 if (nptr == endptr) {
117 return parse_failure("Number expected", *cursor);
120 *cursor += (size_t) (endptr - nptr);
122 return parse_success(atom_as_expr(create_number_atom(x)));
123 } else if (is_symbol_char(str[*cursor])) {
124 const size_t sym_begin = *cursor;
125 size_t sym_end = sym_begin;
127 while (sym_end < n && is_symbol_char(str[sym_end])) {
133 return parse_success(
135 create_symbol_atom(str + sym_begin, str + sym_end)));
140 return parse_failure("Unexpected sequence of characters", *cursor);
143 struct ParseResult parse_success(struct Expr expr)
145 struct ParseResult result = {
153 struct ParseResult parse_failure(const char *error_message,
156 struct ParseResult result = {
159 .error_message = error_message,
160 .error_cursor = error_cursor
167 void print_parse_error(FILE *stream,
169 struct ParseError error)
171 /* TODO(#293): print_parse_error doesn't support colors */
172 /* TODO(#294): print_parse_error doesn't support multiple lines */
174 fprintf(stream, "%s\n", str);
175 for (size_t i = 0; i < error.error_cursor; ++i) {
176 fprintf(stream, " ");
178 fprintf(stream, "^\n");
179 fprintf(stream, "%s\n", error.error_message);