]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Refactor code structure to have separate parser and grammar modules
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 26 Sep 2014 17:52:47 +0000 (13:52 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 26 Sep 2014 17:52:47 +0000 (13:52 -0400)
modules/libcds
modules/libopts
source/sclpl/grammar.c [new file with mode: 0644]
source/sclpl/grammar.h [new file with mode: 0644]
source/sclpl/main.c
source/sclpl/parser.c [new file with mode: 0644]
source/sclpl/parser.h [new file with mode: 0644]

index 5550feb668fd728863039e50bd660e79236df5d0..a70643a30382932f3eda4d2a5159e81664731bea 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5550feb668fd728863039e50bd660e79236df5d0
+Subproject commit a70643a30382932f3eda4d2a5159e81664731bea
index 11db084f5d5c49caa482341f5a83ba37918c9c8c..9266387d534a8ca397824e07e62e390ca1dbb236 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 11db084f5d5c49caa482341f5a83ba37918c9c8c
+Subproject commit 9266387d534a8ca397824e07e62e390ca1dbb236
diff --git a/source/sclpl/grammar.c b/source/sclpl/grammar.c
new file mode 100644 (file)
index 0000000..2de905b
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+  @file grammar.c
+  @brief See header for details
+  $Revision$
+  $HeadURL$
+  */
+#include "grammar.h"
+
+void 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");
+}
+
+void grammar_import(parser_t* p_parser)
+{
+    parser_expect(p_parser, T_VAR);
+    parser_expect(p_parser, T_END);
+}
+
+void grammar_definition(parser_t* p_parser)
+{
+    parser_expect(p_parser,T_VAR);
+    if (parser_peek(p_parser)->type == T_LPAR) {
+        grammar_fn_stmnt(p_parser);
+    } else {
+        grammar_expression(p_parser);
+        parser_expect(p_parser,T_END);
+    }
+}
+
+void grammar_expression(parser_t* p_parser)
+{
+    if (parser_accept(p_parser, T_LPAR)) {
+        grammar_expression(p_parser);
+        parser_accept(p_parser, T_RPAR);
+    } else if (parser_accept_str(p_parser, T_VAR, "if")) {
+        grammar_if_stmnt(p_parser);
+    } else if (parser_accept_str(p_parser, T_VAR, "fn")) {
+        grammar_fn_stmnt(p_parser);
+    } else if (parser_peek(p_parser)->type == T_VAR) {
+        parser_expect(p_parser, T_VAR);
+        if (parser_peek(p_parser)->type == T_LPAR) {
+            grammar_arglist(p_parser);
+        }
+    } else {
+        grammar_literal(p_parser);
+    }
+}
+
+void grammar_literal(parser_t* p_parser)
+{
+    switch (parser_peek(p_parser)->type)
+    {
+        case T_BOOL:
+        case T_CHAR:
+        case T_STRING:
+        case T_INT:
+        case T_FLOAT:
+            parser_accept(p_parser, parser_peek(p_parser)->type);
+            break;
+
+        default:
+            parser_error(p_parser, "Not a valid expression");
+            break;
+    }
+}
+
+void grammar_arglist(parser_t* p_parser)
+{
+    parser_expect(p_parser, T_LPAR);
+    while(parser_peek(p_parser)->type != T_RPAR) {
+        grammar_expression(p_parser);
+        if(parser_peek(p_parser)->type != T_RPAR)
+            parser_expect(p_parser, T_COMMA);
+    }
+    parser_expect(p_parser, T_RPAR);
+}
+
+void grammar_if_stmnt(parser_t* p_parser)
+{
+    grammar_expression(p_parser);
+    grammar_expression(p_parser);
+    parser_expect_str(p_parser,T_VAR,"else");
+    grammar_expression(p_parser);
+    parser_expect(p_parser,T_END);
+}
+
+void grammar_fn_stmnt(parser_t* p_parser)
+{
+    parser_expect(p_parser, T_LPAR);
+    while(parser_peek(p_parser)->type != T_RPAR) {
+        parser_expect(p_parser, T_VAR);
+        if(parser_peek(p_parser)->type != T_RPAR)
+            parser_expect(p_parser, T_COMMA);
+    }
+    parser_expect(p_parser, T_RPAR);
+    while(parser_peek(p_parser)->type != T_END) {
+        grammar_expression(p_parser);
+    }
+    parser_expect(p_parser, T_END);
+}
diff --git a/source/sclpl/grammar.h b/source/sclpl/grammar.h
new file mode 100644 (file)
index 0000000..3ac5088
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+  @file grammar.h
+  @brief Describes the grammar and parsing rules that form the SCLPL language.
+*/
+#ifndef GRAMMAR_H
+#define GRAMMAR_H
+
+#include "parser.h"
+
+void grammar_toplevel(parser_t* p_parser);
+
+void grammar_import(parser_t* p_parser);
+
+void grammar_definition(parser_t* p_parser);
+
+void grammar_expression(parser_t* p_parser);
+
+void grammar_literal(parser_t* p_parser);
+
+void grammar_arglist(parser_t* p_parser);
+
+void grammar_if_stmnt(parser_t* p_parser);
+
+void grammar_fn_stmnt(parser_t* p_parser);
+
+#endif /* GRAMMAR_H */
index 860c6c7c2f8c3089f29cae923d1caa9bc2238600..b354ac5f305781725b6e327ed0bf965c5b12d045 100644 (file)
-#include "scanner.h"
-#include "lexer.h"
-#include "opts.h"
 #include <stdio.h>
 #include <stdlib.h>
+#include "opts.h"
+#include "grammar.h"
 
-/*****************************************************************************/
-typedef struct {
-    lexer_t* p_lexer;
-    lex_tok_t* p_tok;
-} parser_t;
-
-lex_tok_t tok_eof = { T_END_FILE, NULL, 0, 0, NULL };
-
-parser_t* parser_new(char* p_prompt, FILE* input)
-{
-    parser_t* p_parser = (parser_t*)malloc(sizeof(parser_t));
-    p_parser->p_lexer = lexer_new(p_prompt, input);
-    p_parser->p_tok = NULL;
-    return p_parser;
-}
-
-void parser_fetch(parser_t* p_parser)
-{
-    p_parser->p_tok = lexer_read(p_parser->p_lexer);
-    if (NULL == p_parser->p_tok)
-        p_parser->p_tok = &tok_eof;
-}
-
-lex_tok_t* parser_peek(parser_t* p_parser)
-{
-    if (NULL == p_parser->p_tok)
-        parser_fetch(p_parser);
-    return p_parser->p_tok;
-}
-
-bool parser_eof(parser_t* p_parser) {
-    return (parser_peek(p_parser)->type == T_END_FILE);
-}
-
-void parser_error(parser_t* p_parser, const char* p_text)
-{
-    (void)p_parser;
-    fprintf(stderr,"Error: %s\n",p_text);
-    exit(1);
-}
-
-bool parser_accept(parser_t* p_parser, lex_tok_type_t type)
-{
-    bool ret = false;
-    if (parser_peek(p_parser)->type == type) {
-        p_parser->p_tok = NULL;
-        ret = true;
-    }
-    return ret;
-}
-
-bool parser_accept_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text)
-{
-    bool ret = false;
-    if ((parser_peek(p_parser)->type == type) && (0 == strcmp((char*)(p_parser->p_tok->value), p_text))) {
-        p_parser->p_tok = NULL;
-        ret = true;
-    }
-    return ret;
-}
-
-bool parser_expect(parser_t* p_parser, lex_tok_type_t type)
-{
-    bool ret = false;
-    if (parser_accept(p_parser, type)) {
-        ret = true;
-    } else {
-        parser_error(p_parser, "Unexpected token");
-    }
-    return ret;
-}
-
-bool parser_expect_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text)
-{
-    bool ret = false;
-    if (parser_accept_str(p_parser, type, p_text)) {
-        ret = true;
-    } else {
-        parser_error(p_parser, "Unexpected token");
-    }
-    return ret;
-}
-
-/*****************************************************************************/
-void parser_toplevel(parser_t* p_parser);
-void parser_import(parser_t* p_parser);
-void parser_definition(parser_t* p_parser);
-void parser_expression(parser_t* p_parser);
-void parser_literal(parser_t* p_parser);
-void parser_arglist(parser_t* p_parser);
-void parser_if_stmnt(parser_t* p_parser);
-void parser_fn_stmnt(parser_t* p_parser);
-
-void parser_toplevel(parser_t* p_parser)
-{
-    if (parser_accept_str(p_parser, T_VAR, "import"))
-        parser_import(p_parser);
-    else if (parser_accept_str(p_parser, T_VAR, "def"))
-        parser_definition(p_parser);
-    else if (p_parser->p_lexer->scanner->p_input == stdin)
-        parser_expression(p_parser);
-    else
-        parser_error(p_parser, "Unrecognized top-level form");
-}
-
-void parser_import(parser_t* p_parser)
-{
-    parser_expect(p_parser, T_VAR);
-    parser_expect(p_parser, T_END);
-}
-
-void parser_definition(parser_t* p_parser)
-{
-    parser_expect(p_parser,T_VAR);
-    if (parser_peek(p_parser)->type == T_LPAR) {
-        parser_fn_stmnt(p_parser);
-    } else {
-        parser_expression(p_parser);
-        parser_expect(p_parser,T_END);
-    }
-}
-
-void parser_expression(parser_t* p_parser)
-{
-    if (parser_accept(p_parser, T_LPAR)) {
-        parser_expression(p_parser);
-        parser_accept(p_parser, T_RPAR);
-    } else if (parser_accept_str(p_parser, T_VAR, "if")) {
-        parser_if_stmnt(p_parser);
-    } else if (parser_accept_str(p_parser, T_VAR, "fn")) {
-        parser_fn_stmnt(p_parser);
-    } else if (parser_peek(p_parser)->type == T_VAR) {
-        parser_expect(p_parser, T_VAR);
-        if (parser_peek(p_parser)->type == T_LPAR) {
-            parser_arglist(p_parser);
-        }
-    } else {
-        parser_literal(p_parser);
-    }
-}
-
-void parser_literal(parser_t* p_parser)
-{
-    switch (parser_peek(p_parser)->type)
-    {
-        case T_BOOL:
-        case T_CHAR:
-        case T_STRING:
-        case T_INT:
-        case T_FLOAT:
-            parser_accept(p_parser, parser_peek(p_parser)->type);
-            break;
-
-        default:
-            parser_error(p_parser, "Not a valid expression");
-            break;
-    }
-}
-
-void parser_arglist(parser_t* p_parser)
-{
-    parser_expect(p_parser, T_LPAR);
-    while(parser_peek(p_parser)->type != T_RPAR) {
-        parser_expression(p_parser);
-        if(parser_peek(p_parser)->type != T_RPAR)
-            parser_expect(p_parser, T_COMMA);
-    }
-    parser_expect(p_parser, T_RPAR);
-}
-
-void parser_if_stmnt(parser_t* p_parser)
-{
-    parser_expression(p_parser);
-    parser_expression(p_parser);
-    parser_expect_str(p_parser,T_VAR,"else");
-    parser_expression(p_parser);
-    parser_expect(p_parser,T_END);
-}
-
-void parser_fn_stmnt(parser_t* p_parser)
-{
-    parser_expect(p_parser, T_LPAR);
-    while(parser_peek(p_parser)->type != T_RPAR) {
-        parser_expect(p_parser, T_VAR);
-        if(parser_peek(p_parser)->type != T_RPAR)
-            parser_expect(p_parser, T_COMMA);
-    }
-    parser_expect(p_parser, T_RPAR);
-    while(parser_peek(p_parser)->type != T_END) {
-        parser_expression(p_parser);
-    }
-    parser_expect(p_parser, T_END);
-}
+/* Command Line Options
+ *****************************************************************************/
+OptionConfig_T Options_Config[] = {
+    { SHORT, (char*)"L",   (char*)"scan", 0, (char*)"Output the results of lexical analysis and quit"},
+    { SHORT, (char*)"P",   (char*)"scan", 0, (char*)"Output the results of parsing quit"},
+    { END,   (char*)NULL,  (char*)NULL,     0, (char*)NULL }
+};
 
 /* SCLPL Parser
  *****************************************************************************/
@@ -204,24 +17,19 @@ void parser_fn_stmnt(parser_t* p_parser)
 
     * Formalize grammar for parser
     * Paren for function application must be on same line as variable in REPL
-    * "end" and ';' must be equivalent
     * skip line on error and terminate after full program parse
     * skip line and print on error but do not terminate the REPL
-    * Phase out use of MPC
-    * Integrate libcds
-    * Integrate command line parsing
 
 */
-
 int main(int argc, char **argv) {
-    (void)argc;
-    (void)argv;
+    Result_T* results = OPTS_ParseOptions( Options_Config, argc, argv );
 
     parser_t* p_parser = parser_new(":> ", stdin);
     while(!parser_eof(p_parser)) {
-        parser_toplevel(p_parser);
+        grammar_toplevel(p_parser);
         puts("OK.");
     }
 
+    (void)results;
     return 0;
 }
diff --git a/source/sclpl/parser.c b/source/sclpl/parser.c
new file mode 100644 (file)
index 0000000..356cd68
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+  @file parser.c
+  @brief See header for details
+  $Revision$
+  $HeadURL$
+  */
+#include "parser.h"
+#include "vec.h"
+
+lex_tok_t tok_eof = { T_END_FILE, NULL, 0, 0, NULL };
+
+parser_t* parser_new(char* p_prompt, FILE* input)
+{
+    parser_t* p_parser = (parser_t*)malloc(sizeof(parser_t));
+    p_parser->p_lexer = lexer_new(p_prompt, input);
+    p_parser->p_tok = NULL;
+    p_parser->p_tok_buf = vec_new(0);
+    return p_parser;
+}
+
+void parser_fetch(parser_t* p_parser)
+{
+    p_parser->p_tok = lexer_read(p_parser->p_lexer);
+    if (NULL == p_parser->p_tok)
+        p_parser->p_tok = &tok_eof;
+}
+
+lex_tok_t* parser_peek(parser_t* p_parser)
+{
+    if (NULL == p_parser->p_tok)
+        parser_fetch(p_parser);
+    return p_parser->p_tok;
+}
+
+bool parser_eof(parser_t* p_parser) {
+    return (parser_peek(p_parser)->type == T_END_FILE);
+}
+
+void parser_error(parser_t* p_parser, const char* p_text)
+{
+    (void)p_parser;
+    fprintf(stderr,"Error: %s\n",p_text);
+    exit(1);
+}
+
+bool parser_accept(parser_t* p_parser, lex_tok_type_t type)
+{
+    bool ret = false;
+    if (parser_peek(p_parser)->type == type) {
+        p_parser->p_tok = NULL;
+        ret = true;
+    }
+    return ret;
+}
+
+bool parser_accept_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text)
+{
+    bool ret = false;
+    if ((parser_peek(p_parser)->type == type) && (0 == strcmp((char*)(p_parser->p_tok->value), p_text))) {
+        p_parser->p_tok = NULL;
+        ret = true;
+    }
+    return ret;
+}
+
+bool parser_expect(parser_t* p_parser, lex_tok_type_t type)
+{
+    bool ret = false;
+    if (parser_accept(p_parser, type)) {
+        ret = true;
+    } else {
+        parser_error(p_parser, "Unexpected token");
+    }
+    return ret;
+}
+
+bool parser_expect_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text)
+{
+    bool ret = false;
+    if (parser_accept_str(p_parser, type, p_text)) {
+        ret = true;
+    } else {
+        parser_error(p_parser, "Unexpected token");
+    }
+    return ret;
+}
diff --git a/source/sclpl/parser.h b/source/sclpl/parser.h
new file mode 100644 (file)
index 0000000..b427d7f
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+  @file parser.h
+  @brief A collection of helper functions for implementing recursive descent parsers.
+  $Revision$
+  $HeadURL$
+*/
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "lexer.h"
+#include "vec.h"
+
+typedef struct {
+    lexer_t* p_lexer;
+    lex_tok_t* p_tok;
+    vec_t* p_tok_buf;
+} parser_t;
+
+parser_t* parser_new(char* p_prompt, FILE* input);
+
+void parser_fetch(parser_t* p_parser);
+
+lex_tok_t* parser_peek(parser_t* p_parser);
+
+bool parser_eof(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);
+
+bool parser_accept_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text);
+
+bool parser_expect(parser_t* p_parser, lex_tok_type_t type);
+
+bool parser_expect_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text);
+
+#endif /* PARSER_H */