From a481f9b4f8a9b1a839d28e186fd36e4b891b2d8c Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 1 Oct 2014 20:00:05 -0400 Subject: [PATCH] added some error handling --- source/sclpl/grammar.c | 25 ++++++++++++++++--------- source/sclpl/lexer.c | 8 ++++++-- source/sclpl/lexer.h | 2 ++ source/sclpl/main.c | 10 +++++++--- source/sclpl/parser.c | 23 ++++++++++++++++++----- source/sclpl/parser.h | 5 +++++ source/sclpl/scanner.c | 3 +-- source/sclpl/scanner.h | 2 ++ 8 files changed, 57 insertions(+), 21 deletions(-) diff --git a/source/sclpl/grammar.c b/source/sclpl/grammar.c index 9ab6523..8a4a33c 100644 --- a/source/sclpl/grammar.c +++ b/source/sclpl/grammar.c @@ -5,18 +5,25 @@ $HeadURL$ */ #include "grammar.h" +#include "exn.h" tree_t* grammar_toplevel(parser_t* p_parser) { - if (parser_accept_str(p_parser, T_VAR, "import")) - grammar_import(p_parser); - else if (parser_accept_str(p_parser, T_VAR, "def")) - grammar_definition(p_parser); - else if (p_parser->p_lexer->scanner->p_input == stdin) - grammar_expression(p_parser); - else - parser_error(p_parser, "Unrecognized top-level form"); - return parser_get_tree(p_parser); + tree_t* p_tree = NULL; + try { + if (parser_accept_str(p_parser, T_VAR, "import")) + grammar_import(p_parser); + else if (parser_accept_str(p_parser, T_VAR, "def")) + grammar_definition(p_parser); + else if (p_parser->p_lexer->scanner->p_input == stdin) + grammar_expression(p_parser); + else + parser_error(p_parser, "Unrecognized top-level form"); + p_tree = parser_get_tree(p_parser); + } catch(ParseException) { + fprintf(stderr, "Invalid Syntax\n"); + } + return p_tree; } void grammar_import(parser_t* p_parser) diff --git a/source/sclpl/lexer.c b/source/sclpl/lexer.c index b0bafe5..dc0f6ae 100644 --- a/source/sclpl/lexer.c +++ b/source/sclpl/lexer.c @@ -52,13 +52,17 @@ lex_tok_t* lexer_read(lexer_t* p_lexer) { char* text = scanner_read(p_lexer->scanner); if (NULL != text) { p_tok = lexer_make_token(text); - if (NULL != p_tok) - printf("TOK: '%s' -> %s\n", text, lexer_tok_type_str(p_tok)); + //if (NULL != p_tok) + // printf("TOK: '%s' -> %s\n", text, lexer_tok_type_str(p_tok)); free(text); } return p_tok; } +void lexer_skipline(lexer_t* p_lexer) { + scanner_getline(p_lexer->scanner); +} + static lex_tok_t* lexer_make_token(char* text) { lex_tok_t* p_tok = NULL; if ((0 == strcmp(text,"end") || (text[0] == ';'))) { diff --git a/source/sclpl/lexer.h b/source/sclpl/lexer.h index e0536b8..40d65fa 100644 --- a/source/sclpl/lexer.h +++ b/source/sclpl/lexer.h @@ -33,6 +33,8 @@ lexer_t* lexer_new(char* p_prompt, FILE* p_input); lex_tok_t* lexer_read(lexer_t* p_lexer); +void lexer_skipline(lexer_t* p_lexer); + char* lexer_tok_type_str(lex_tok_t* p_tok); #endif /* LEXER_H */ diff --git a/source/sclpl/main.c b/source/sclpl/main.c index 2aebbb3..0e032a7 100644 --- a/source/sclpl/main.c +++ b/source/sclpl/main.c @@ -50,9 +50,13 @@ int main(int argc, char **argv) { parser_t* p_parser = parser_new(":> ", stdin); while(!parser_eof(p_parser)) { tree_t* p_tree = grammar_toplevel(p_parser); - print_tree(p_tree, 0); - mem_release(p_tree); - puts("OK."); + if (NULL != p_tree) { + print_tree(p_tree, 0); + mem_release(p_tree); + puts("OK."); + } else { + parser_resume(p_parser); + } } mem_release(p_parser); diff --git a/source/sclpl/parser.c b/source/sclpl/parser.c index 9482459..9317594 100644 --- a/source/sclpl/parser.c +++ b/source/sclpl/parser.c @@ -7,6 +7,8 @@ #include "parser.h" #include "vec.h" +DEFINE_EXCEPTION(ParseException, &RuntimeException); + lex_tok_t tok_eof = { T_END_FILE, NULL, 0, 0, NULL }; static void parser_free(void* p_obj) { @@ -59,11 +61,16 @@ bool parser_eof(parser_t* p_parser) { return (parser_peek(p_parser)->type == T_END_FILE); } +void parser_resume(parser_t* p_parser) { + if (NULL != p_parser->p_tok) + mem_release(p_parser->p_tok); + vec_clear(p_parser->p_tok_buf); + lexer_skipline(p_parser->p_lexer); +} + void parser_error(parser_t* p_parser, const char* p_text) { - (void)p_parser; - fprintf(stderr,"Error: %s\n",p_text); - exit(1); + throw_msg(ParseException, p_text); } bool parser_accept(parser_t* p_parser, lex_tok_type_t type) @@ -128,8 +135,14 @@ void parser_reduce(parser_t* p_parser, size_t mark) } tree_t* parser_get_tree(parser_t* p_parser) { - tree_t* p_tree = parser_tree_new(TREE, p_parser->p_tok_buf); - p_parser->p_tok_buf = vec_new(0); + tree_t* p_tree = NULL; + if (1 == vec_size(p_parser->p_tok_buf)) { + p_tree = mem_retain(vec_at(p_parser->p_tok_buf, 0)); + vec_clear(p_parser->p_tok_buf); + } else { + p_tree = parser_tree_new(TREE, p_parser->p_tok_buf); + p_parser->p_tok_buf = vec_new(0); + } return p_tree; } diff --git a/source/sclpl/parser.h b/source/sclpl/parser.h index 0e62b1a..0ab71fc 100644 --- a/source/sclpl/parser.h +++ b/source/sclpl/parser.h @@ -9,6 +9,9 @@ #include "lexer.h" #include "vec.h" +#include "exn.h" + +DECLARE_EXCEPTION(ParseException); typedef enum { ATOM, TREE } tree_tag_t; @@ -34,6 +37,8 @@ lex_tok_t* parser_peek(parser_t* p_parser); bool parser_eof(parser_t* p_parser); +void parser_resume(parser_t* p_parser); + void parser_error(parser_t* p_parser, const char* p_text); bool parser_accept(parser_t* p_parser, lex_tok_type_t type); diff --git a/source/sclpl/scanner.c b/source/sclpl/scanner.c index 4813dc7..0dc2785 100644 --- a/source/sclpl/scanner.c +++ b/source/sclpl/scanner.c @@ -1,7 +1,6 @@ #include "scanner.h" #include "mem.h" -static void scanner_getline(scanner_t* p_scanner); static void scanner_skip_ws(scanner_t* p_scanner); static char scanner_current(scanner_t* p_scanner); static bool scanner_oneof(scanner_t* p_scanner, const char* p_set); @@ -60,7 +59,7 @@ bool scanner_eol(scanner_t* p_scanner) return ret; } -static void scanner_getline(scanner_t* p_scanner) { +void scanner_getline(scanner_t* p_scanner) { int c; size_t capacity = 8; size_t index = 0; diff --git a/source/sclpl/scanner.h b/source/sclpl/scanner.h index 0cc14f1..31afcea 100644 --- a/source/sclpl/scanner.h +++ b/source/sclpl/scanner.h @@ -25,4 +25,6 @@ bool scanner_eof(scanner_t* p_scanner); bool scanner_eol(scanner_t* p_scanner); +void scanner_getline(scanner_t* p_scanner); + #endif /* SCANNER_H */ -- 2.52.0