Improve parser errors slightly

This commit is contained in:
2022-11-15 15:18:37 -05:00
parent 583367ee9d
commit 785dbf06f6
4 changed files with 50 additions and 14 deletions

View File

@@ -79,7 +79,12 @@ int main(int argc, const char **argv) {
}
struct ucl_object *sexp = ucl_parse(line);
struct ucl_object *result = ucl_evaluate(scope, ucl_car(sexp));
struct ucl_object *result = NULL;
if (sexp->type == UCL_TYPE_ERROR) {
result = sexp;
} else {
result = ucl_evaluate(scope, ucl_car(sexp));
}
ucl_print_obj(result);
printf("\n");

View File

@@ -1,5 +1,6 @@
#include "uclisp.h"
#include "internal.h"
#include "utility.h"
// TODO: remove these
#include <stdbool.h>
@@ -20,6 +21,8 @@ static const char *reserved_symbols[] = {
};
// TODO: remove malloc and strndup calls
// TODO: refresh this with newer 'object' code
// TODO: Syntatic sugar for quote
static bool ucl_is_whitespace(char c) {
return c == ' ' || c == '\n' || c == '\t';
@@ -68,6 +71,7 @@ struct ucl_object *ucl_token_next(const char **curr_src) {
str = strndup(start + 1, *curr_src - start - 2);
return ucl_cell_create(ucl_string_create(str), NULL);
case '0'...'9': {
// TODO: Add support for negative integers
char *end = NULL;
long value = strtol(*curr_src, &end, 0);
*curr_src = end;
@@ -141,6 +145,9 @@ static struct ucl_object *ucl_parse_tokens_recursive(struct ucl_object **token_i
assert((*token_iter)->type == UCL_TYPE_CELL);
struct ucl_object *token = (*token_iter)->cell.car;
if (token == NULL) {
return NULL;
}
struct ucl_object *next_sexp = ucl_parse_token_atom(token);
if (next_sexp != NULL) {
*token_iter = (*token_iter)->cell.cdr;
@@ -154,7 +161,13 @@ static struct ucl_object *ucl_parse_tokens_recursive(struct ucl_object **token_i
// Consume the START_LIST_CHAR
*token_iter = (*token_iter)->cell.cdr;
while (1) {
if (*token_iter == NULL) {
// Unexpected end of parsing
return ucl_error_create("Unmatched open parenthesis");
}
token = (*token_iter)->cell.car;
if (token->type == UCL_TYPE_SYMBOL && token->symbol[0] == END_LIST_CHAR) {
*token_iter = (*token_iter)->cell.cdr;
if (list == NULL) {
@@ -164,6 +177,7 @@ static struct ucl_object *ucl_parse_tokens_recursive(struct ucl_object **token_i
}
next_sexp = ucl_parse_tokens_recursive(token_iter);
UCL_RET_IF_ERROR(next_sexp);
if (next_sexp == NULL) {
// Error somewhere in the recursive parsing
ucl_object_delete(list);
@@ -174,12 +188,11 @@ static struct ucl_object *ucl_parse_tokens_recursive(struct ucl_object **token_i
next_node = &(*next_node)->cell.cdr;
}
} else if (token->symbol[0] == END_LIST_CHAR) {
// Mismatched parens
return NULL;
return ucl_error_create("Unmatched closed parenthesis");
}
// Any other symbol type should have been an atom, this shouldn't happen
assert(false);
return NULL;
return ucl_error_create("Unreachable parse error");
}
// parse_tokens -> doesn't care about quotes, terminates on EOF
@@ -192,8 +205,8 @@ struct ucl_object *ucl_parse_tokens(struct ucl_object *tokens) {
while (*token_iter != NULL) {
struct ucl_object *new_sexp = ucl_parse_tokens_recursive(token_iter);
if (new_sexp == NULL) {
goto error;
if (new_sexp == NULL || new_sexp->type == UCL_TYPE_ERROR) {
return new_sexp;
}
*next_cell = ucl_cell_create(new_sexp, NULL);
@@ -206,7 +219,6 @@ struct ucl_object *ucl_parse_tokens(struct ucl_object *tokens) {
return resultl;
error:
ucl_object_delete(resultl);
return NULL;
}
@@ -214,13 +226,13 @@ struct ucl_object *ucl_parse_tokens(struct ucl_object *tokens) {
// all sexps in the source (return a list of sexps)?
struct ucl_object *ucl_parse(const char *source) {
struct ucl_object *tokens = ucl_tokenize(source);
if (tokens == NULL) {
tokens = ucl_nil_create();
}
UCL_RET_IF_ERROR(tokens);
struct ucl_object *sexp = ucl_parse_tokens(tokens);
ucl_object_delete(tokens);
if (sexp == NULL) {
return ucl_nil_create();
}
return sexp;
}
/* struct ParseResult *ucl_parse(const char *source) { */
/* struct Cell *tokens = ucl_tokenize(source); */
/* struct Cell *sexp = n */
/* } */

View File

@@ -5,6 +5,8 @@
#include <assert.h>
// TODO: Macro support?
struct ucl_object *ucl_special_let(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *assignments = ucl_car(args);

View File

@@ -4,6 +4,7 @@
#include "uclisp.h"
#include "internal.h"
#include "testing_helpers.h"
/* static struct ucl_parse_result *result; */
static struct ucl_object *response;
@@ -331,6 +332,20 @@ static void test_parse_nested(void) {
TEST_ASSERT_EQUAL_STRING("foo", response->cell.car->cell.car->cell.car->symbol);
}
static void test_parse_mismatched_open(void) {
response = ucl_parse("(");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_parse_mismatched_closed(void) {
response = ucl_parse(")");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_OBJ_ERROR(response);
}
int main(void) {
UNITY_BEGIN();
@@ -357,5 +372,7 @@ int main(void) {
RUN_TEST(test_parse_2elem);
RUN_TEST(test_parse_2elem_str);
RUN_TEST(test_parse_nested);
RUN_TEST(test_parse_mismatched_open);
RUN_TEST(test_parse_mismatched_closed);
return UNITY_END();
}