]> git.lizzy.rs Git - nothing.git/blob - src/script/parser.c
Merge pull request #287 from tsoding/283
[nothing.git] / src / script / parser.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4
5 #include "script/parser.h"
6
7 static void skip_whitespaces(const char *str, size_t *cursor, size_t n)
8 {
9     assert(str);
10     assert(cursor);
11
12     while (*cursor < n && isspace(str[*cursor])) {
13         (*cursor)++;
14     }
15 }
16
17 struct ParseResult create_expr_from_str(const char *str,
18                                         size_t *cursor,
19                                         size_t n)
20 {
21     assert(str);
22     assert(cursor);
23
24     skip_whitespaces(str, cursor, n);
25     if (*cursor >= n) {
26         return parse_failure("EOF");
27     }
28
29     switch (str[*cursor]) {
30     case '(': {
31         (*cursor)++;
32         struct ParseResult car = create_expr_from_str(str, cursor, n);
33         if (car.is_error) {
34             return car;
35         }
36
37         skip_whitespaces(str, cursor, n);
38         if (*cursor >= n) {
39             return parse_failure("EOF");
40         }
41
42         if (str[*cursor] != '.') {
43             return parse_failure("Expected .");
44         }
45         (*cursor)++;
46
47         skip_whitespaces(str, cursor, n);
48         if (*cursor >= n) {
49             return parse_failure("EOF");
50         }
51
52         struct ParseResult cdr = create_expr_from_str(str, cursor, n);
53         if (cdr.is_error) {
54             return cdr;
55         }
56
57         skip_whitespaces(str, cursor, n);
58         if (*cursor >= n) {
59             return parse_failure("EOF");
60         }
61
62         if (str[*cursor] != ')') {
63             return parse_failure("Expected )");
64         }
65
66         (*cursor)++;
67
68         return parse_success(cons_as_expr(create_cons(car.expr, cdr.expr)));
69     }
70
71     case '"': {
72         /* TODO(#288): create_expr_from_str does not support strings */
73         return parse_failure("Strings are not supported");
74     }
75
76     default: {
77         if (isdigit(str[*cursor])) {
78             const char *nptr = str + *cursor;
79             char *endptr = 0;
80             const double x = strtod(nptr, &endptr);
81
82             if (nptr == endptr) {
83                 return parse_failure("Number expected");
84             }
85
86             *cursor += (size_t) (endptr - nptr);
87
88             return parse_success(atom_as_expr(create_atom(ATOM_NUMBER, x)));
89         } else if (isalpha(str[*cursor])) {
90             /* TODO(#289): create_expr_from_str does not support symbols */
91             return parse_failure("Symbols are not supported");
92         }
93     }
94     }
95
96     return parse_failure("Unexpected sequence of characters");
97 }
98
99 struct ParseResult parse_success(struct Expr expr)
100 {
101     struct ParseResult result = {
102         .is_error = false,
103         .expr = expr
104     };
105
106     return result;
107 }
108
109 struct ParseResult parse_failure(const char *error)
110 {
111     struct ParseResult result = {
112         .is_error = true,
113         .error = error
114     };
115
116     return result;
117 }