From: Mike Lowis Date: Tue, 15 Dec 2015 09:26:42 +0000 (+0000) Subject: Combined parser and grammar files as they are not *really* independent X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=92841104e10ea1a84dc5954d0abd925f29f8931f;p=proto%2Fsclpl.git Combined parser and grammar files as they are not *really* independent --- diff --git a/Makefile b/Makefile index 281ffba..c924ccb 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,6 @@ LDFLAGS += ${LIBS} # Build Targets and Rules #------------------------------------------------------------------------------ SRCS = source/main.c \ - source/grammar.c \ source/lexer.c \ source/parser.c \ source/pprint.c \ diff --git a/source/grammar.c b/source/grammar.c deleted file mode 100644 index 2d560bb..0000000 --- a/source/grammar.c +++ /dev/null @@ -1,202 +0,0 @@ -/** - @file grammar.c - @brief See header for details - $Revision$ - $HeadURL$ -*/ -#include - -static AST* require(Parser* p); -static AST* definition(Parser* p); -static AST* expression(Parser* p); -static AST* if_stmnt(Parser* p); -static AST* function(Parser* p); -static AST* literal(Parser* p); -static AST* expr_block(Parser* p); -static AST* token_to_tree(Tok* tok); -static AST* func_app(Parser* p, AST* fn); - -AST* toplevel(Parser* p) -{ - AST* ret = NULL; - if (!match(p, T_END_FILE)) { - if (accept_str(p, T_ID, "require")) - ret = require(p); - else if (accept_str(p, T_ID, "def")) - ret = definition(p); - else - ret = expression(p); - } - //printf("%p\n", ret); - //else if (accept_str(p, T_ID, "type")) - // return type_definition(p); - //else if (accept_str(p, T_ID, "ann")) - // return type_annotation(p); - return ret; -} - -static AST* definition(Parser* p) -{ - Tok* id = expect(p, T_ID); - AST* expr; - if (peek(p)->type == T_LPAR) { - expr = function(p); - } else { - expr = expression(p); - expect(p, T_END); - } - return Def(id, expr); -} - -static AST* require(Parser* p) -{ - AST* ast = Require(expect(p, T_STRING)); - expect(p, T_END); - return ast; -} - -static AST* expression(Parser* p) -{ - AST* expr = NULL; - if (accept(p, T_LPAR)) { - expr = expression(p); - expect(p, T_RPAR); - } else if (accept_str(p, T_ID, "if")) { - expr = if_stmnt(p); - } else if (accept_str(p, T_ID, "fn")) { - expr = function(p); - } else if (match(p, T_ID)) { - expr = Ident(expect(p,T_ID)); - } else { - expr = literal(p); - } - /* Check if this is a function application */ - if (peek(p)->type == T_LPAR) { - expr = func_app(p, expr); - } - return expr; -} - -static AST* if_stmnt(Parser* p) -{ - AST* ifexpr = IfExpr(); - ifexpr_set_cond( ifexpr, expression(p) ); - accept_str(p, T_ID, "then"); - ifexpr_set_then( ifexpr, expr_block(p) ); - if (accept_str(p, T_ID, "else")) - ifexpr_set_else( ifexpr, expr_block(p) ); - expect(p,T_END); - return ifexpr; -} - -static AST* function(Parser* p) -{ - AST* func = Func(); - expect(p, T_LPAR); - while(peek(p)->type != T_RPAR) { - func_add_arg(func, Ident(expect(p,T_ID))); - if(peek(p)->type != T_RPAR) - expect(p, T_COMMA); - } - expect(p, T_RPAR); - func_set_body(func, expr_block(p)); - expect(p, T_END); - return func; -} - -static AST* literal(Parser* p) -{ - AST* ret = NULL; - Tok* tok = peek(p); - switch (tok->type) { - case T_BOOL: - case T_CHAR: - case T_STRING: - case T_INT: - case T_FLOAT: - ret = token_to_tree(expect(p, tok->type)); - break; - default: - error(p, "Expected a literal"); - } - return ret; -} - -static AST* expr_block(Parser* p) -{ - AST* block = Block(); - do { - block_append(block, expression(p)); - } while(!match(p, T_END) && !match_str(p, T_ID, "else")); - return block; -} - -static AST* token_to_tree(Tok* tok) -{ - switch (tok->type) { - case T_BOOL: return Bool(tok); - case T_CHAR: return Char(tok); - case T_STRING: return String(tok); - case T_INT: return Integer(tok); - case T_FLOAT: return Float(tok); - case T_ID: return Ident(tok); - default: return NULL; - } -} - -static AST* func_app(Parser* p, AST* fn) -{ - AST* app = FnApp(fn); - expect(p,T_LPAR); - while (peek(p)->type != T_RPAR) { - fnapp_add_arg(app, expression(p)); - if (peek(p)->type != T_RPAR) - expect(p, T_COMMA); - } - expect(p,T_RPAR); - return app; -} - - -#if 0 -static AST* type_annotation(Parser* p) -{ - //shifttok(p, T_ID); - //type(p); - //expect(p, T_END); - //reduce(Annotation); - return NULL; -} - -static AST* type_definition(Parser* p) -{ - //expect(p, T_ID); - //expect_str(p, T_ID, "is"); - //type(p); - //expect(p, T_END); - return NULL; -} - -static AST* type(Parser* p) { - //if (accept(p, T_LBRACE)) { - // tuple(p); - //} else { - // expect(p, T_ID); - // if (accept(p, T_LPAR)) { - // function(p); - // } - //} - return NULL; -} - -static AST* tuple(Parser* p) { - ////size_t mrk = mark(p); - ////insert(p, T_ID, lexer_dup("tuple")); - //do { - // type(p); - //} while (accept(p, T_COMMA)); - //expect(p, T_RBRACE); - ////reduce(p, mrk); - return NULL; -} -#endif diff --git a/source/parser.c b/source/parser.c index a058bf8..479df83 100644 --- a/source/parser.c +++ b/source/parser.c @@ -6,17 +6,226 @@ */ #include +/* Private Declarations + *****************************************************************************/ +// Sentinel EOF Token Tok tok_eof = { NULL, 0, 0, T_END_FILE, {0} }; -static void parser_free(void* obj) { - Parser* parser = (Parser*)obj; - if ((NULL != parser->tok) && (&tok_eof != parser->tok)) { - gc_delref(parser->tok); +// Grammar Routines +static AST* require(Parser* p); +static AST* definition(Parser* p); +static AST* expression(Parser* p); +static AST* if_stmnt(Parser* p); +static AST* function(Parser* p); +static AST* literal(Parser* p); +static AST* expr_block(Parser* p); +static AST* token_to_tree(Tok* tok); +static AST* func_app(Parser* p, AST* fn); + +// Parsing Routines +static void parser_free(void* obj); +static void fetch(Parser* parser); +static Tok* peek(Parser* parser); +static bool parser_eof(Parser* parser); +static void parser_resume(Parser* parser); +static void error(Parser* parser, const char* text); +static bool match(Parser* parser, TokType type); +static bool match_str(Parser* parser, TokType type, const char* text); +static Tok* accept(Parser* parser, TokType type); +static Tok* accept_str(Parser* parser, TokType type, const char* text); +static Tok* expect(Parser* parser, TokType type); +static Tok* expect_str(Parser* parser, TokType type, const char* text); + +/* Grammar Definition + *****************************************************************************/ +AST* toplevel(Parser* p) +{ + AST* ret = NULL; + if (!match(p, T_END_FILE)) { + if (accept_str(p, T_ID, "require")) + ret = require(p); + else if (accept_str(p, T_ID, "def")) + ret = definition(p); + else + ret = expression(p); } - if (parser->line != NULL) - free(parser->line); + //printf("%p\n", ret); + //else if (accept_str(p, T_ID, "type")) + // return type_definition(p); + //else if (accept_str(p, T_ID, "ann")) + // return type_annotation(p); + return ret; +} + +static AST* definition(Parser* p) +{ + Tok* id = expect(p, T_ID); + AST* expr; + if (peek(p)->type == T_LPAR) { + expr = function(p); + } else { + expr = expression(p); + expect(p, T_END); + } + return Def(id, expr); } +static AST* require(Parser* p) +{ + AST* ast = Require(expect(p, T_STRING)); + expect(p, T_END); + return ast; +} + +static AST* expression(Parser* p) +{ + AST* expr = NULL; + if (accept(p, T_LPAR)) { + expr = expression(p); + expect(p, T_RPAR); + } else if (accept_str(p, T_ID, "if")) { + expr = if_stmnt(p); + } else if (accept_str(p, T_ID, "fn")) { + expr = function(p); + } else if (match(p, T_ID)) { + expr = Ident(expect(p,T_ID)); + } else { + expr = literal(p); + } + /* Check if this is a function application */ + if (peek(p)->type == T_LPAR) { + expr = func_app(p, expr); + } + return expr; +} + +static AST* if_stmnt(Parser* p) +{ + AST* ifexpr = IfExpr(); + ifexpr_set_cond( ifexpr, expression(p) ); + accept_str(p, T_ID, "then"); + ifexpr_set_then( ifexpr, expr_block(p) ); + if (accept_str(p, T_ID, "else")) + ifexpr_set_else( ifexpr, expr_block(p) ); + expect(p,T_END); + return ifexpr; +} + +static AST* function(Parser* p) +{ + AST* func = Func(); + expect(p, T_LPAR); + while(peek(p)->type != T_RPAR) { + func_add_arg(func, Ident(expect(p,T_ID))); + if(peek(p)->type != T_RPAR) + expect(p, T_COMMA); + } + expect(p, T_RPAR); + func_set_body(func, expr_block(p)); + expect(p, T_END); + return func; +} + +static AST* literal(Parser* p) +{ + AST* ret = NULL; + Tok* tok = peek(p); + switch (tok->type) { + case T_BOOL: + case T_CHAR: + case T_STRING: + case T_INT: + case T_FLOAT: + ret = token_to_tree(expect(p, tok->type)); + break; + default: + error(p, "Expected a literal"); + } + return ret; +} + +static AST* expr_block(Parser* p) +{ + AST* block = Block(); + do { + block_append(block, expression(p)); + } while(!match(p, T_END) && !match_str(p, T_ID, "else")); + return block; +} + +static AST* token_to_tree(Tok* tok) +{ + switch (tok->type) { + case T_BOOL: return Bool(tok); + case T_CHAR: return Char(tok); + case T_STRING: return String(tok); + case T_INT: return Integer(tok); + case T_FLOAT: return Float(tok); + case T_ID: return Ident(tok); + default: return NULL; + } +} + +static AST* func_app(Parser* p, AST* fn) +{ + AST* app = FnApp(fn); + expect(p,T_LPAR); + while (peek(p)->type != T_RPAR) { + fnapp_add_arg(app, expression(p)); + if (peek(p)->type != T_RPAR) + expect(p, T_COMMA); + } + expect(p,T_RPAR); + return app; +} + + +#if 0 +static AST* type_annotation(Parser* p) +{ + //shifttok(p, T_ID); + //type(p); + //expect(p, T_END); + //reduce(Annotation); + return NULL; +} + +static AST* type_definition(Parser* p) +{ + //expect(p, T_ID); + //expect_str(p, T_ID, "is"); + //type(p); + //expect(p, T_END); + return NULL; +} + +static AST* type(Parser* p) { + //if (accept(p, T_LBRACE)) { + // tuple(p); + //} else { + // expect(p, T_ID); + // if (accept(p, T_LPAR)) { + // function(p); + // } + //} + return NULL; +} + +static AST* tuple(Parser* p) { + ////size_t mrk = mark(p); + ////insert(p, T_ID, lexer_dup("tuple")); + //do { + // type(p); + //} while (accept(p, T_COMMA)); + //expect(p, T_RBRACE); + ////reduce(p, mrk); + return NULL; +} +#endif + + +/* Parsing Routines + *****************************************************************************/ Parser* parser_new(char* prompt, FILE* input) { Parser* parser = (Parser*)gc_alloc(sizeof(Parser), &parser_free); @@ -29,25 +238,37 @@ Parser* parser_new(char* prompt, FILE* input) return parser; } -void fetch(Parser* parser) +static void parser_free(void* obj) +{ + Parser* parser = (Parser*)obj; + if ((NULL != parser->tok) && (&tok_eof != parser->tok)) { + gc_delref(parser->tok); + } + if (parser->line != NULL) + free(parser->line); +} + +static void fetch(Parser* parser) { parser->tok = gettoken(parser); if (NULL == parser->tok) parser->tok = &tok_eof; } -Tok* peek(Parser* parser) +static Tok* peek(Parser* parser) { if (NULL == parser->tok) fetch(parser); return parser->tok; } -bool parser_eof(Parser* parser) { +static bool parser_eof(Parser* parser) +{ return (peek(parser)->type == T_END_FILE); } -void parser_resume(Parser* parser) { +static void parser_resume(Parser* parser) +{ if ((NULL != parser->tok) && (&tok_eof != parser->tok)) { gc_delref(parser->tok); parser->tok = NULL; @@ -57,25 +278,25 @@ void parser_resume(Parser* parser) { fetchline(parser); } -void error(Parser* parser, const char* text) +static void error(Parser* parser, const char* text) { Tok* tok = peek(parser); fprintf(stderr, ":%zu:%zu:Error: %s\n", tok->line, tok->col, text); exit(1); } -bool match(Parser* parser, TokType type) +static bool match(Parser* parser, TokType type) { return (peek(parser)->type == type); } -bool match_str(Parser* parser, TokType type, const char* text) +static bool match_str(Parser* parser, TokType type, const char* text) { return (match(parser, type) && (0 == strcmp((char*)(peek(parser)->value.text), text))); } -Tok* accept(Parser* parser, TokType type) +static Tok* accept(Parser* parser, TokType type) { Tok* tok = peek(parser); if (tok->type == type) { @@ -85,7 +306,7 @@ Tok* accept(Parser* parser, TokType type) return NULL; } -Tok* accept_str(Parser* parser, TokType type, const char* text) +static Tok* accept_str(Parser* parser, TokType type, const char* text) { Tok* tok = peek(parser); if ((tok->type == type) && (0 == strcmp((char*)(tok->value.text), text))) { @@ -95,7 +316,7 @@ Tok* accept_str(Parser* parser, TokType type, const char* text) return NULL; } -Tok* expect(Parser* parser, TokType type) +static Tok* expect(Parser* parser, TokType type) { Tok* tok = accept(parser, type); if (tok == NULL) { @@ -104,7 +325,7 @@ Tok* expect(Parser* parser, TokType type) return tok; } -Tok* expect_str(Parser* parser, TokType type, const char* text) +static Tok* expect_str(Parser* parser, TokType type, const char* text) { Tok* tok = accept_str(parser, type, text); if (tok == NULL) { diff --git a/source/sclpl.h b/source/sclpl.h index 4493960..7bf4b38 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -211,17 +211,6 @@ void fetchline(Parser* ctx); // Parser routines Parser* parser_new(char* p_prompt, FILE* input); -void fetch(Parser* p_parser); -Tok* peek(Parser* p_parser); -bool parser_eof(Parser* p_parser); -void parser_resume(Parser* p_parser); -void error(Parser* p_parser, const char* p_text); -bool match(Parser* parser, TokType type); -bool match_str(Parser* parser, TokType type, const char* text); -Tok* accept(Parser* p_parser, TokType type); -Tok* accept_str(Parser* p_parser, TokType type, const char* p_text); -Tok* expect(Parser* p_parser, TokType type); -Tok* expect_str(Parser* p_parser, TokType type, const char* p_text); // Grammar Routines AST* toplevel(Parser* p);