diff options
Diffstat (limited to 'parser.c')
| -rw-r--r-- | parser.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..574d2ac --- /dev/null +++ b/parser.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | #include "parser.h" | ||
| 2 | #include "lexer.h" | ||
| 3 | #include "types.h" | ||
| 4 | #include <stdio.h> | ||
| 5 | |||
| 6 | |||
| 7 | LISP_OBJECT *parser_parse_str(char *str) | ||
| 8 | { | ||
| 9 | Lexer *lexer = lexer_tokenize(str); | ||
| 10 | lexer_tokens_reverse(lexer); | ||
| 11 | |||
| 12 | Token *token = lexer->tokens; | ||
| 13 | LISP_OBJECT *lisp_obj = NULL; | ||
| 14 | lisp_obj = parser_parse_tokens(&token); | ||
| 15 | |||
| 16 | lexer_free(lexer); | ||
| 17 | |||
| 18 | return lisp_obj; | ||
| 19 | } | ||
| 20 | |||
| 21 | LISP_OBJECT *parser_parse_tokens(Token **token) | ||
| 22 | { | ||
| 23 | LISP_OBJECT *lisp_obj = NULL; | ||
| 24 | switch((*token)->type) | ||
| 25 | { | ||
| 26 | case TOKEN_TYPE_SPECIAL: | ||
| 27 | lisp_obj = parser_make_list(token); | ||
| 28 | break; | ||
| 29 | case TOKEN_TYPE_NUMBER: | ||
| 30 | lisp_obj = parser_make_number(token); | ||
| 31 | break; | ||
| 32 | case TOKEN_TYPE_STRING: | ||
| 33 | lisp_obj = parser_make_string(token); | ||
| 34 | break; | ||
| 35 | case TOKEN_TYPE_SYMBOL: | ||
| 36 | lisp_obj = parser_make_symbol(token); | ||
| 37 | break; | ||
| 38 | case TOKEN_TYPE_TRUE: | ||
| 39 | lisp_obj = parser_make_true(token); | ||
| 40 | break; | ||
| 41 | case TOKEN_TYPE_FALSE: | ||
| 42 | lisp_obj = parser_make_false(token); | ||
| 43 | break; | ||
| 44 | case TOKEN_TYPE_NIL: | ||
| 45 | lisp_obj = parser_make_nil(token); | ||
| 46 | break; | ||
| 47 | case TOKEN_TYPE_ERROR: | ||
| 48 | lisp_obj = lisp_object_make_error((*token)->value); | ||
| 49 | *token = (*token)->next; | ||
| 50 | break; | ||
| 51 | default: | ||
| 52 | *token = (*token)->next; | ||
| 53 | lisp_obj = lisp_object_make_error("Something bad happenend!"); | ||
| 54 | } | ||
| 55 | return lisp_obj; | ||
| 56 | } | ||
| 57 | |||
| 58 | LISP_OBJECT *parser_make_list(Token **token) | ||
| 59 | { | ||
| 60 | LISP_OBJECT *lisp_list_obj = lisp_object_make_list(); | ||
| 61 | char close_delimiter = ( *(*token)->value == '(' ) ? ')' : ']'; | ||
| 62 | *token = (*token)->next; | ||
| 63 | int is_close_delimiter = 1; | ||
| 64 | |||
| 65 | while(*token) | ||
| 66 | { | ||
| 67 | if((*token)->type==TOKEN_TYPE_SPECIAL && | ||
| 68 | *(*token)->value==close_delimiter) | ||
| 69 | { | ||
| 70 | is_close_delimiter=0; | ||
| 71 | *token=(*token)->next; | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | |||
| 75 | lisp_object_list_push(lisp_list_obj, | ||
| 76 | (void *)parser_parse_tokens(token)); | ||
| 77 | |||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | List *list = list_reverse(lisp_list_obj->value.list); | ||
| 82 | lisp_list_obj->value.list = list; | ||
| 83 | |||
| 84 | if(is_close_delimiter != 0) | ||
| 85 | { | ||
| 86 | LISP_OBJECT *err_msg = lisp_object_make_error("Unbalanced parenthesis!"); | ||
| 87 | lisp_object_list_push(lisp_list_obj, err_msg); | ||
| 88 | } | ||
| 89 | |||
| 90 | return lisp_list_obj; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | LISP_OBJECT *parser_make_number(Token **token) | ||
| 95 | { | ||
| 96 | LISP_OBJECT *lisp_obj = NULL; | ||
| 97 | char *number_str = (*token)->value; | ||
| 98 | union | ||
| 99 | { | ||
| 100 | long long natural; | ||
| 101 | double floating; | ||
| 102 | |||
| 103 | } number; | ||
| 104 | |||
| 105 | if((*token)->is_decimal_point) | ||
| 106 | { | ||
| 107 | sscanf(number_str, "%lf", &number.floating); | ||
| 108 | lisp_obj = lisp_object_make_number_float(number.floating); | ||
| 109 | } | ||
| 110 | else | ||
| 111 | { | ||
| 112 | sscanf(number_str, "%lld", &number.natural); | ||
| 113 | lisp_obj = lisp_object_make_number_natural(number.natural); | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | *token=(*token)->next; | ||
| 118 | return lisp_obj; | ||
| 119 | } | ||
| 120 | |||
| 121 | LISP_OBJECT *parser_make_string(Token **token) | ||
| 122 | { | ||
| 123 | char *str = (*token)->value; | ||
| 124 | LISP_OBJECT *lisp_obj = lisp_object_make_string(str); | ||
| 125 | |||
| 126 | *token=(*token)->next; | ||
| 127 | return lisp_obj; | ||
| 128 | } | ||
| 129 | |||
| 130 | LISP_OBJECT *parser_make_symbol(Token **token) | ||
| 131 | { | ||
| 132 | char *str = (*token)->value; | ||
| 133 | LISP_OBJECT *lisp_obj = lisp_object_make_symbol(str); | ||
| 134 | |||
| 135 | *token=(*token)->next; | ||
| 136 | return lisp_obj; | ||
| 137 | } | ||
| 138 | |||
| 139 | LISP_OBJECT *parser_make_true(Token **token) | ||
| 140 | { | ||
| 141 | LISP_OBJECT *lisp_obj = lisp_object_make_true(); | ||
| 142 | |||
| 143 | *token=(*token)->next; | ||
| 144 | return lisp_obj; | ||
| 145 | } | ||
| 146 | |||
| 147 | LISP_OBJECT *parser_make_false(Token **token) | ||
| 148 | { | ||
| 149 | LISP_OBJECT *lisp_obj = lisp_object_make_false(); | ||
| 150 | |||
| 151 | *token=(*token)->next; | ||
| 152 | return lisp_obj; | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | LISP_OBJECT *parser_make_nil(Token **token) | ||
| 157 | { | ||
| 158 | LISP_OBJECT *lisp_obj = lisp_object_make_nil(); | ||
| 159 | |||
| 160 | *token=(*token)->next; | ||
| 161 | return lisp_obj; | ||
| 162 | } | ||
| 163 | |||
| 164 | int main() | ||
| 165 | { | ||
| 166 | char *test = "(display (string-append \"4*3+2=\" (number->string (+ (* 4 3) 1))))"; | ||
| 167 | |||
| 168 | |||
| 169 | LISP_OBJECT *obj = NULL; | ||
| 170 | |||
| 171 | obj = parser_parse_str(test); | ||
| 172 | lisp_object_print(obj, 0); | ||
| 173 | lisp_object_free(obj); | ||
| 174 | } | ||
