]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Checkin new parser files
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 19 Sep 2014 18:41:46 +0000 (14:41 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 19 Sep 2014 18:41:46 +0000 (14:41 -0400)
source/sclpl/ast.c
source/sclpl/ast.h
source/sclpl/grammar.c
source/sclpl/grammar.y
source/sclpl/lexer.c [new file with mode: 0644]
source/sclpl/lexer.h [new file with mode: 0644]
source/sclpl/main.c
source/sclpl/mpc.c
source/sclpl/scanner.c [new file with mode: 0644]
source/sclpl/scanner.h [new file with mode: 0644]

index a94aec4fad24eb3f2414a3a4a63ea776e4911fe8..e45739f2003d42b93aa3e1b911ee1da6d45309dd 100644 (file)
@@ -5,7 +5,6 @@
   $HeadURL$
 */
 #include "ast.h"
-#include <stdlib.h>
 
 void ast_free(void* p_obj)
 {
@@ -14,60 +13,59 @@ void ast_free(void* p_obj)
 
 ast_t* ast_new(ast_type_t type, void* value)
 {
-    ast_t* p_ast = (ast_t*)malloc(sizeof(ast_t));
-    p_ast->pos = NULL;
-    p_ast->type = type;
-    p_ast->value = value;
-    p_ast->children = NULL;
-    return p_ast;
+    (void)type;
+    (void)value;
+    return NULL;
 }
 
 void ast_set_pos(ast_t* p_ast, const char* file, size_t line, size_t col)
 {
-    pos_t* p_pos = (pos_t*)malloc(sizeof(pos_t));
-    p_pos->file = file;
-    p_pos->line = line;
-    p_pos->column = col;
-    p_ast->pos = p_pos;
+    (void)p_ast;
+    (void)file;
+    (void)line;
+    (void)col;
 }
 
 const pos_t* ast_get_pos(ast_t* p_ast)
 {
-    return p_ast->pos;
+    (void)p_ast;
+    return NULL;
 }
 
 void ast_set_type(ast_t* p_ast, ast_type_t type)
 {
-    p_ast->type = type;
+    (void)p_ast;
+    (void)type;
 }
 
 ast_type_t ast_get_type(ast_t* p_ast)
 {
-    return p_ast->type;
+    (void)p_ast;
+    return UNKNOWN;
 }
 
 void ast_set_value(ast_t* p_ast, void* value)
 {
-    p_ast->value = value;
+    (void)p_ast;
+    (void)value;
 }
 
 const void* ast_get_value(ast_t* p_ast)
 {
-    return p_ast->value;
+    (void)p_ast;
+    return NULL;
+}
+
+void ast_set_children(ast_t* p_ast, child_t* p_children)
+{
+    (void)p_ast;
+    (void)p_children;
 }
 
-ast_t* ast_add_child(ast_t* p_ast, ast_t* p_child)
+const child_t* ast_get_children(ast_t* p_ast)
 {
-    child_t* child = p_ast->children;
-    child_t* newchild = (child_t*)malloc(sizeof(child));
-    newchild->ast = p_ast;
-    newchild->next = NULL;
-    if (child != NULL) {
-        while (child->next != NULL) child = child->next;
-        child->next = newchild;
-    } else {
-        p_ast->children = newchild;
-    }
+    (void)p_ast;
+    return NULL;
 }
 
 ast_t* ast_map(const ast_t* p_ast, ast_map_fn_t p_fn)
@@ -76,4 +74,3 @@ ast_t* ast_map(const ast_t* p_ast, ast_map_fn_t p_fn)
     (void)p_fn;
     return NULL;
 }
-
index 12f11c6780217abe39804849860def83f15fdb70..366b7aba4939ec4789dbc6dbd03f1f1a16273ff9 100644 (file)
 typedef enum {
     BOOLEAN,
     INTEGER,
-    FLOAT,
     CHARACTER,
     STRING,
-    SEXPR,
     UNKNOWN
 } ast_type_t;
 
 typedef struct {
-    const char* file;
+    char* file;
     size_t line;
     size_t column;
 } pos_t;
@@ -58,9 +56,10 @@ void ast_set_value(ast_t* p_ast, void* value);
 
 const void* ast_get_value(ast_t* p_ast);
 
-ast_t* ast_add_child(ast_t* p_ast, ast_t* p_child);
+void ast_set_children(ast_t* p_ast, child_t* p_children);
 
-ast_t* ast_map(const ast_t* p_ast, ast_map_fn_t p_fn);
+const child_t* ast_get_children(ast_t* p_ast);
 
+ast_t* ast_map(const ast_t* p_ast, ast_map_fn_t p_fn);
 
 #endif /* AST_H */
index 0e5dc9334e7e147e5f18e43b9873020381040316..96105c15df61ba1ce8577b378c97167670468016 100644 (file)
@@ -1,36 +1,26 @@
-const char Grammar[] = \r
-""\r
-"program : /^/ <expr> /$/ ;"\r
-""\r
-"replexpr : <ws> <expr> /[^\\n]*\\n/ ;"\r
-""\r
-"expr : <sexpr> | <qexpr> | <radixnum> | <float> | <int> | <ch> | <str> | <bool> | <var> ;"\r
-""\r
-"sexpr : '(' (<ws> <expr> <ws>)* ')' ;"\r
-""\r
-"qexpr : ('\\'' | '`' | ',') <expr> ;"\r
-""\r
-"atom : <float> | <int> | <radixnum> | <ch> | <str> | <bool> | <var> ;"\r
-""\r
-"int : /[-+]?[0-9]+/ ;"\r
-""\r
-"float : /[-+]?[0-9]+\\.[0-9]+/ ;"\r
-""\r
-"radixnum : \"0b\" /[0-1]+/"\r
-"         | \"0o\" /[0-7]+/"\r
-"         | \"0d\" /[0-9]+/"\r
-"         | \"0x\" /[0-9a-fA-F]+/"\r
-"         ;"\r
-""\r
-"ch : '\\\\' (\"space\"|\"newline\"|\"return\"|\"tab\"|\"vtab\")"\r
-"   | '\\\\' /./"\r
-"   ;"\r
-""\r
-"str : '\"' /[^\"]*/ '\"' ;"\r
-""\r
-"bool : \"True\" | \"False\" ;"\r
-""\r
-"var : /[^() \\t\\r\\n#`'\"]+/ ;"\r
-""\r
-"ws : '#' /[^\\n]*\\n/ | /[ \\t\\r\\n]*/ ;"\r
-;\r
+const char Grammar[] = 
+""
+"token : /^/ <atom> /$/ ;"
+""
+"atom : <punc> | <radixnum> | <floating> | <integer> | <character> | <boolean> | <var> ;"
+""
+"punc : /['\"(){}\\[\\];,]/ ;"
+""
+"floating : /[-+]?[0-9]+\\.[0-9]+/ ;"
+""
+"integer : /[-+]?[0-9]+/ ;"
+""
+"radixnum : \"0b\" /[0-1]+/"
+"         | \"0o\" /[0-7]+/"
+"         | \"0d\" /[0-9]+/"
+"         | \"0x\" /[0-9a-fA-F]+/"
+"         ;"
+""
+"character : '\\\\' (\"space\"|\"newline\"|\"return\"|\"tab\"|\"vtab\")"
+"          | '\\\\' /./"
+"          ;"
+""
+"boolean : \"true\" | \"false\" ;"
+""
+"var : /.*/ ;"
+;
index 3ed52d938762b9edb92a39a91739e2367f0bcc01..cb195f504f524f5e4aeec566e51c1a0a79d325e9 100644 (file)
@@ -1,19 +1,13 @@
 
-program : /^/ <expr> /$/ ;
+token : /^/ <atom> /$/ ;
 
-replexpr : <ws> <expr> /[^\n]*\n/ ;
+atom : <punc> | <radixnum> | <floating> | <integer> | <character> | <boolean> | <var> ;
 
-expr : <sexpr> | <qexpr> | <radixnum> | <float> | <int> | <ch> | <str> | <bool> | <var> ;
+punc : /['"(){}\[\];,]/ ;
 
-sexpr : '(' (<ws> <expr> <ws>)* ')' ;
+floating : /[-+]?[0-9]+\.[0-9]+/ ;
 
-qexpr : ('\'' | '`' | ',') <expr> ;
-
-atom : <float> | <int> | <radixnum> | <ch> | <str> | <bool> | <var> ;
-
-int : /[-+]?[0-9]+/ ;
-
-float : /[-+]?[0-9]+\.[0-9]+/ ;
+integer : /[-+]?[0-9]+/ ;
 
 radixnum : "0b" /[0-1]+/
          | "0o" /[0-7]+/
@@ -21,14 +15,10 @@ radixnum : "0b" /[0-1]+/
          | "0x" /[0-9a-fA-F]+/
          ;
 
-ch : '\\' ("space"|"newline"|"return"|"tab"|"vtab")
-   | '\\' /./
-   ;
-
-str : '"' /[^"]*/ '"' ;
-
-bool : "True" | "False" ;
+character : '\\' ("space"|"newline"|"return"|"tab"|"vtab")
+          | '\\' /./
+          ;
 
-var : /[^() \t\r\n#`'"]+/ ;
+boolean : "true" | "false" ;
 
-ws : '#' /[^\n]*\n/ | /[ \t\r\n]*/ ;
+var : /.*/ ;
diff --git a/source/sclpl/lexer.c b/source/sclpl/lexer.c
new file mode 100644 (file)
index 0000000..04c92e4
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+  @file lexer.c
+  @brief See header for details
+  $Revision$
+  $HeadURL$
+  */
+#include "lexer.h"
+
+static lex_tok_t* lexer_translate(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_punc(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_radix(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_integer(mpc_ast_t* p_tok_ast, int base);
+static lex_tok_t* lexer_float(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_char(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_bool(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lexer_var(mpc_ast_t* p_tok_ast);
+static lex_tok_t* lex_tok_new(lex_tok_type_t type, void* val);
+static int read_radix(const mpc_ast_t* t);
+
+/* Grammar is auto generated into 'source/grammar.c' */
+extern const char Grammar[];
+
+lexer_t* lexer_new(char* p_prompt, FILE* p_input) {
+    lexer_t* p_lexer = (lexer_t*)malloc(sizeof(lexer_t));
+    /* Build the token parser */
+    mpc_parser_t* token     = mpc_new("token");
+    mpc_parser_t* atom      = mpc_new("atom");
+    mpc_parser_t* punc      = mpc_new("punc");
+    mpc_parser_t* floating  = mpc_new("floating");
+    mpc_parser_t* integer   = mpc_new("integer");
+    mpc_parser_t* radix_num = mpc_new("radixnum");
+    mpc_parser_t* character = mpc_new("character");
+    mpc_parser_t* boolean   = mpc_new("boolean");
+    mpc_parser_t* variable  = mpc_new("var");
+    mpca_lang(MPCA_LANG_DEFAULT, Grammar,
+        token, atom, punc, floating, integer, radix_num, character, boolean, variable, NULL);
+    /* Build the Lexer */
+    p_lexer->lexrule = token;
+    p_lexer->scanner = scanner_new(p_prompt, p_input);
+    return p_lexer;
+}
+
+lex_tok_t* lexer_read(lexer_t* p_lexer) {
+    mpc_result_t r;
+    lex_tok_t* p_tok = NULL;
+    char* text = scanner_read(p_lexer->scanner);
+    if (mpc_parse("<stdin>", text, p_lexer->lexrule, &r)) {
+        mpc_ast_print(((mpc_ast_t*)r.output)->children[1]);
+        p_tok = lexer_translate( ((mpc_ast_t*)r.output)->children[1] );
+        mpc_ast_delete(r.output);
+    } else {
+        mpc_err_print(r.error);
+        mpc_err_delete(r.error);
+    }
+    free(text);
+    return p_tok;
+}
+
+lex_tok_t* lexer_translate(mpc_ast_t* p_tok_ast) {
+    lex_tok_t* p_tok = (lex_tok_t*)malloc(sizeof(lex_tok_t));
+    if (0 == strncmp("atom|punc", p_tok_ast->tag, 9)) {
+        p_tok = lexer_punc(p_tok_ast);
+    } else if (0 == strncmp("radixnum", p_tok_ast->tag, 8)) {
+        p_tok = lexer_radix(p_tok_ast);
+    } else if (0 == strncmp("atom|integer", p_tok_ast->tag, 12)) {
+        p_tok = lexer_integer(p_tok_ast, 10);
+    } else if (0 == strncmp("atom|floating", p_tok_ast->tag, 13)) {
+        p_tok = lexer_float(p_tok_ast);
+    } else if (0 == strncmp("character", p_tok_ast->tag, 9)) {
+        p_tok = lexer_char(p_tok_ast);
+    } else if (0 == strncmp("atom|boolean", p_tok_ast->tag, 12)) {
+        p_tok = lexer_bool(p_tok_ast);
+    } else if (0 == strncmp("atom|var", p_tok_ast->tag, 8)) {
+        p_tok = lexer_var(p_tok_ast);
+    } else {
+        puts("unknown");
+    }
+    return p_tok;
+}
+
+lex_tok_t* lexer_punc(mpc_ast_t* p_tok_ast)
+{
+    lex_tok_t* p_tok = NULL;
+    switch (p_tok_ast->contents[0]) {
+        case '(': p_tok = lex_tok_new(LPAR,   NULL); break;
+        case ')': p_tok = lex_tok_new(RPAR,   NULL); break;
+        case '{': p_tok = lex_tok_new(LBRACE, NULL); break;
+        case '}': p_tok = lex_tok_new(RBRACE, NULL); break;
+        case '[': p_tok = lex_tok_new(LBRACK, NULL); break;
+        case ']': p_tok = lex_tok_new(RBRACK, NULL); break;
+        case ';': p_tok = lex_tok_new(END,    NULL); break;
+        case ',': p_tok = lex_tok_new(COMMA,  NULL); break;
+    }
+    return p_tok;
+}
+
+lex_tok_t* lexer_radix(mpc_ast_t* p_tok_ast)
+{
+    return lexer_integer(p_tok_ast->children[1], read_radix(p_tok_ast));
+}
+
+lex_tok_t* lexer_integer(mpc_ast_t* p_tok_ast, int base)
+{
+    long* p_int = (long*)malloc(sizeof(long));
+    errno = 0;
+    *p_int = strtol(p_tok_ast->contents, NULL, base);
+    assert(errno == 0);
+    return lex_tok_new(INT, p_int);
+}
+
+lex_tok_t* lexer_float(mpc_ast_t* p_tok_ast)
+{
+    double* p_dbl = (double*)malloc(sizeof(double));
+    errno = 0;
+    *p_dbl = strtod(p_tok_ast->contents, NULL);
+    assert(errno == 0);
+    return lex_tok_new(FLOAT, p_dbl);
+}
+
+lex_tok_t* lexer_char(mpc_ast_t* p_tok_ast)
+{
+    lex_tok_t* p_tok = NULL;
+    static const char* lookup_table[5] = {
+        " \0space",
+        "\n\0newline",
+        "\r\0return",
+        "\t\0tab",
+        "\v\0vtab"
+    };
+    if (strlen(p_tok_ast->contents) == 1) {
+        p_tok = lex_tok_new(CHAR, (void*)(p_tok_ast->contents[0]));
+    } else {
+        for(int i = 0; i < 5; i++) {
+            if (strcmp(p_tok_ast->contents, &(lookup_table[i][2]))) {
+                p_tok = lex_tok_new(CHAR, (void*)(lookup_table[i][0]));
+                break;
+            }
+        }
+    }
+    return p_tok;
+}
+
+lex_tok_t* lexer_bool(mpc_ast_t* p_tok_ast)
+{
+    return lex_tok_new(BOOL, (void*)((0==strcmp(p_tok_ast->contents,"True")) ? true : false));
+}
+
+lex_tok_t* lexer_var(mpc_ast_t* p_tok_ast)
+{
+    char* p_str = strdup(p_tok_ast->contents);
+    return lex_tok_new(VAR, p_str);
+}
+
+lex_tok_t* lex_tok_new(lex_tok_type_t type, void* val) {
+    lex_tok_t* p_tok = (lex_tok_t*)malloc(sizeof(lex_tok_t));
+    p_tok->type  = type;
+    p_tok->value = val;
+    return p_tok;
+}
+
+static int read_radix(const mpc_ast_t* t) {
+    switch( t->children[0]->contents[1] ) {
+        case 'b': return 2;
+        case 'o': return 8;
+        case 'd': return 10;
+        case 'h': return 16;
+        default:  return 10;
+    }
+}
diff --git a/source/sclpl/lexer.h b/source/sclpl/lexer.h
new file mode 100644 (file)
index 0000000..9233b91
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+  @file lexer.h
+  @brief TODO: Describe this file
+  $Revision$
+  $HeadURL$
+  */
+#ifndef LEXER_H
+#define LEXER_H
+
+#include "scanner.h"
+#include "mpc.h"
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+typedef struct {
+    mpc_parser_t* lexrule;
+    scanner_t* scanner;
+} lexer_t;
+
+typedef enum {
+    END, STRING, CHAR, INT, FLOAT, BOOL, LBRACE, RBRACE, LBRACK, RBRACK, LPAR,
+    RPAR, COMMA, VAR
+} lex_tok_type_t;
+
+typedef struct {
+    lex_tok_type_t type;
+    const char* file;
+    size_t line;
+    size_t column;
+    void* value;
+} lex_tok_t;
+
+lexer_t* lexer_new(char* p_prompt, FILE* p_input);
+
+lex_tok_t* lexer_read(lexer_t* p_lexer);
+
+#endif /* LEXER_H */
index a739c37fb8d5ec45bef372c38063fdcfa2823cca..430c26007646c0353dc42a71d29b39ebef0635b9 100644 (file)
 #include "mpc.h"
-#include "ast.h"
+#include "scanner.h"
+#include "lexer.h"
 #include <stdio.h>
-#include <assert.h>
 
-/* SCLPL Parser
- *****************************************************************************/
-/* Grammar is auto generated into 'source/grammar.c' */
-extern const char Grammar[];
+/*****************************************************************************/
+typedef struct {
+    lexer_t* p_lexer;
+    lex_tok_t* p_tok;
+} parser_t;
 
-static ast_t* read_sexpr(const mpc_ast_t* t) {
-    (void)t;
-    return 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;
 }
 
-static ast_t* read_qexpr(const mpc_ast_t* t) {
-    (void)t;
-    return NULL;
+void parser_fetch(parser_t* p_parser)
+{
+    p_parser->p_tok = lexer_read(p_parser->p_lexer);
 }
 
-static ast_t* read_char(const mpc_ast_t* t) {
-    (void)t;
-    return NULL;
+lex_tok_t* parser_peek(parser_t* p_parser)
+{
+    if (NULL == p_parser->p_tok)
+        parser_fetch(p_parser);
+    return p_parser->p_tok;
 }
 
-static ast_t* read_string(const mpc_ast_t* t) {
-    (void)t;
-    return NULL;
+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;
 }
 
-static ast_t* read_var(const mpc_ast_t* t) {
-    (void)t;
-    return NULL;
+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;
 }
 
-static ast_t* read_bool(const mpc_ast_t* t) {
-    (void)t;
-    return NULL;
+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;
 }
 
-static ast_t* read_float(const mpc_ast_t* t) {
-    double* p_dbl = (double*)malloc(sizeof(double));
-    ast_t* p_ast = ast_new(FLOAT, p_dbl);
-    ast_set_pos(p_ast, "<stdin>", t->state.row, t->state.col);
-    errno = 0;
-    *p_dbl = strtod(t->contents, NULL);
-    assert(errno == 0);
-    return p_ast;
+/*****************************************************************************/
+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, VAR, "import"))
+        parser_import(p_parser);
+    else if (parser_accept_str(p_parser, 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");
 }
 
-static ast_t* read_int(const mpc_ast_t* t, int base) {
-    long* p_int = (long*)malloc(sizeof(long));
-    printf("reading int with base: %d\n", base);
-    ast_t* p_ast = ast_new(INTEGER, p_int);
-    ast_set_pos(p_ast, "<stdin>", t->state.row, t->state.col);
-    errno = 0;
-    *p_int = strtol(t->contents, NULL, base);
-    assert(errno == 0);
-    return p_ast;
+void parser_import(parser_t* p_parser)
+{
+    parser_expect(p_parser, VAR);
+    parser_expect(p_parser, END);
 }
 
-static int read_radix(const mpc_ast_t* t) {
-    switch( t->children[0]->contents[1] ) {
-        case 'b': return 2;
-        case 'o': return 8;
-        case 'd': return 10;
-        case 'x': return 16;
-        default:  return 10;
+void parser_definition(parser_t* p_parser)
+{
+    parser_expect(p_parser,VAR);
+    if (parser_peek(p_parser)->type == LPAR) {
+        parser_fn_stmnt(p_parser);
+    } else {
+        parser_expression(p_parser);
+        parser_expect(p_parser,END);
     }
 }
 
-ast_t* format_expr_ast(mpc_ast_t* expr) {
-    ast_t* p_ast = NULL;
-
-    /* Handle the current node */
-    if (0 == strcmp("sexpr|>", expr->tag)) {
-    } else if (0 == strcmp("qexpr|>", expr->tag)) {
-    } else if (0 == strcmp("radixnum|>", expr->tag)) {
-        p_ast = read_int(expr->children[1], read_radix(expr));
-        printf("int: %d\n", *((long*)p_ast->value));
-    } else if (0 == strcmp("expr|float|regex", expr->tag)) {
-        p_ast = read_float(expr);
-        printf("double: %f\n", *((double*)p_ast->value));
-    } else if (0 == strcmp("expr|int|regex", expr->tag)) {
-        p_ast = read_int(expr,10);
-        printf("int: %d\n", *((long*)p_ast->value));
-    } else if (0 == strcmp("ch|>", expr->tag)) {
-    } else if (0 == strcmp("str|>", expr->tag)) {
-    } else if (0 == strcmp("expr|bool|str", expr->tag)) {
-    } else if (0 == strcmp("expr|var|regex", expr->tag)) {
+void parser_expression(parser_t* p_parser)
+{
+    if (parser_accept(p_parser, LPAR)) {
+        parser_expression(p_parser);
+        parser_accept(p_parser, RPAR);
+    } else if (parser_accept_str(p_parser, VAR, "if")) {
+        parser_if_stmnt(p_parser);
+    } else if (parser_accept_str(p_parser, VAR, "fn")) {
+        parser_fn_stmnt(p_parser);
+    } else if (parser_peek(p_parser)->type == VAR) {
+        parser_expect(p_parser, VAR);
+        if (parser_peek(p_parser)->type == LPAR) {
+            parser_arglist(p_parser);
+        }
     } else {
-        printf("unknown tag: '%s'\n", expr->tag);
-        free(p_ast->pos);
-        free(p_ast);
-        p_ast = NULL;
+        parser_literal(p_parser);
+    }
+}
+
+void parser_literal(parser_t* p_parser)
+{
+    switch (parser_peek(p_parser)->type)
+    {
+        case BOOL:
+        case CHAR:
+        case STRING:
+        case INT:
+        case 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, LPAR);
+    while(parser_peek(p_parser)->type != RPAR) {
+        parser_expression(p_parser);
+        if(parser_peek(p_parser)->type != RPAR)
+            parser_expect(p_parser, COMMA);
+    }
+    parser_expect(p_parser, RPAR);
+}
 
-    return p_ast;
+void parser_if_stmnt(parser_t* p_parser)
+{
+    parser_expression(p_parser);
+    parser_expression(p_parser);
+    parser_expect_str(p_parser,VAR,"else");
+    parser_expression(p_parser);
+    parser_expect(p_parser,END);
+}
+
+void parser_fn_stmnt(parser_t* p_parser)
+{
+    parser_expect(p_parser, LPAR);
+    while(parser_peek(p_parser)->type != RPAR) {
+        parser_expect(p_parser, VAR);
+        if(parser_peek(p_parser)->type != RPAR)
+            parser_expect(p_parser, COMMA);
+    }
+    parser_expect(p_parser, RPAR);
+    while(parser_peek(p_parser)->type != END) {
+        parser_expression(p_parser);
+    }
+    parser_expect(p_parser, END);
 }
 
+/* SCLPL Parser
+ *****************************************************************************/
+/* TODO:
+
+    * Gracefully handle EOF
+    * 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) {
-    mpc_parser_t* ReplExpr = mpc_new("replexpr");
-    mpc_parser_t* Expr = mpc_new("expr");
-    mpc_parser_t* SExpr = mpc_new("sexpr");
-    mpc_parser_t* QExpr = mpc_new("qexpr");
-    mpc_parser_t* Atom = mpc_new("atom");
-    mpc_parser_t* Int = mpc_new("int");
-    mpc_parser_t* Float = mpc_new("float");
-    mpc_parser_t* Radix = mpc_new("radixnum");
-    mpc_parser_t* Char = mpc_new("ch");
-    mpc_parser_t* String = mpc_new("str");
-    mpc_parser_t* Bool = mpc_new("bool");
-    mpc_parser_t* Var = mpc_new("var");
-    mpc_parser_t* WS = mpc_new("ws");
-    mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE, Grammar,
-        ReplExpr, Expr, SExpr, QExpr, Atom, Int, Float, Radix, Char, String, Bool, Var, WS, NULL);
-    while(!feof(stdin)) {
-        mpc_result_t r;
-        printf(":> ");
-        if (mpc_parse_pipe("<stdin>", stdin, ReplExpr, &r)) {
-            mpc_ast_t* expr = (mpc_ast_t*)(((mpc_ast_t*)r.output)->children[1]);
-            mpc_ast_print(expr);
-            format_expr_ast(expr);
-            mpc_ast_delete(r.output);
-        } else {
-            mpc_err_print(r.error);
-            mpc_err_delete(r.error);
-            while('\n' != fgetc(stdin)){}
-        }
+    (void)argc;
+    (void)argv;
+
+    //scanner_t* p_scanner = scanner_new(":> ", stdin);
+    //while(!scanner_eof(p_scanner)) {
+    //    printf("TOK: '%s'\n", scanner_read(p_scanner) );
+    //    puts("OK.");
+    //}
+
+    parser_t* p_parser = parser_new(":> ", stdin);
+    while(true) {
+        parser_toplevel(p_parser);
+        puts("OK.");
     }
-    mpc_cleanup(13, ReplExpr, Expr, SExpr, QExpr, Atom, Int, Float, Radix, Char, String, Bool, Var, WS);
+
     return 0;
 }
index 4e0d8cf4d005dc0c280c462ef08be7526f1dcb79..5b0c5c46c2da89c3ff2a98dc2a226817e20f4e60 100644 (file)
@@ -63,7 +63,7 @@ void mpc_err_delete(mpc_err_t *x) {
   for (i = 0; i < x->expected_num; i++) {\r
     free(x->expected[i]);\r
   }\r
-\r
+  \r
   free(x->expected);\r
   free(x->filename);\r
   free(x->failure);\r
@@ -71,26 +71,26 @@ void mpc_err_delete(mpc_err_t *x) {
 }\r
 \r
 static int mpc_err_contains_expected(mpc_err_t *x, char *expected) {\r
-\r
+  \r
   int i;\r
   for (i = 0; i < x->expected_num; i++) {\r
     if (strcmp(x->expected[i], expected) == 0) { return 1; }\r
   }\r
-\r
+  \r
   return 0;\r
 }\r
 \r
 static void mpc_err_add_expected(mpc_err_t *x, char *expected) {\r
-\r
+  \r
   x->expected_num++;\r
   x->expected = realloc(x->expected, sizeof(char*) * x->expected_num);\r
   x->expected[x->expected_num-1] = malloc(strlen(expected) + 1);\r
   strcpy(x->expected[x->expected_num-1], expected);\r
-\r
+  \r
 }\r
 \r
 static void mpc_err_clear_expected(mpc_err_t *x, char *expected) {\r
-\r
+  \r
   int i;\r
   for (i = 0; i < x->expected_num; i++) {\r
     free(x->expected[i]);\r
@@ -99,7 +99,7 @@ static void mpc_err_clear_expected(mpc_err_t *x, char *expected) {
   x->expected = realloc(x->expected, sizeof(char*) * x->expected_num);\r
   x->expected[0] = malloc(strlen(expected) + 1);\r
   strcpy(x->expected[0], expected);\r
-\r
+  \r
 }\r
 \r
 void mpc_err_print(mpc_err_t *x) {\r
@@ -125,13 +125,13 @@ void mpc_err_string_cat(char *buffer, int *pos, int *max, char *fmt, ...) {
 static char char_unescape_buffer[3];\r
 \r
 static char *mpc_err_char_unescape(char c) {\r
-\r
+  \r
   char_unescape_buffer[0] = '\'';\r
   char_unescape_buffer[1] = ' ';\r
   char_unescape_buffer[2] = '\'';\r
-\r
+  \r
   switch (c) {\r
-\r
+    \r
     case '\a': return "bell";\r
     case '\b': return "backspace";\r
     case '\f': return "formfeed";\r
@@ -145,48 +145,48 @@ static char *mpc_err_char_unescape(char c) {
       char_unescape_buffer[1] = c;\r
       return char_unescape_buffer;\r
   }\r
-\r
+  \r
 }\r
 \r
 char *mpc_err_string(mpc_err_t *x) {\r
-\r
+  \r
   char *buffer = calloc(1, 1024);\r
   int max = 1023;\r
-  int pos = 0;\r
+  int pos = 0; \r
   int i;\r
-\r
+  \r
   if (x->failure) {\r
     mpc_err_string_cat(buffer, &pos, &max,\r
-    "%s: error: %s\n",\r
+    "%s: error: %s\n", \r
       x->filename, x->failure);\r
     return buffer;\r
   }\r
-\r
-  mpc_err_string_cat(buffer, &pos, &max,\r
+  \r
+  mpc_err_string_cat(buffer, &pos, &max, \r
     "%s:%i:%i: error: expected ", x->filename, x->state.row+1, x->state.col+1);\r
-\r
+  \r
   if (x->expected_num == 0) { mpc_err_string_cat(buffer, &pos, &max, "ERROR: NOTHING EXPECTED"); }\r
   if (x->expected_num == 1) { mpc_err_string_cat(buffer, &pos, &max, "%s", x->expected[0]); }\r
   if (x->expected_num >= 2) {\r
-\r
+  \r
     for (i = 0; i < x->expected_num-2; i++) {\r
       mpc_err_string_cat(buffer, &pos, &max, "%s, ", x->expected[i]);\r
-    }\r
-\r
-    mpc_err_string_cat(buffer, &pos, &max, "%s or %s",\r
-      x->expected[x->expected_num-2],\r
+    } \r
+    \r
+    mpc_err_string_cat(buffer, &pos, &max, "%s or %s", \r
+      x->expected[x->expected_num-2], \r
       x->expected[x->expected_num-1]);\r
   }\r
-\r
+  \r
   mpc_err_string_cat(buffer, &pos, &max, " at ");\r
   mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->recieved));\r
   mpc_err_string_cat(buffer, &pos, &max, "\n");\r
-\r
+  \r
   return realloc(buffer, strlen(buffer) + 1);\r
 }\r
 \r
 static mpc_err_t *mpc_err_or(mpc_err_t** x, int n) {\r
-\r
+  \r
   int i, j;\r
   mpc_err_t *e = malloc(sizeof(mpc_err_t));\r
   e->state = mpc_state_invalid();\r
@@ -195,32 +195,32 @@ static mpc_err_t *mpc_err_or(mpc_err_t** x, int n) {
   e->failure = NULL;\r
   e->filename = malloc(strlen(x[0]->filename)+1);\r
   strcpy(e->filename, x[0]->filename);\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
     if (x[i]->state.pos > e->state.pos) { e->state = x[i]->state; }\r
   }\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
-\r
+    \r
     if (x[i]->state.pos < e->state.pos) { continue; }\r
-\r
+    \r
     if (x[i]->failure) {\r
       e->failure = malloc(strlen(x[i]->failure)+1);\r
       strcpy(e->failure, x[i]->failure);\r
       break;\r
     }\r
-\r
+    \r
     e->recieved = x[i]->recieved;\r
-\r
+    \r
     for (j = 0; j < x[i]->expected_num; j++) {\r
       if (!mpc_err_contains_expected(e, x[i]->expected[j])) { mpc_err_add_expected(e, x[i]->expected[j]); }\r
     }\r
   }\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
     mpc_err_delete(x[i]);\r
   }\r
-\r
+  \r
   return e;\r
 }\r
 \r
@@ -229,20 +229,20 @@ static mpc_err_t *mpc_err_repeat(mpc_err_t *x, const char *prefix) {
   int i;\r
   char *expect = malloc(strlen(prefix) + 1);\r
   strcpy(expect, prefix);\r
-\r
+  \r
   if (x->expected_num == 1) {\r
     expect = realloc(expect, strlen(expect) + strlen(x->expected[0]) + 1);\r
     strcat(expect, x->expected[0]);\r
   }\r
-\r
+  \r
   if (x->expected_num > 1) {\r
-\r
+  \r
     for (i = 0; i < x->expected_num-2; i++) {\r
       expect = realloc(expect, strlen(expect) + strlen(x->expected[i]) + strlen(", ") + 1);\r
       strcat(expect, x->expected[i]);\r
       strcat(expect, ", ");\r
     }\r
-\r
+    \r
     expect = realloc(expect, strlen(expect) + strlen(x->expected[x->expected_num-2]) + strlen(" or ") + 1);\r
     strcat(expect, x->expected[x->expected_num-2]);\r
     strcat(expect, " or ");\r
@@ -250,10 +250,10 @@ static mpc_err_t *mpc_err_repeat(mpc_err_t *x, const char *prefix) {
     strcat(expect, x->expected[x->expected_num-1]);\r
 \r
   }\r
-\r
+  \r
   mpc_err_clear_expected(x, expect);\r
   free(expect);\r
-\r
+  \r
   return x;\r
 \r
 }\r
@@ -277,24 +277,24 @@ static mpc_err_t *mpc_err_count(mpc_err_t *x, int n) {
 */\r
 \r
 /*\r
-** In mpc the input type has three modes of\r
+** In mpc the input type has three modes of \r
 ** operation: String, File and Pipe.\r
 **\r
-** String is easy. The whole contents are\r
+** String is easy. The whole contents are \r
 ** loaded into a buffer and scanned through.\r
-** The cursor can jump around at will making\r
+** The cursor can jump around at will making \r
 ** backtracking easy.\r
 **\r
 ** The second is a File which is also somewhat\r
-** easy. The contents are never loaded into\r
+** easy. The contents are never loaded into \r
 ** memory but backtracking can still be achieved\r
 ** by seeking in the file at different positions.\r
 **\r
 ** The final mode is Pipe. This is the difficult\r
-** one. As we assume pipes cannot be seeked - and\r
-** only support a single character lookahead at\r
-** any point, when the input is marked for a\r
-** potential backtracking we start buffering any\r
+** one. As we assume pipes cannot be seeked - and \r
+** only support a single character lookahead at \r
+** any point, when the input is marked for a \r
+** potential backtracking we start buffering any \r
 ** input.\r
 **\r
 ** This means that if we are requested to seek\r
@@ -316,102 +316,102 @@ enum {
 typedef struct {\r
 \r
   int type;\r
-  char *filename;\r
+  char *filename;  \r
   mpc_state_t state;\r
-\r
+  \r
   char *string;\r
   char *buffer;\r
   FILE *file;\r
-\r
+  \r
   int backtrack;\r
   int marks_num;\r
   mpc_state_t* marks;\r
   char* lasts;\r
-\r
+  \r
   char last;\r
-\r
+  \r
 } mpc_input_t;\r
 \r
 static mpc_input_t *mpc_input_new_string(const char *filename, const char *string) {\r
 \r
   mpc_input_t *i = malloc(sizeof(mpc_input_t));\r
-\r
+  \r
   i->filename = malloc(strlen(filename) + 1);\r
   strcpy(i->filename, filename);\r
   i->type = MPC_INPUT_STRING;\r
-\r
+  \r
   i->state = mpc_state_new();\r
-\r
+  \r
   i->string = malloc(strlen(string) + 1);\r
   strcpy(i->string, string);\r
   i->buffer = NULL;\r
   i->file = NULL;\r
-\r
+  \r
   i->backtrack = 1;\r
   i->marks_num = 0;\r
   i->marks = NULL;\r
   i->lasts = NULL;\r
 \r
   i->last = '\0';\r
-\r
+  \r
   return i;\r
 }\r
 \r
 static mpc_input_t *mpc_input_new_pipe(const char *filename, FILE *pipe) {\r
 \r
   mpc_input_t *i = malloc(sizeof(mpc_input_t));\r
-\r
+  \r
   i->filename = malloc(strlen(filename) + 1);\r
   strcpy(i->filename, filename);\r
-\r
+  \r
   i->type = MPC_INPUT_PIPE;\r
   i->state = mpc_state_new();\r
-\r
+  \r
   i->string = NULL;\r
   i->buffer = NULL;\r
   i->file = pipe;\r
-\r
+  \r
   i->backtrack = 1;\r
   i->marks_num = 0;\r
   i->marks = NULL;\r
   i->lasts = NULL;\r
-\r
+  \r
   i->last = '\0';\r
-\r
+  \r
   return i;\r
-\r
+  \r
 }\r
 \r
 static mpc_input_t *mpc_input_new_file(const char *filename, FILE *file) {\r
-\r
+  \r
   mpc_input_t *i = malloc(sizeof(mpc_input_t));\r
-\r
+  \r
   i->filename = malloc(strlen(filename) + 1);\r
   strcpy(i->filename, filename);\r
   i->type = MPC_INPUT_FILE;\r
   i->state = mpc_state_new();\r
-\r
+  \r
   i->string = NULL;\r
   i->buffer = NULL;\r
   i->file = file;\r
-\r
+  \r
   i->backtrack = 1;\r
   i->marks_num = 0;\r
   i->marks = NULL;\r
   i->lasts = NULL;\r
-\r
+  \r
   i->last = '\0';\r
-\r
+  \r
   return i;\r
 }\r
 \r
 static void mpc_input_delete(mpc_input_t *i) {\r
-\r
+  \r
   free(i->filename);\r
-\r
+  \r
   if (i->type == MPC_INPUT_STRING) { free(i->string); }\r
   if (i->type == MPC_INPUT_PIPE) { free(i->buffer); }\r
-\r
+  \r
   free(i->marks);\r
   free(i->lasts);\r
   free(i);\r
@@ -421,47 +421,47 @@ static void mpc_input_backtrack_disable(mpc_input_t *i) { i->backtrack--; }
 static void mpc_input_backtrack_enable(mpc_input_t *i) { i->backtrack++; }\r
 \r
 static void mpc_input_mark(mpc_input_t *i) {\r
-\r
+  \r
   if (i->backtrack < 1) { return; }\r
-\r
+  \r
   i->marks_num++;\r
   i->marks = realloc(i->marks, sizeof(mpc_state_t) * i->marks_num);\r
   i->lasts = realloc(i->lasts, sizeof(char) * i->marks_num);\r
   i->marks[i->marks_num-1] = i->state;\r
   i->lasts[i->marks_num-1] = i->last;\r
-\r
+  \r
   if (i->type == MPC_INPUT_PIPE && i->marks_num == 1) {\r
     i->buffer = calloc(1, 1);\r
   }\r
-\r
+  \r
 }\r
 \r
 static void mpc_input_unmark(mpc_input_t *i) {\r
-\r
+  \r
   if (i->backtrack < 1) { return; }\r
-\r
+  \r
   i->marks_num--;\r
   i->marks = realloc(i->marks, sizeof(mpc_state_t) * i->marks_num);\r
   i->lasts = realloc(i->lasts, sizeof(char) * i->marks_num);\r
-\r
+  \r
   if (i->type == MPC_INPUT_PIPE && i->marks_num == 0) {\r
     free(i->buffer);\r
     i->buffer = NULL;\r
   }\r
-\r
+  \r
 }\r
 \r
 static void mpc_input_rewind(mpc_input_t *i) {\r
-\r
+  \r
   if (i->backtrack < 1) { return; }\r
-\r
+  \r
   i->state = i->marks[i->marks_num-1];\r
   i->last  = i->lasts[i->marks_num-1];\r
-\r
+  \r
   if (i->type == MPC_INPUT_FILE) {\r
     fseek(i->file, i->state.pos, SEEK_SET);\r
   }\r
-\r
+  \r
   mpc_input_unmark(i);\r
 }\r
 \r
@@ -481,17 +481,17 @@ static int mpc_input_terminated(mpc_input_t *i) {
 }\r
 \r
 static char mpc_input_getc(mpc_input_t *i) {\r
-\r
+  \r
   char c = '\0';\r
-\r
+  \r
   switch (i->type) {\r
-\r
+    \r
     case MPC_INPUT_STRING: return i->string[i->state.pos];\r
     case MPC_INPUT_FILE: c = fgetc(i->file); return c;\r
     case MPC_INPUT_PIPE:\r
-\r
+    \r
       if (!i->buffer) { c = getc(i->file); return c; }\r
-\r
+      \r
       if (i->buffer && mpc_input_buffer_in_range(i)) {\r
         c = mpc_input_buffer_get(i);\r
         return c;\r
@@ -499,34 +499,34 @@ static char mpc_input_getc(mpc_input_t *i) {
         c = getc(i->file);\r
         return c;\r
       }\r
-\r
+    \r
     default: return c;\r
   }\r
 }\r
 \r
 static char mpc_input_peekc(mpc_input_t *i) {\r
-\r
+  \r
   char c = '\0';\r
-\r
+  \r
   switch (i->type) {\r
     case MPC_INPUT_STRING: return i->string[i->state.pos];\r
-    case MPC_INPUT_FILE:\r
-\r
+    case MPC_INPUT_FILE: \r
+      \r
       c = fgetc(i->file);\r
       if (feof(i->file)) { return '\0'; }\r
-\r
+      \r
       fseek(i->file, -1, SEEK_CUR);\r
       return c;\r
-\r
+    \r
     case MPC_INPUT_PIPE:\r
-\r
+      \r
       if (!i->buffer) {\r
         c = getc(i->file);\r
         if (feof(i->file)) { return '\0'; }\r
         ungetc(c, i->file);\r
         return c;\r
       }\r
-\r
+      \r
       if (i->buffer && mpc_input_buffer_in_range(i)) {\r
         return mpc_input_buffer_get(i);\r
       } else {\r
@@ -535,10 +535,10 @@ static char mpc_input_peekc(mpc_input_t *i) {
         ungetc(c, i->file);\r
         return c;\r
       }\r
-\r
+    \r
     default: return c;\r
   }\r
-\r
+  \r
 }\r
 \r
 static int mpc_input_failure(mpc_input_t *i, char c) {\r
@@ -547,46 +547,46 @@ static int mpc_input_failure(mpc_input_t *i, char c) {
     case MPC_INPUT_STRING: break;\r
     case MPC_INPUT_FILE: fseek(i->file, -1, SEEK_CUR); break;\r
     case MPC_INPUT_PIPE:\r
-\r
+      \r
       if (!i->buffer) { ungetc(c, i->file); break; }\r
-\r
+      \r
       if (i->buffer && mpc_input_buffer_in_range(i)) {\r
         break;\r
       } else {\r
-        ungetc(c, i->file);\r
+        ungetc(c, i->file); \r
       }\r
-\r
+      \r
   }\r
-\r
+  \r
   return 0;\r
 }\r
 \r
 static int mpc_input_success(mpc_input_t *i, char c, char **o) {\r
-\r
+  \r
   if (i->type == MPC_INPUT_PIPE &&\r
       i->buffer &&\r
       !mpc_input_buffer_in_range(i)) {\r
-\r
+    \r
     i->buffer = realloc(i->buffer, strlen(i->buffer) + 2);\r
     i->buffer[strlen(i->buffer) + 1] = '\0';\r
     i->buffer[strlen(i->buffer) + 0] = c;\r
   }\r
-\r
+  \r
   i->last = c;\r
   i->state.pos++;\r
   i->state.col++;\r
-\r
+  \r
   if (c == '\n') {\r
     i->state.col = 0;\r
     i->state.row++;\r
   }\r
-\r
+  \r
   if (o) {\r
     (*o) = malloc(2);\r
     (*o)[0] = c;\r
     (*o)[1] = '\0';\r
   }\r
-\r
+  \r
   return 1;\r
 }\r
 \r
@@ -605,29 +605,29 @@ static int mpc_input_char(mpc_input_t *i, char c, char **o) {
 static int mpc_input_range(mpc_input_t *i, char c, char d, char **o) {\r
   char x = mpc_input_getc(i);\r
   if (mpc_input_terminated(i)) { return 0; }\r
-  return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);\r
+  return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);  \r
 }\r
 \r
 static int mpc_input_oneof(mpc_input_t *i, const char *c, char **o) {\r
   char x = mpc_input_getc(i);\r
   if (mpc_input_terminated(i)) { return 0; }\r
-  return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);\r
+  return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);  \r
 }\r
 \r
 static int mpc_input_noneof(mpc_input_t *i, const char *c, char **o) {\r
   char x = mpc_input_getc(i);\r
   if (mpc_input_terminated(i)) { return 0; }\r
-  return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);\r
+  return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);  \r
 }\r
 \r
 static int mpc_input_satisfy(mpc_input_t *i, int(*cond)(char), char **o) {\r
   char x = mpc_input_getc(i);\r
   if (mpc_input_terminated(i)) { return 0; }\r
-  return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);\r
+  return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x);  \r
 }\r
 \r
 static int mpc_input_string(mpc_input_t *i, const char *c, char **o) {\r
-\r
+  \r
   char *co = NULL;\r
   const char *x = c;\r
 \r
@@ -642,7 +642,7 @@ static int mpc_input_string(mpc_input_t *i, const char *c, char **o) {
     x++;\r
   }\r
   mpc_input_unmark(i);\r
-\r
+  \r
   *o = malloc(strlen(c) + 1);\r
   strcpy(*o, c);\r
   return 1;\r
@@ -665,7 +665,7 @@ enum {
   MPC_TYPE_EXPECT    = 5,\r
   MPC_TYPE_ANCHOR    = 6,\r
   MPC_TYPE_STATE     = 7,\r
-\r
+  \r
   MPC_TYPE_ANY       = 8,\r
   MPC_TYPE_SINGLE    = 9,\r
   MPC_TYPE_ONEOF     = 10,\r
@@ -673,7 +673,7 @@ enum {
   MPC_TYPE_RANGE     = 12,\r
   MPC_TYPE_SATISFY   = 13,\r
   MPC_TYPE_STRING    = 14,\r
-\r
+  \r
   MPC_TYPE_APPLY     = 15,\r
   MPC_TYPE_APPLY_TO  = 16,\r
   MPC_TYPE_PREDICT   = 17,\r
@@ -682,7 +682,7 @@ enum {
   MPC_TYPE_MANY      = 20,\r
   MPC_TYPE_MANY1     = 21,\r
   MPC_TYPE_COUNT     = 22,\r
-\r
+  \r
   MPC_TYPE_OR        = 23,\r
   MPC_TYPE_AND       = 24\r
 };\r
@@ -743,26 +743,26 @@ typedef struct {
   int results_slots;\r
   mpc_result_t *results;\r
   int *returns;\r
-\r
+  \r
   mpc_err_t *err;\r
-\r
+  \r
 } mpc_stack_t;\r
 \r
 static mpc_stack_t *mpc_stack_new(const char *filename) {\r
   mpc_stack_t *s = malloc(sizeof(mpc_stack_t));\r
-\r
+  \r
   s->parsers_num = 0;\r
   s->parsers_slots = 0;\r
   s->parsers = NULL;\r
   s->states = NULL;\r
-\r
+  \r
   s->results_num = 0;\r
   s->results_slots = 0;\r
   s->results = NULL;\r
   s->returns = NULL;\r
-\r
+  \r
   s->err = mpc_err_fail(filename, mpc_state_invalid(), "Unknown Error");\r
-\r
+  \r
   return s;\r
 }\r
 \r
@@ -775,7 +775,7 @@ static void mpc_stack_err(mpc_stack_t *s, mpc_err_t* e) {
 \r
 static int mpc_stack_terminate(mpc_stack_t *s, mpc_result_t *r) {\r
   int success = s->returns[0];\r
-\r
+  \r
   if (success) {\r
     r->output = s->results[0].output;\r
     mpc_err_delete(s->err);\r
@@ -783,13 +783,13 @@ static int mpc_stack_terminate(mpc_stack_t *s, mpc_result_t *r) {
     mpc_stack_err(s, s->results[0].error);\r
     r->error = s->err;\r
   }\r
-\r
+  \r
   free(s->parsers);\r
   free(s->states);\r
   free(s->results);\r
   free(s->returns);\r
   free(s);\r
-\r
+  \r
   return success;\r
 }\r
 \r
@@ -951,7 +951,7 @@ static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) {
 ** it looked pretty nice. But I've since switched\r
 ** it around to an awkward while loop. It was an\r
 ** unfortunate change for code simplicity but it\r
-** is noble in the name of performance (and\r
+** is noble in the name of performance (and \r
 ** not smashing the stack).\r
 **\r
 ** But it is now a pretty ugly beast...\r
@@ -963,25 +963,25 @@ static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) {
 #define MPC_PRIMATIVE(x, f) if (f) { MPC_SUCCESS(x); } else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); }\r
 \r
 int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {\r
-\r
+  \r
   /* Stack */\r
   int st = 0;\r
   mpc_parser_t *p = NULL;\r
   mpc_stack_t *stk = mpc_stack_new(i->filename);\r
-\r
+  \r
   /* Variables */\r
   char *s;\r
   mpc_result_t r;\r
 \r
   /* Go! */\r
   mpc_stack_pushp(stk, init);\r
-\r
+  \r
   while (!mpc_stack_empty(stk)) {\r
-\r
+    \r
     mpc_stack_peepp(stk, &p, &st);\r
-\r
+    \r
     switch (p->type) {\r
-\r
+      \r
       /* Basic Parsers */\r
 \r
       case MPC_TYPE_ANY:       MPC_PRIMATIVE(s, mpc_input_any(i, &s));\r
@@ -991,36 +991,36 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
       case MPC_TYPE_NONEOF:    MPC_PRIMATIVE(s, mpc_input_noneof(i, p->data.string.x, &s));\r
       case MPC_TYPE_SATISFY:   MPC_PRIMATIVE(s, mpc_input_satisfy(i, p->data.satisfy.f, &s));\r
       case MPC_TYPE_STRING:    MPC_PRIMATIVE(s, mpc_input_string(i, p->data.string.x, &s));\r
-\r
+      \r
       /* Other parsers */\r
-\r
-      case MPC_TYPE_UNDEFINED: MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Parser Undefined!"));\r
+      \r
+      case MPC_TYPE_UNDEFINED: MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Parser Undefined!"));      \r
       case MPC_TYPE_PASS:      MPC_SUCCESS(NULL);\r
       case MPC_TYPE_FAIL:      MPC_FAILURE(mpc_err_fail(i->filename, i->state, p->data.fail.m));\r
       case MPC_TYPE_LIFT:      MPC_SUCCESS(p->data.lift.lf());\r
       case MPC_TYPE_LIFT_VAL:  MPC_SUCCESS(p->data.lift.x);\r
       case MPC_TYPE_STATE:     MPC_SUCCESS(mpc_state_copy(i->state));\r
-\r
+      \r
       case MPC_TYPE_ANCHOR:\r
         if (mpc_input_anchor(i, p->data.anchor.f)) {\r
           MPC_SUCCESS(NULL);\r
         } else {\r
           MPC_FAILURE(mpc_err_new(i->filename, i->state, "anchor", mpc_input_peekc(i)));\r
         }\r
-\r
+      \r
       /* Application Parsers */\r
-\r
+      \r
       case MPC_TYPE_EXPECT:\r
         if (st == 0) { MPC_CONTINUE(1, p->data.expect.x); }\r
         if (st == 1) {\r
           if (mpc_stack_popr(stk, &r)) {\r
             MPC_SUCCESS(r.output);\r
           } else {\r
-            mpc_err_delete(r.error);\r
+            mpc_err_delete(r.error); \r
             MPC_FAILURE(mpc_err_new(i->filename, i->state, p->data.expect.m, mpc_input_peekc(i)));\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_APPLY:\r
         if (st == 0) { MPC_CONTINUE(1, p->data.apply.x); }\r
         if (st == 1) {\r
@@ -1030,7 +1030,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             MPC_FAILURE(r.error);\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_APPLY_TO:\r
         if (st == 0) { MPC_CONTINUE(1, p->data.apply_to.x); }\r
         if (st == 1) {\r
@@ -1040,7 +1040,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             MPC_FAILURE(r.error);\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_PREDICT:\r
         if (st == 0) { mpc_input_backtrack_disable(i); MPC_CONTINUE(1, p->data.predict.x); }\r
         if (st == 1) {\r
@@ -1048,11 +1048,11 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
           mpc_stack_popp(stk, &p, &st);\r
           continue;\r
         }\r
-\r
+      \r
       /* Optional Parsers */\r
-\r
+      \r
       /* TODO: Update Not Error Message */\r
-\r
+      \r
       case MPC_TYPE_NOT:\r
         if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(1, p->data.not.x); }\r
         if (st == 1) {\r
@@ -1066,7 +1066,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             MPC_SUCCESS(p->data.not.lf());\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_MAYBE:\r
         if (st == 0) { MPC_CONTINUE(1, p->data.not.x); }\r
         if (st == 1) {\r
@@ -1077,9 +1077,9 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             MPC_SUCCESS(p->data.not.lf());\r
           }\r
         }\r
-\r
+      \r
       /* Repeat Parsers */\r
-\r
+      \r
       case MPC_TYPE_MANY:\r
         if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }\r
         if (st >  0) {\r
@@ -1091,7 +1091,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             MPC_SUCCESS(mpc_stack_merger_out(stk, st-1, p->data.repeat.f));\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_MANY1:\r
         if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }\r
         if (st >  0) {\r
@@ -1108,7 +1108,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             }\r
           }\r
         }\r
-\r
+      \r
       case MPC_TYPE_COUNT:\r
         if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.repeat.x); }\r
         if (st >  0) {\r
@@ -1128,13 +1128,13 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
             }\r
           }\r
         }\r
-\r
+        \r
       /* Combinatory Parsers */\r
-\r
+      \r
       case MPC_TYPE_OR:\r
-\r
+        \r
         if (p->data.or.n == 0) { MPC_SUCCESS(NULL); }\r
-\r
+        \r
         if (st == 0) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }\r
         if (st <= p->data.or.n) {\r
           if (mpc_stack_peekr(stk, &r)) {\r
@@ -1145,11 +1145,11 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
           if (st <  p->data.or.n) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }\r
           if (st == p->data.or.n) { MPC_FAILURE(mpc_stack_merger_err(stk, p->data.or.n)); }\r
         }\r
-\r
+      \r
       case MPC_TYPE_AND:\r
-\r
+        \r
         if (p->data.or.n == 0) { MPC_SUCCESS(p->data.and.f(0, NULL)); }\r
-\r
+        \r
         if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.and.xs[st]); }\r
         if (st <= p->data.and.n) {\r
           if (!mpc_stack_peekr(stk, &r)) {\r
@@ -1161,17 +1161,17 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
           if (st <  p->data.and.n) { MPC_CONTINUE(st+1, p->data.and.xs[st]); }\r
           if (st == p->data.and.n) { mpc_input_unmark(i); MPC_SUCCESS(mpc_stack_merger_out(stk, p->data.and.n, p->data.and.f)); }\r
         }\r
-\r
+      \r
       /* End */\r
-\r
+      \r
       default:\r
-\r
+        \r
         MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Unknown Parser Type Id!"));\r
     }\r
   }\r
-\r
+  \r
   return mpc_stack_terminate(stk, final);\r
-\r
+  \r
 }\r
 \r
 #undef MPC_CONTINUE\r
@@ -1204,16 +1204,16 @@ int mpc_parse_pipe(const char *filename, FILE *pipe, mpc_parser_t *p, mpc_result
 }\r
 \r
 int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r) {\r
-\r
+  \r
   FILE *f = fopen(filename, "rb");\r
   int res;\r
-\r
+  \r
   if (f == NULL) {\r
     r->output = NULL;\r
     r->error = mpc_err_fail(filename, mpc_state_new(), "Unable to open file!");\r
     return 0;\r
   }\r
-\r
+  \r
   res = mpc_parse_file(filename, f, p, r);\r
   fclose(f);\r
   return res;\r
@@ -1226,71 +1226,71 @@ int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r) {
 static void mpc_undefine_unretained(mpc_parser_t *p, int force);\r
 \r
 static void mpc_undefine_or(mpc_parser_t *p) {\r
-\r
+  \r
   int i;\r
   for (i = 0; i < p->data.or.n; i++) {\r
     mpc_undefine_unretained(p->data.or.xs[i], 0);\r
   }\r
   free(p->data.or.xs);\r
-\r
+  \r
 }\r
 \r
 static void mpc_undefine_and(mpc_parser_t *p) {\r
-\r
+  \r
   int i;\r
   for (i = 0; i < p->data.and.n; i++) {\r
     mpc_undefine_unretained(p->data.and.xs[i], 0);\r
   }\r
   free(p->data.and.xs);\r
   free(p->data.and.dxs);\r
-\r
+  \r
 }\r
 \r
 static void mpc_undefine_unretained(mpc_parser_t *p, int force) {\r
-\r
+  \r
   if (p->retained && !force) { return; }\r
-\r
+  \r
   switch (p->type) {\r
-\r
+    \r
     case MPC_TYPE_FAIL: free(p->data.fail.m); break;\r
-\r
-    case MPC_TYPE_ONEOF:\r
+    \r
+    case MPC_TYPE_ONEOF: \r
     case MPC_TYPE_NONEOF:\r
     case MPC_TYPE_STRING:\r
-      free(p->data.string.x);\r
+      free(p->data.string.x); \r
       break;\r
-\r
+    \r
     case MPC_TYPE_APPLY:    mpc_undefine_unretained(p->data.apply.x, 0);    break;\r
     case MPC_TYPE_APPLY_TO: mpc_undefine_unretained(p->data.apply_to.x, 0); break;\r
     case MPC_TYPE_PREDICT:  mpc_undefine_unretained(p->data.predict.x, 0);  break;\r
-\r
+    \r
     case MPC_TYPE_MAYBE:\r
     case MPC_TYPE_NOT:\r
       mpc_undefine_unretained(p->data.not.x, 0);\r
       break;\r
-\r
+    \r
     case MPC_TYPE_EXPECT:\r
       mpc_undefine_unretained(p->data.expect.x, 0);\r
       free(p->data.expect.m);\r
       break;\r
-\r
+      \r
     case MPC_TYPE_MANY:\r
     case MPC_TYPE_MANY1:\r
     case MPC_TYPE_COUNT:\r
       mpc_undefine_unretained(p->data.repeat.x, 0);\r
       break;\r
-\r
+    \r
     case MPC_TYPE_OR:  mpc_undefine_or(p);  break;\r
     case MPC_TYPE_AND: mpc_undefine_and(p); break;\r
-\r
+    \r
     default: break;\r
   }\r
-\r
+  \r
   if (!force) {\r
     free(p->name);\r
     free(p);\r
   }\r
-\r
+  \r
 }\r
 \r
 void mpc_delete(mpc_parser_t *p) {\r
@@ -1298,13 +1298,13 @@ void mpc_delete(mpc_parser_t *p) {
 \r
     if (p->type != MPC_TYPE_UNDEFINED) {\r
       mpc_undefine_unretained(p, 0);\r
-    }\r
-\r
+    } \r
+    \r
     free(p->name);\r
     free(p);\r
-\r
+  \r
   } else {\r
-    mpc_undefine_unretained(p, 0);\r
+    mpc_undefine_unretained(p, 0);  \r
   }\r
 }\r
 \r
@@ -1335,7 +1335,7 @@ mpc_parser_t *mpc_undefine(mpc_parser_t *p) {
 }\r
 \r
 mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a) {\r
-\r
+  \r
   if (p->retained) {\r
     p->type = a->type;\r
     p->data = a->data;\r
@@ -1345,21 +1345,21 @@ mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a) {
     p->data = a2->data;\r
     free(a2);\r
   }\r
-\r
+  \r
   free(a);\r
-  return p;\r
+  return p;  \r
 }\r
 \r
 void mpc_cleanup(int n, ...) {\r
   int i;\r
   mpc_parser_t **list = malloc(sizeof(mpc_parser_t*) * n);\r
-\r
+  \r
   va_list va;\r
   va_start(va, n);\r
   for (i = 0; i < n; i++) { list[i] = va_arg(va, mpc_parser_t*); }\r
   for (i = 0; i < n; i++) { mpc_undefine(list[i]); }\r
-  for (i = 0; i < n; i++) { mpc_delete(list[i]); }\r
-  va_end(va);\r
+  for (i = 0; i < n; i++) { mpc_delete(list[i]); }  \r
+  va_end(va);  \r
 \r
   free(list);\r
 }\r
@@ -1379,7 +1379,7 @@ mpc_parser_t *mpc_fail(const char *m) {
 }\r
 \r
 /*\r
-** As `snprintf` is not ANSI standard this\r
+** As `snprintf` is not ANSI standard this \r
 ** function `mpc_failf` should be considered\r
 ** unsafe.\r
 **\r
@@ -1390,7 +1390,7 @@ mpc_parser_t *mpc_fail(const char *m) {
 **   the buffer length using precision specifiers\r
 **   such as `%.512s`.\r
 **\r
-** - Patch this function in your code base to\r
+** - Patch this function in your code base to \r
 **   use `snprintf` or whatever variant your\r
 **   system supports.\r
 **\r
@@ -1399,18 +1399,18 @@ mpc_parser_t *mpc_fail(const char *m) {
 */\r
 \r
 mpc_parser_t *mpc_failf(const char *fmt, ...) {\r
-\r
+  \r
   va_list va;\r
   char *buffer;\r
 \r
   mpc_parser_t *p = mpc_undefined();\r
   p->type = MPC_TYPE_FAIL;\r
-\r
+  \r
   va_start(va, fmt);\r
   buffer = malloc(2048);\r
   vsprintf(buffer, fmt, va);\r
   va_end(va);\r
-\r
+  \r
   buffer = realloc(buffer, strlen(buffer) + 1);\r
   p->data.fail.m = buffer;\r
   return p;\r
@@ -1454,7 +1454,7 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *expected) {
 }\r
 \r
 /*\r
-** As `snprintf` is not ANSI standard this\r
+** As `snprintf` is not ANSI standard this \r
 ** function `mpc_expectf` should be considered\r
 ** unsafe.\r
 **\r
@@ -1465,7 +1465,7 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *expected) {
 **   the buffer length using precision specifiers\r
 **   such as `%.512s`.\r
 **\r
-** - Patch this function in your code base to\r
+** - Patch this function in your code base to \r
 **   use `snprintf` or whatever variant your\r
 **   system supports.\r
 **\r
@@ -1479,12 +1479,12 @@ mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...) {
 \r
   mpc_parser_t *p = mpc_undefined();\r
   p->type = MPC_TYPE_EXPECT;\r
-\r
+  \r
   va_start(va, fmt);\r
   buffer = malloc(2048);\r
   vsprintf(buffer, fmt, va);\r
   va_end(va);\r
-\r
+  \r
   buffer = realloc(buffer, strlen(buffer) + 1);\r
   p->data.expect.x = a;\r
   p->data.expect.m = buffer;\r
@@ -1633,17 +1633,17 @@ mpc_parser_t *mpc_or(int n, ...) {
   va_list va;\r
 \r
   mpc_parser_t *p = mpc_undefined();\r
-\r
+  \r
   p->type = MPC_TYPE_OR;\r
   p->data.or.n = n;\r
   p->data.or.xs = malloc(sizeof(mpc_parser_t*) * n);\r
-\r
-  va_start(va, n);\r
+  \r
+  va_start(va, n);  \r
   for (i = 0; i < n; i++) {\r
     p->data.or.xs[i] = va_arg(va, mpc_parser_t*);\r
   }\r
   va_end(va);\r
-\r
+  \r
   return p;\r
 }\r
 \r
@@ -1653,22 +1653,22 @@ mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...) {
   va_list va;\r
 \r
   mpc_parser_t *p = mpc_undefined();\r
-\r
+  \r
   p->type = MPC_TYPE_AND;\r
   p->data.and.n = n;\r
   p->data.and.f = f;\r
   p->data.and.xs = malloc(sizeof(mpc_parser_t*) * n);\r
   p->data.and.dxs = malloc(sizeof(mpc_dtor_t) * (n-1));\r
 \r
-  va_start(va, f);\r
+  va_start(va, f);  \r
   for (i = 0; i < n; i++) {\r
     p->data.and.xs[i] = va_arg(va, mpc_parser_t*);\r
   }\r
   for (i = 0; i < (n-1); i++) {\r
     p->data.and.dxs[i] = va_arg(va, mpc_dtor_t);\r
-  }\r
+  }  \r
   va_end(va);\r
-\r
+  \r
   return p;\r
 }\r
 \r
@@ -1724,9 +1724,9 @@ mpc_parser_t *mpc_number(void) { return mpc_expect(mpc_or(3, mpc_int(), mpc_hex(
 mpc_parser_t *mpc_real(void) {\r
 \r
   /* [+-]?\d+(\.\d+)?([eE][+-]?[0-9]+)? */\r
-\r
+  \r
   mpc_parser_t *p0, *p1, *p2, *p30, *p31, *p32, *p3;\r
-\r
+  \r
   p0 = mpc_maybe_lift(mpc_oneof("+-"), mpcf_ctor_str);\r
   p1 = mpc_digits();\r
   p2 = mpc_maybe_lift(mpc_and(2, mpcf_strfold, mpc_char('.'), mpc_digits(), free), mpcf_ctor_str);\r
@@ -1734,7 +1734,7 @@ mpc_parser_t *mpc_real(void) {
   p31 = mpc_maybe_lift(mpc_oneof("+-"), mpcf_ctor_str);\r
   p32 = mpc_digits();\r
   p3 = mpc_maybe_lift(mpc_and(3, mpcf_strfold, p30, p31, p32, free, free), mpcf_ctor_str);\r
-\r
+  \r
   return mpc_expect(mpc_and(4, mpcf_strfold, p0, p1, p2, p3, free, free, free), "real");\r
 \r
 }\r
@@ -1752,15 +1752,15 @@ mpc_parser_t *mpc_string_lit(void) {
   return mpc_expect(mpc_between(mpc_many(mpcf_strfold, strchar), free, "\"", "\""), "string");\r
 }\r
 \r
-mpc_parser_t *mpc_regex_lit(void) {\r
+mpc_parser_t *mpc_regex_lit(void) {  \r
   mpc_parser_t *regexchar = mpc_or(2, mpc_escape(), mpc_noneof("/"));\r
   return mpc_expect(mpc_between(mpc_many(mpcf_strfold, regexchar), free, "/", "/"), "regex");\r
 }\r
 \r
 mpc_parser_t *mpc_ident(void) {\r
-  mpc_parser_t *p0, *p1;\r
+  mpc_parser_t *p0, *p1; \r
   p0 = mpc_or(2, mpc_alpha(), mpc_underscore());\r
-  p1 = mpc_many(mpcf_strfold, mpc_alphanum());\r
+  p1 = mpc_many(mpcf_strfold, mpc_alphanum()); \r
   return mpc_and(2, mpcf_strfold, p0, p1, free);\r
 }\r
 \r
@@ -1821,7 +1821,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad)  { return mpc_tok_
 ** a parser directly - as we are parsing.\r
 **\r
 ** This is certainly something that\r
-** would be less elegant/interesting\r
+** would be less elegant/interesting \r
 ** in a two-phase parser which first\r
 ** builds an AST and then traverses it\r
 ** to generate the object.\r
@@ -1837,7 +1837,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad)  { return mpc_tok_
 **  ### Regular Expression Grammar\r
 **\r
 **      <regex> : <term> | (<term> "|" <regex>)\r
-**\r
+**     \r
 **      <term> : <factor>*\r
 **\r
 **      <factor> : <base>\r
@@ -1845,7 +1845,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad)  { return mpc_tok_
 **               | <base> "+"\r
 **               | <base> "?"\r
 **               | <base> "{" <digits> "}"\r
-**\r
+**           \r
 **      <base> : <char>\r
 **             | "\" <char>\r
 **             | "(" <regex> ")"\r
@@ -1867,7 +1867,7 @@ static mpc_val_t *mpcf_re_and(int n, mpc_val_t **xs) {
 }\r
 \r
 static mpc_val_t *mpcf_re_repeat(int n, mpc_val_t **xs) {\r
-\r
+  \r
   int num;\r
   if (xs[1] == NULL) { return xs[0]; }\r
   if (strcmp(xs[1], "*") == 0) { free(xs[1]); return mpc_many(mpcf_strfold, xs[0]); }\r
@@ -1875,7 +1875,7 @@ static mpc_val_t *mpcf_re_repeat(int n, mpc_val_t **xs) {
   if (strcmp(xs[1], "?") == 0) { free(xs[1]); return mpc_maybe_lift(xs[0], mpcf_ctor_str); }\r
   num = *(int*)xs[1];\r
   free(xs[1]);\r
-\r
+  \r
   return mpc_count(num, mpcf_strfold, xs[0], free);\r
 }\r
 \r
@@ -1902,15 +1902,15 @@ static mpc_parser_t *mpc_re_escape_char(char c) {
 }\r
 \r
 static mpc_val_t *mpcf_re_escape(mpc_val_t *x) {\r
-\r
+  \r
   char *s = x;\r
   mpc_parser_t *p;\r
-\r
+  \r
   /* Regex Special Characters */\r
   if (s[0] == '.') { free(s); return mpc_any(); }\r
   if (s[0] == '^') { free(s); return mpc_and(2, mpcf_snd, mpc_soi(), mpc_lift(mpcf_ctor_str), free); }\r
   if (s[0] == '$') { free(s); return mpc_and(2, mpcf_snd, mpc_eoi(), mpc_lift(mpcf_ctor_str), free); }\r
-\r
+  \r
   /* Regex Escape */\r
   if (s[0] == '\\') {\r
     p = mpc_re_escape_char(s[1]);\r
@@ -1918,7 +1918,7 @@ static mpc_val_t *mpcf_re_escape(mpc_val_t *x) {
     free(s);\r
     return p;\r
   }\r
-\r
+  \r
   /* Regex Standard */\r
   p = mpc_char(s[0]);\r
   free(s);\r
@@ -1943,7 +1943,7 @@ static char *mpc_re_range_escape_char(char c) {
 }\r
 \r
 static mpc_val_t *mpcf_re_range(mpc_val_t *x) {\r
-\r
+  \r
   mpc_parser_t *out;\r
   char *range = calloc(1,1);\r
   char *tmp = NULL;\r
@@ -1951,15 +1951,15 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) {
   char start, end;\r
   int i, j;\r
   int comp = 0;\r
-\r
-  if (s[0] == '\0') { free(x); return mpc_fail("Invalid Regex Range Expression"); }\r
-  if (s[0] == '^' &&\r
+  \r
+  if (s[0] == '\0') { free(x); return mpc_fail("Invalid Regex Range Expression"); } \r
+  if (s[0] == '^' && \r
       s[1] == '\0') { free(x); return mpc_fail("Invalid Regex Range Expression"); }\r
-\r
+  \r
   if (s[0] == '^') { comp = 1;}\r
-\r
+  \r
   for (i = comp; i < strlen(s); i++){\r
-\r
+    \r
     /* Regex Range Escape */\r
     if (s[i] == '\\') {\r
       tmp = mpc_re_range_escape_char(s[i+1]);\r
@@ -1969,11 +1969,11 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) {
       } else {\r
         range = realloc(range, strlen(range) + 1 + 1);\r
         range[strlen(range) + 1] = '\0';\r
-        range[strlen(range) + 0] = s[i+1];\r
+        range[strlen(range) + 0] = s[i+1];      \r
       }\r
       i++;\r
     }\r
-\r
+    \r
     /* Regex Range...Range */\r
     else if (s[i] == '-') {\r
       if (s[i+1] == '\0' || i == 0) {\r
@@ -1986,48 +1986,48 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) {
           range = realloc(range, strlen(range) + 1 + 1);\r
           range[strlen(range) + 1] = '\0';\r
           range[strlen(range) + 0] = j;\r
-        }\r
+        }        \r
       }\r
     }\r
-\r
+    \r
     /* Regex Range Normal */\r
     else {\r
       range = realloc(range, strlen(range) + 1 + 1);\r
       range[strlen(range) + 1] = '\0';\r
       range[strlen(range) + 0] = s[i];\r
     }\r
-\r
+  \r
   }\r
-\r
+  \r
   out = comp ? mpc_noneof(range) : mpc_oneof(range);\r
-\r
+  \r
   free(x);\r
   free(range);\r
-\r
+  \r
   return out;\r
 }\r
 \r
 mpc_parser_t *mpc_re(const char *re) {\r
-\r
+  \r
   char *err_msg;\r
   mpc_parser_t *err_out;\r
   mpc_result_t r;\r
-  mpc_parser_t *Regex, *Term, *Factor, *Base, *Range, *RegexEnclose;\r
-\r
+  mpc_parser_t *Regex, *Term, *Factor, *Base, *Range, *RegexEnclose; \r
+  \r
   Regex  = mpc_new("regex");\r
   Term   = mpc_new("term");\r
   Factor = mpc_new("factor");\r
   Base   = mpc_new("base");\r
   Range  = mpc_new("range");\r
-\r
+  \r
   mpc_define(Regex, mpc_and(2, mpcf_re_or,\r
-    Term,\r
+    Term, \r
     mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_char('|'), Regex, free)),\r
     (mpc_dtor_t)mpc_delete\r
   ));\r
-\r
+  \r
   mpc_define(Term, mpc_many(mpcf_re_and, Factor));\r
-\r
+  \r
   mpc_define(Factor, mpc_and(2, mpcf_re_repeat,\r
     Base,\r
     mpc_or(5,\r
@@ -2036,34 +2036,34 @@ mpc_parser_t *mpc_re(const char *re) {
       mpc_pass()),\r
     (mpc_dtor_t)mpc_delete\r
   ));\r
-\r
+  \r
   mpc_define(Base, mpc_or(4,\r
     mpc_parens(Regex, (mpc_dtor_t)mpc_delete),\r
     mpc_squares(Range, (mpc_dtor_t)mpc_delete),\r
     mpc_apply(mpc_escape(), mpcf_re_escape),\r
     mpc_apply(mpc_noneof(")|"), mpcf_re_escape)\r
   ));\r
-\r
+  \r
   mpc_define(Range, mpc_apply(\r
     mpc_many(mpcf_strfold, mpc_or(2, mpc_escape(), mpc_noneof("]"))),\r
     mpcf_re_range\r
   ));\r
-\r
+  \r
   RegexEnclose = mpc_whole(mpc_predictive(Regex), (mpc_dtor_t)mpc_delete);\r
-\r
+  \r
   if(!mpc_parse("<mpc_re_compiler>", re, RegexEnclose, &r)) {\r
     err_msg = mpc_err_string(r.error);\r
     err_out = mpc_failf("Invalid Regex: %s", err_msg);\r
-    mpc_err_delete(r.error);\r
+    mpc_err_delete(r.error);  \r
     free(err_msg);\r
     r.output = err_out;\r
   }\r
-\r
+  \r
   mpc_delete(RegexEnclose);\r
   mpc_cleanup(5, Regex, Term, Factor, Base, Range);\r
-\r
+  \r
   return r.output;\r
-\r
+  \r
 }\r
 \r
 /*\r
@@ -2107,9 +2107,9 @@ mpc_val_t *mpcf_float(mpc_val_t *x) {
 static char mpc_escape_input_c[]  = {\r
   '\a', '\b', '\f', '\n', '\r',\r
   '\t', '\v', '\\', '\'', '\"', '\0'};\r
-\r
+    \r
 static char *mpc_escape_output_c[] = {\r
-  "\\a", "\\b", "\\f", "\\n", "\\r", "\\t",\r
+  "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", \r
   "\\v", "\\\\", "\\'", "\\\"", "\\0", NULL};\r
 \r
 static char mpc_escape_input_raw_re[] = { '/' };\r
@@ -2122,15 +2122,15 @@ static char mpc_escape_input_raw_cchar[] = { '\'' };
 static char *mpc_escape_output_raw_cchar[] = { "\\'", NULL };\r
 \r
 static mpc_val_t *mpcf_escape_new(mpc_val_t *x, char *input, char **output) {\r
-\r
+  \r
   int i;\r
   int found;\r
   char *s = x;\r
   char *y = calloc(1, 1);\r
   char buff[2];\r
-\r
+  \r
   while (*s) {\r
-\r
+    \r
     i = 0;\r
     found = 0;\r
 \r
@@ -2143,22 +2143,22 @@ static mpc_val_t *mpcf_escape_new(mpc_val_t *x, char *input, char **output) {
       }\r
       i++;\r
     }\r
-\r
+    \r
     if (!found) {\r
       y = realloc(y, strlen(y) + 2);\r
       buff[0] = *s; buff[1] = '\0';\r
       strcat(y, buff);\r
     }\r
-\r
+    \r
     s++;\r
   }\r
-\r
-\r
+  \r
+  \r
   return y;\r
 }\r
 \r
 static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, char *input, char **output) {\r
-\r
+  \r
   int i;\r
   int found = 0;\r
   char *s = x;\r
@@ -2166,10 +2166,10 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, char *input, char **output) {
   char buff[2];\r
 \r
   while (*s) {\r
-\r
+    \r
     i = 0;\r
     found = 0;\r
-\r
+    \r
     while (output[i]) {\r
       if ((*(s+0)) == output[i][0] &&\r
           (*(s+1)) == output[i][1]) {\r
@@ -2182,19 +2182,19 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, char *input, char **output) {
       }\r
       i++;\r
     }\r
-\r
+      \r
     if (!found) {\r
       y = realloc(y, strlen(y) + 2);\r
       buff[0] = *s; buff[1] = '\0';\r
       strcat(y, buff);\r
     }\r
-\r
+    \r
     if (*s == '\0') { break; }\r
     else { s++; }\r
   }\r
-\r
+  \r
   return y;\r
-\r
+  \r
 }\r
 \r
 mpc_val_t *mpcf_escape(mpc_val_t *x) {\r
@@ -2212,7 +2212,7 @@ mpc_val_t *mpcf_unescape(mpc_val_t *x) {
 mpc_val_t *mpcf_unescape_regex(mpc_val_t *x) {\r
   mpc_val_t *y = mpcf_unescape_new(x, mpc_escape_input_raw_re, mpc_escape_output_raw_re);\r
   free(x);\r
-  return y;\r
+  return y;  \r
 }\r
 \r
 mpc_val_t *mpcf_escape_string_raw(mpc_val_t *x) {\r
@@ -2251,7 +2251,7 @@ static mpc_val_t *mpcf_nth_free(int n, mpc_val_t **xs, int x) {
   }\r
   return xs[x];\r
 }\r
-\r
\r
 mpc_val_t *mpcf_fst_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 0); }\r
 mpc_val_t *mpcf_snd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 1); }\r
 mpc_val_t *mpcf_trd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 2); }\r
@@ -2268,17 +2268,17 @@ mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) {
 }\r
 \r
 mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) {\r
-\r
+  \r
   int **vs = (int**)xs;\r
-\r
+    \r
   if (strcmp(xs[1], "*") == 0) { *vs[0] *= *vs[2]; }\r
   if (strcmp(xs[1], "/") == 0) { *vs[0] /= *vs[2]; }\r
   if (strcmp(xs[1], "%") == 0) { *vs[0] %= *vs[2]; }\r
   if (strcmp(xs[1], "+") == 0) { *vs[0] += *vs[2]; }\r
   if (strcmp(xs[1], "-") == 0) { *vs[0] -= *vs[2]; }\r
-\r
+  \r
   free(xs[1]); free(xs[2]);\r
-\r
+  \r
   return xs[0];\r
 }\r
 \r
@@ -2287,19 +2287,19 @@ mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) {
 */\r
 \r
 static void mpc_print_unretained(mpc_parser_t *p, int force) {\r
-\r
+  \r
   /* TODO: Print Everything Escaped */\r
-\r
+  \r
   int i;\r
   char *s, *e;\r
   char buff[2];\r
-\r
+  \r
   if (p->retained && !force) {;\r
     if (p->name) { printf("<%s>", p->name); }\r
     else { printf("<anon>"); }\r
     return;\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_UNDEFINED) { printf("<?>"); }\r
   if (p->type == MPC_TYPE_PASS)   { printf("<:>"); }\r
   if (p->type == MPC_TYPE_FAIL)   { printf("<!>"); }\r
@@ -2310,7 +2310,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     printf("%s", p->data.expect.m);\r
     /*mpc_print_unretained(p->data.expect.x, 0);*/\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_ANY) { printf("<.>"); }\r
   if (p->type == MPC_TYPE_SATISFY) { printf("<f>"); }\r
 \r
@@ -2323,7 +2323,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     printf("'%s'", s);\r
     free(s);\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_RANGE) {\r
     buff[0] = p->data.range.x; buff[1] = '\0';\r
     s = mpcf_escape_new(\r
@@ -2339,7 +2339,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     free(s);\r
     free(e);\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_ONEOF) {\r
     s = mpcf_escape_new(\r
       p->data.string.x,\r
@@ -2348,7 +2348,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     printf("[%s]", s);\r
     free(s);\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_NONEOF) {\r
     s = mpcf_escape_new(\r
       p->data.string.x,\r
@@ -2357,7 +2357,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     printf("[^%s]", s);\r
     free(s);\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_STRING) {\r
     s = mpcf_escape_new(\r
       p->data.string.x,\r
@@ -2366,7 +2366,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     printf("\"%s\"", s);\r
     free(s);\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_APPLY)    { mpc_print_unretained(p->data.apply.x, 0); }\r
   if (p->type == MPC_TYPE_APPLY_TO) { mpc_print_unretained(p->data.apply_to.x, 0); }\r
   if (p->type == MPC_TYPE_PREDICT)  { mpc_print_unretained(p->data.predict.x, 0); }\r
@@ -2377,7 +2377,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
   if (p->type == MPC_TYPE_MANY)  { mpc_print_unretained(p->data.repeat.x, 0); printf("*"); }\r
   if (p->type == MPC_TYPE_MANY1) { mpc_print_unretained(p->data.repeat.x, 0); printf("+"); }\r
   if (p->type == MPC_TYPE_COUNT) { mpc_print_unretained(p->data.repeat.x, 0); printf("{%i}", p->data.repeat.n); }\r
-\r
+  \r
   if (p->type == MPC_TYPE_OR) {\r
     printf("(");\r
     for(i = 0; i < p->data.or.n-1; i++) {\r
@@ -2387,7 +2387,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     mpc_print_unretained(p->data.or.xs[p->data.or.n-1], 0);\r
     printf(")");\r
   }\r
-\r
+  \r
   if (p->type == MPC_TYPE_AND) {\r
     printf("(");\r
     for(i = 0; i < p->data.and.n-1; i++) {\r
@@ -2397,7 +2397,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
     mpc_print_unretained(p->data.and.xs[p->data.and.n-1], 0);\r
     printf(")");\r
   }\r
-\r
+  \r
 }\r
 \r
 void mpc_print(mpc_parser_t *p) {\r
@@ -2425,7 +2425,7 @@ int mpc_test_fail(mpc_parser_t *p, const char *s, void *d,
   mpc_dtor_t destructor,\r
   void(*printer)(void*)) {\r
 \r
-  mpc_result_t r;\r
+  mpc_result_t r;  \r
   if (mpc_parse("<test>", s, p, &r)) {\r
 \r
     if (tester(r.output, d)) {\r
@@ -2435,22 +2435,22 @@ int mpc_test_fail(mpc_parser_t *p, const char *s, void *d,
       destructor(r.output);\r
       return 1;\r
     }\r
-\r
+  \r
   } else {\r
     mpc_err_delete(r.error);\r
     return 1;\r
   }\r
-\r
+  \r
 }\r
 \r
 int mpc_test_pass(mpc_parser_t *p, const char *s, void *d,\r
-  int(*tester)(void*, void*),\r
-  mpc_dtor_t destructor,\r
+  int(*tester)(void*, void*), \r
+  mpc_dtor_t destructor, \r
   void(*printer)(void*)) {\r
 \r
-  mpc_result_t r;\r
+  mpc_result_t r;  \r
   if (mpc_parse("<test>", s, p, &r)) {\r
-\r
+    \r
     if (tester(r.output, d)) {\r
       destructor(r.output);\r
       return 1;\r
@@ -2460,14 +2460,14 @@ int mpc_test_pass(mpc_parser_t *p, const char *s, void *d,
       destructor(r.output);\r
       return 0;\r
     }\r
-\r
-  } else {\r
+    \r
+  } else {    \r
     mpc_err_print(r.error);\r
     mpc_err_delete(r.error);\r
     return 0;\r
-\r
+    \r
   }\r
-\r
+  \r
 }\r
 \r
 \r
@@ -2476,19 +2476,19 @@ int mpc_test_pass(mpc_parser_t *p, const char *s, void *d,
 */\r
 \r
 void mpc_ast_delete(mpc_ast_t *a) {\r
-\r
+  \r
   int i;\r
-\r
+  \r
   if (a == NULL) { return; }\r
   for (i = 0; i < a->children_num; i++) {\r
     mpc_ast_delete(a->children[i]);\r
   }\r
-\r
+  \r
   free(a->children);\r
   free(a->tag);\r
   free(a->contents);\r
   free(a);\r
-\r
+  \r
 }\r
 \r
 static void mpc_ast_delete_no_children(mpc_ast_t *a) {\r
@@ -2499,39 +2499,39 @@ static void mpc_ast_delete_no_children(mpc_ast_t *a) {
 }\r
 \r
 mpc_ast_t *mpc_ast_new(const char *tag, const char *contents) {\r
-\r
+  \r
   mpc_ast_t *a = malloc(sizeof(mpc_ast_t));\r
-\r
+  \r
   a->tag = malloc(strlen(tag) + 1);\r
   strcpy(a->tag, tag);\r
-\r
+  \r
   a->contents = malloc(strlen(contents) + 1);\r
   strcpy(a->contents, contents);\r
-\r
+  \r
   a->state = mpc_state_new();\r
-\r
+  \r
   a->children_num = 0;\r
   a->children = NULL;\r
   return a;\r
-\r
+  \r
 }\r
 \r
 mpc_ast_t *mpc_ast_build(int n, const char *tag, ...) {\r
-\r
+  \r
   mpc_ast_t *a = mpc_ast_new(tag, "");\r
-\r
+  \r
   int i;\r
   va_list va;\r
   va_start(va, tag);\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
     mpc_ast_add_child(a, va_arg(va, mpc_ast_t*));\r
   }\r
-\r
+  \r
   va_end(va);\r
-\r
+  \r
   return a;\r
-\r
+  \r
 }\r
 \r
 mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a) {\r
@@ -2548,17 +2548,17 @@ mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a) {
 }\r
 \r
 int mpc_ast_eq(mpc_ast_t *a, mpc_ast_t *b) {\r
-\r
+  \r
   int i;\r
 \r
   if (strcmp(a->tag, b->tag) != 0) { return 0; }\r
   if (strcmp(a->contents, b->contents) != 0) { return 0; }\r
   if (a->children_num != b->children_num) { return 0; }\r
-\r
+  \r
   for (i = 0; i < a->children_num; i++) {\r
     if (!mpc_ast_eq(a->children[i], b->children[i])) { return 0; }\r
   }\r
-\r
+  \r
   return 1;\r
 }\r
 \r
@@ -2591,20 +2591,20 @@ mpc_ast_t *mpc_ast_state(mpc_ast_t *a, mpc_state_t s) {
 }\r
 \r
 static void mpc_ast_print_depth(mpc_ast_t *a, int d, FILE *fp) {\r
-\r
+  \r
   int i;\r
   for (i = 0; i < d; i++) { fprintf(fp, "  "); }\r
-\r
+  \r
   if (strlen(a->contents)) {\r
     fprintf(fp, "%s:%i:%i '%s'\n", a->tag, a->state.row+1, a->state.col+1, a->contents);\r
   } else {\r
     fprintf(fp, "%s \n", a->tag);\r
   }\r
-\r
+  \r
   for (i = 0; i < a->children_num; i++) {\r
     mpc_ast_print_depth(a->children[i], d+1, fp);\r
   }\r
-\r
+  \r
 }\r
 \r
 void mpc_ast_print(mpc_ast_t *a) {\r
@@ -2616,40 +2616,40 @@ void mpc_ast_print_to(mpc_ast_t *a, FILE *fp) {
 }\r
 \r
 mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) {\r
-\r
+  \r
   int i, j;\r
   mpc_ast_t** as = (mpc_ast_t**)xs;\r
   mpc_ast_t *r;\r
-\r
+  \r
   if (n == 0) { return NULL; }\r
   if (n == 1) { return xs[0]; }\r
   if (n == 2 && xs[1] == NULL) { return xs[0]; }\r
   if (n == 2 && xs[0] == NULL) { return xs[1]; }\r
-\r
+  \r
   r = mpc_ast_new(">", "");\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
-\r
+    \r
     if (as[i] == NULL) { continue; }\r
-\r
+    \r
     if (as[i] && as[i]->children_num > 0) {\r
-\r
+      \r
       for (j = 0; j < as[i]->children_num; j++) {\r
         mpc_ast_add_child(r, as[i]->children[j]);\r
       }\r
-\r
+      \r
       mpc_ast_delete_no_children(as[i]);\r
-\r
+      \r
     } else if (as[i] && as[i]->children_num == 0) {\r
       mpc_ast_add_child(r, as[i]);\r
     }\r
-\r
+  \r
   }\r
-\r
+  \r
   if (r->children_num) {\r
     r->state = r->children[0]->state;\r
   }\r
-\r
+  \r
   return r;\r
 }\r
 \r
@@ -2695,44 +2695,44 @@ mpc_parser_t *mpca_or(int n, ...) {
   va_list va;\r
 \r
   mpc_parser_t *p = mpc_undefined();\r
-\r
+  \r
   p->type = MPC_TYPE_OR;\r
   p->data.or.n = n;\r
   p->data.or.xs = malloc(sizeof(mpc_parser_t*) * n);\r
-\r
-  va_start(va, n);\r
+  \r
+  va_start(va, n);  \r
   for (i = 0; i < n; i++) {\r
     p->data.or.xs[i] = va_arg(va, mpc_parser_t*);\r
   }\r
   va_end(va);\r
-\r
+  \r
   return p;\r
-\r
+  \r
 }\r
 \r
 mpc_parser_t *mpca_and(int n, ...) {\r
-\r
+  \r
   int i;\r
   va_list va;\r
-\r
+  \r
   mpc_parser_t *p = mpc_undefined();\r
-\r
+  \r
   p->type = MPC_TYPE_AND;\r
   p->data.and.n = n;\r
   p->data.and.f = mpcf_fold_ast;\r
   p->data.and.xs = malloc(sizeof(mpc_parser_t*) * n);\r
   p->data.and.dxs = malloc(sizeof(mpc_dtor_t) * (n-1));\r
-\r
+  \r
   va_start(va, n);\r
   for (i = 0; i < n; i++) {\r
     p->data.and.xs[i] = va_arg(va, mpc_parser_t*);\r
   }\r
   for (i = 0; i < (n-1); i++) {\r
     p->data.and.dxs[i] = (mpc_dtor_t)mpc_ast_delete;\r
-  }\r
+  }    \r
   va_end(va);\r
-\r
-  return p;\r
+  \r
+  return p;  \r
 }\r
 \r
 mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_ast_delete); }\r
@@ -2765,7 +2765,7 @@ mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_
 **  ### Grammar Grammar\r
 **\r
 **      <grammar> : (<term> "|" <grammar>) | <term>\r
-**\r
+**     \r
 **      <term> : <factor>*\r
 **\r
 **      <factor> : <base>\r
@@ -2773,7 +2773,7 @@ mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_
 **               | <base> "+"\r
 **               | <base> "?"\r
 **               | <base> "{" <digits> "}"\r
-**\r
+**           \r
 **      <base> : "<" (<digits> | <ident>) ">"\r
 **             | <string_lit>\r
 **             | <char_lit>\r
@@ -2795,7 +2795,7 @@ static mpc_val_t *mpcaf_grammar_or(int n, mpc_val_t **xs) {
 \r
 static mpc_val_t *mpcaf_grammar_and(int n, mpc_val_t **xs) {\r
   int i;\r
-  mpc_parser_t *p = mpc_pass();\r
+  mpc_parser_t *p = mpc_pass();  \r
   for (i = 0; i < n; i++) {\r
     if (xs[i] != NULL) { p = mpca_and(2, p, xs[i]); }\r
   }\r
@@ -2803,9 +2803,9 @@ static mpc_val_t *mpcaf_grammar_and(int n, mpc_val_t **xs) {
 }\r
 \r
 static mpc_val_t *mpcaf_grammar_repeat(int n, mpc_val_t **xs) {\r
-\r
+  \r
   int num;\r
-  if (xs[1] == NULL) { return xs[0]; }\r
+  if (xs[1] == NULL) { return xs[0]; }  \r
   if (strcmp(xs[1], "*") == 0) { free(xs[1]); return mpca_many(xs[0]); }\r
   if (strcmp(xs[1], "+") == 0) { free(xs[1]); return mpca_many1(xs[0]); }\r
   if (strcmp(xs[1], "?") == 0) { free(xs[1]); return mpca_maybe(xs[0]); }\r
@@ -2847,15 +2847,15 @@ static int is_number(const char* s) {
 }\r
 \r
 static mpc_parser_t *mpca_grammar_find_parser(char *x, mpca_grammar_st_t *st) {\r
-\r
+  \r
   int i;\r
   mpc_parser_t *p;\r
-\r
+  \r
   /* Case of Number */\r
   if (is_number(x)) {\r
 \r
     i = strtol(x, NULL, 10);\r
-\r
+    \r
     while (st->parsers_num <= i) {\r
       st->parsers_num++;\r
       st->parsers = realloc(st->parsers, sizeof(mpc_parser_t*) * st->parsers_num);\r
@@ -2864,39 +2864,39 @@ static mpc_parser_t *mpca_grammar_find_parser(char *x, mpca_grammar_st_t *st) {
         return mpc_failf("No Parser in position %i! Only supplied %i Parsers!", i, st->parsers_num);\r
       }\r
     }\r
-\r
+    \r
     return st->parsers[st->parsers_num-1];\r
-\r
+  \r
   /* Case of Identifier */\r
   } else {\r
-\r
+    \r
     /* Search Existing Parsers */\r
     for (i = 0; i < st->parsers_num; i++) {\r
       mpc_parser_t *p = st->parsers[i];\r
       if (p == NULL) { return mpc_failf("Unknown Parser '%s'!", x); }\r
       if (p->name && strcmp(p->name, x) == 0) { return p; }\r
     }\r
-\r
+    \r
     /* Search New Parsers */\r
     while (1) {\r
-\r
+    \r
       p = va_arg(*st->va, mpc_parser_t*);\r
-\r
+      \r
       st->parsers_num++;\r
       st->parsers = realloc(st->parsers, sizeof(mpc_parser_t*) * st->parsers_num);\r
       st->parsers[st->parsers_num-1] = p;\r
-\r
+      \r
       if (p == NULL) { return mpc_failf("Unknown Parser '%s'!", x); }\r
       if (p->name && strcmp(p->name, x) == 0) { return p; }\r
-\r
+      \r
     }\r
-\r
-  }\r
-\r
+  \r
+  }  \r
+  \r
 }\r
 \r
 static mpc_val_t *mpcaf_grammar_id(mpc_val_t *x, void *s) {\r
-\r
+  \r
   mpca_grammar_st_t *st = s;\r
   mpc_parser_t *p = mpca_grammar_find_parser(x, st);\r
   free(x);\r
@@ -2909,30 +2909,30 @@ static mpc_val_t *mpcaf_grammar_id(mpc_val_t *x, void *s) {
 }\r
 \r
 mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) {\r
-\r
+  \r
   char *err_msg;\r
   mpc_parser_t *err_out;\r
   mpc_result_t r;\r
   mpc_parser_t *GrammarTotal, *Grammar, *Term, *Factor, *Base;\r
-\r
+  \r
   GrammarTotal = mpc_new("grammar_total");\r
   Grammar = mpc_new("grammar");\r
   Term = mpc_new("term");\r
   Factor = mpc_new("factor");\r
   Base = mpc_new("base");\r
-\r
+  \r
   mpc_define(GrammarTotal,\r
     mpc_predictive(mpc_total(Grammar, mpc_soft_delete))\r
   );\r
-\r
+  \r
   mpc_define(Grammar, mpc_and(2, mpcaf_grammar_or,\r
     Term,\r
     mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_sym("|"), Grammar, free)),\r
     mpc_soft_delete\r
   ));\r
-\r
+  \r
   mpc_define(Term, mpc_many1(mpcaf_grammar_and, Factor));\r
-\r
+  \r
   mpc_define(Factor, mpc_and(2, mpcaf_grammar_repeat,\r
     Base,\r
       mpc_or(6,\r
@@ -2944,7 +2944,7 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) {
         mpc_pass()),\r
     mpc_soft_delete\r
   ));\r
-\r
+  \r
   mpc_define(Base, mpc_or(5,\r
     mpc_apply_to(mpc_tok(mpc_string_lit()), mpcaf_grammar_string, st),\r
     mpc_apply_to(mpc_tok(mpc_char_lit()),   mpcaf_grammar_char, st),\r
@@ -2952,7 +2952,7 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) {
     mpc_apply_to(mpc_tok_braces(mpc_or(2, mpc_digits(), mpc_ident()), free), mpcaf_grammar_id, st),\r
     mpc_tok_parens(Grammar, mpc_soft_delete)\r
   ));\r
-\r
+  \r
   if(!mpc_parse("<mpc_grammar_compiler>", grammar, GrammarTotal, &r)) {\r
     err_msg = mpc_err_string(r.error);\r
     err_out = mpc_failf("Invalid Grammar: %s", err_msg);\r
@@ -2960,11 +2960,11 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) {
     free(err_msg);\r
     r.output = err_out;\r
   }\r
-\r
+  \r
   mpc_cleanup(5, GrammarTotal, Grammar, Term, Factor, Base);\r
-\r
+  \r
   return (st->flags & MPCA_LANG_PREDICTIVE) ? mpc_predictive(r.output) : r.output;\r
-\r
+  \r
 }\r
 \r
 mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...) {\r
@@ -2972,13 +2972,13 @@ mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...) {
   mpc_parser_t *res;\r
   va_list va;\r
   va_start(va, grammar);\r
-\r
+  \r
   st.va = &va;\r
   st.parsers_num = 0;\r
   st.parsers = NULL;\r
   st.flags = flags;\r
-\r
-  res = mpca_grammar_st(grammar, &st);\r
+  \r
+  res = mpca_grammar_st(grammar, &st);  \r
   free(st.parsers);\r
   va_end(va);\r
   return res;\r
@@ -2991,28 +2991,28 @@ typedef struct {
 } mpca_stmt_t;\r
 \r
 static mpc_val_t *mpca_stmt_afold(int n, mpc_val_t **xs) {\r
-\r
+  \r
   mpca_stmt_t *stmt = malloc(sizeof(mpca_stmt_t));\r
   stmt->ident = ((char**)xs)[0];\r
   stmt->name = ((char**)xs)[1];\r
   stmt->grammar = ((mpc_parser_t**)xs)[3];\r
-\r
+  \r
   free(((char**)xs)[2]);\r
   free(((char**)xs)[4]);\r
-\r
+  \r
   return stmt;\r
 }\r
 \r
 static mpc_val_t *mpca_stmt_fold(int n, mpc_val_t **xs) {\r
-\r
+  \r
   int i;\r
   mpca_stmt_t **stmts = malloc(sizeof(mpca_stmt_t*) * (n+1));\r
-\r
+  \r
   for (i = 0; i < n; i++) {\r
     stmts[i] = xs[i];\r
   }\r
-  stmts[n] = NULL;\r
-\r
+  stmts[n] = NULL;  \r
+  \r
   return stmts;\r
 }\r
 \r
@@ -3021,11 +3021,11 @@ static void mpca_stmt_list_delete(mpc_val_t *x) {
   mpca_stmt_t **stmts = x;\r
 \r
   while(*stmts) {\r
-    mpca_stmt_t *stmt = *stmts;\r
+    mpca_stmt_t *stmt = *stmts; \r
     free(stmt->ident);\r
     free(stmt->name);\r
     mpc_soft_delete(stmt->grammar);\r
-    free(stmt);\r
+    free(stmt);  \r
     stmts++;\r
   }\r
   free(x);\r
@@ -3051,41 +3051,41 @@ static mpc_val_t *mpca_stmt_list_apply_to(mpc_val_t *x, void *s) {
     stmts++;\r
   }\r
   free(x);\r
-\r
+  \r
   return NULL;\r
 }\r
 \r
 static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) {\r
-\r
+  \r
   mpc_result_t r;\r
   mpc_err_t *e;\r
-  mpc_parser_t *Lang, *Stmt, *Grammar, *Term, *Factor, *Base;\r
-\r
+  mpc_parser_t *Lang, *Stmt, *Grammar, *Term, *Factor, *Base; \r
+  \r
   Lang    = mpc_new("lang");\r
   Stmt    = mpc_new("stmt");\r
   Grammar = mpc_new("grammar");\r
   Term    = mpc_new("term");\r
   Factor  = mpc_new("factor");\r
   Base    = mpc_new("base");\r
-\r
+  \r
   mpc_define(Lang, mpc_apply_to(\r
     mpc_total(mpc_predictive(mpc_many(mpca_stmt_fold, Stmt)), mpca_stmt_list_delete),\r
     mpca_stmt_list_apply_to, st\r
   ));\r
-\r
+  \r
   mpc_define(Stmt, mpc_and(5, mpca_stmt_afold,\r
     mpc_tok(mpc_ident()), mpc_maybe(mpc_tok(mpc_string_lit())), mpc_sym(":"), Grammar, mpc_sym(";"),\r
     free, free, free, mpc_soft_delete\r
   ));\r
-\r
+  \r
   mpc_define(Grammar, mpc_and(2, mpcaf_grammar_or,\r
       Term,\r
       mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_sym("|"), Grammar, free)),\r
       mpc_soft_delete\r
   ));\r
-\r
+  \r
   mpc_define(Term, mpc_many1(mpcaf_grammar_and, Factor));\r
-\r
+  \r
   mpc_define(Factor, mpc_and(2, mpcaf_grammar_repeat,\r
     Base,\r
       mpc_or(6,\r
@@ -3097,7 +3097,7 @@ static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) {
         mpc_pass()),\r
     mpc_soft_delete\r
   ));\r
-\r
+  \r
   mpc_define(Base, mpc_or(5,\r
     mpc_apply_to(mpc_tok(mpc_string_lit()), mpcaf_grammar_string, st),\r
     mpc_apply_to(mpc_tok(mpc_char_lit()),   mpcaf_grammar_char, st),\r
@@ -3105,16 +3105,16 @@ static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) {
     mpc_apply_to(mpc_tok_braces(mpc_or(2, mpc_digits(), mpc_ident()), free), mpcaf_grammar_id, st),\r
     mpc_tok_parens(Grammar, mpc_soft_delete)\r
   ));\r
-\r
-\r
+  \r
+  \r
   if (!mpc_parse_input(i, Lang, &r)) {\r
     e = r.error;\r
   } else {\r
     e = NULL;\r
   }\r
-\r
+  \r
   mpc_cleanup(6, Lang, Stmt, Grammar, Term, Factor, Base);\r
-\r
+  \r
   return e;\r
 }\r
 \r
@@ -3123,18 +3123,18 @@ mpc_err_t *mpca_lang_file(int flags, FILE *f, ...) {
   mpc_input_t *i;\r
   mpc_err_t *err;\r
 \r
-  va_list va;\r
+  va_list va;  \r
   va_start(va, f);\r
-\r
+  \r
   st.va = &va;\r
   st.parsers_num = 0;\r
   st.parsers = NULL;\r
   st.flags = flags;\r
-\r
+  \r
   i = mpc_input_new_file("<mpca_lang_file>", f);\r
   err = mpca_lang_st(i, &st);\r
   mpc_input_delete(i);\r
-\r
+  \r
   free(st.parsers);\r
   va_end(va);\r
   return err;\r
@@ -3145,75 +3145,75 @@ mpc_err_t *mpca_lang_pipe(int flags, FILE *p, ...) {
   mpc_input_t *i;\r
   mpc_err_t *err;\r
 \r
-  va_list va;\r
+  va_list va;  \r
   va_start(va, p);\r
-\r
+  \r
   st.va = &va;\r
   st.parsers_num = 0;\r
   st.parsers = NULL;\r
   st.flags = flags;\r
-\r
+  \r
   i = mpc_input_new_pipe("<mpca_lang_pipe>", p);\r
   err = mpca_lang_st(i, &st);\r
   mpc_input_delete(i);\r
-\r
+  \r
   free(st.parsers);\r
   va_end(va);\r
   return err;\r
 }\r
 \r
 mpc_err_t *mpca_lang(int flags, const char *language, ...) {\r
-\r
+  \r
   mpca_grammar_st_t st;\r
   mpc_input_t *i;\r
   mpc_err_t *err;\r
-\r
-  va_list va;\r
+  \r
+  va_list va;  \r
   va_start(va, language);\r
-\r
+  \r
   st.va = &va;\r
   st.parsers_num = 0;\r
   st.parsers = NULL;\r
   st.flags = flags;\r
-\r
+  \r
   i = mpc_input_new_string("<mpca_lang>", language);\r
   err = mpca_lang_st(i, &st);\r
   mpc_input_delete(i);\r
-\r
+  \r
   free(st.parsers);\r
   va_end(va);\r
   return err;\r
 }\r
 \r
 mpc_err_t *mpca_lang_contents(int flags, const char *filename, ...) {\r
-\r
+  \r
   mpca_grammar_st_t st;\r
   mpc_input_t *i;\r
   mpc_err_t *err;\r
-\r
+  \r
   va_list va;\r
 \r
   FILE *f = fopen(filename, "rb");\r
-\r
+  \r
   if (f == NULL) {\r
     return mpc_err_fail(filename, mpc_state_new(), "Unable to open file!");\r
   }\r
-\r
+  \r
   va_start(va, filename);\r
-\r
+  \r
   st.va = &va;\r
   st.parsers_num = 0;\r
   st.parsers = NULL;\r
   st.flags = flags;\r
-\r
+  \r
   i = mpc_input_new_file(filename, f);\r
   err = mpca_lang_st(i, &st);\r
   mpc_input_delete(i);\r
-\r
+  \r
   free(st.parsers);\r
-  va_end(va);\r
-\r
+  va_end(va);  \r
+  \r
   fclose(f);\r
-\r
+  \r
   return err;\r
 }\r
diff --git a/source/sclpl/scanner.c b/source/sclpl/scanner.c
new file mode 100644 (file)
index 0000000..fcfe78f
--- /dev/null
@@ -0,0 +1,123 @@
+#include "scanner.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.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);
+static char* scanner_dup(scanner_t* p_scanner, size_t start_idx, size_t len);
+
+scanner_t* scanner_new(char* p_prompt, FILE* p_file) {
+    scanner_t* p_scanner = (scanner_t*)malloc(sizeof(scanner_t));
+    p_scanner->p_line   = NULL;
+    p_scanner->index    = 0;
+    p_scanner->p_input  = p_file;
+    p_scanner->p_prompt = p_prompt;
+    return p_scanner;
+}
+
+char* scanner_read(scanner_t* p_scanner) {
+    char* p_tok = NULL;
+    scanner_skip_ws(p_scanner);
+    if (!scanner_eof(p_scanner)) {
+        if (scanner_oneof(p_scanner, "()[]{};,'\"")) {
+            p_tok = scanner_dup(p_scanner, p_scanner->index, 1);
+            p_scanner->index++;
+        } else {
+            size_t start =  p_scanner->index;
+            while(!scanner_oneof(p_scanner," \t\r\n()[];,'\"")) {
+                p_scanner->index++;
+            }
+            p_tok = scanner_dup(p_scanner, start, p_scanner->index - start);
+        }
+    }
+    return p_tok;
+}
+
+bool scanner_eof(scanner_t* p_scanner)
+{
+    return (scanner_eol(p_scanner) && feof(p_scanner->p_input));
+}
+
+bool scanner_eol(scanner_t* p_scanner)
+{
+    bool ret = true;
+    size_t index = p_scanner->index;
+    char ch;
+    while((NULL != p_scanner->p_line) && ('\0' != (ch = p_scanner->p_line[index]))) {
+        if((' '!=ch) && ('\t'!=ch) && ('\r'!=ch) && ('\n'!=ch)) {
+            ret = false;
+            break;
+        }
+        index++;
+    }
+    return ret;
+}
+
+static void scanner_getline(scanner_t* p_scanner) {
+    int c;
+    size_t capacity = 8;
+    size_t index    = 0;
+    /* Reallocate and clear the line buffer */
+    p_scanner->p_line = realloc(p_scanner->p_line, capacity);
+    p_scanner->p_line[0] = '\0';
+    p_scanner->index = 0;
+
+    /* If we have not yet reached the end of the file, read the next line */
+    if (!scanner_eof(p_scanner)) {
+        if (NULL != p_scanner->p_prompt)
+            printf("%s", p_scanner->p_prompt);
+        while(('\n' != (c = fgetc(p_scanner->p_input))) && (EOF != c)) {
+            if (index+2 == capacity) {
+                capacity <<= 1u;
+                p_scanner->p_line = realloc(p_scanner->p_line, capacity);
+            }
+            p_scanner->p_line[index++] = c;
+        }
+        p_scanner->p_line[index++] = (c == EOF) ? '\0' : c;
+        p_scanner->p_line[index++] = '\0';
+        p_scanner->index = 0;
+    }
+}
+
+static void scanner_skip_ws(scanner_t* p_scanner) {
+    /* If we haven't read a line yet, read one now */
+    if (NULL == p_scanner->p_line)
+        scanner_getline(p_scanner);
+    while('\0' == scanner_current(p_scanner) || scanner_oneof(p_scanner, " \t\r\n")) {
+        if ('\0' == scanner_current(p_scanner) && !scanner_eof(p_scanner)) {
+            scanner_getline(p_scanner);
+        } else {
+            p_scanner->index++;
+        }
+    }
+}
+
+static char scanner_current(scanner_t* p_scanner) {
+    return p_scanner->p_line[p_scanner->index];
+}
+
+static bool scanner_oneof(scanner_t* p_scanner, const char* p_set) {
+    bool ret = false;
+    size_t sz = strlen(p_set);
+    for (size_t idx = 0; idx < sz; idx++) {
+        if (scanner_current(p_scanner) == p_set[idx]) {
+            ret = true;
+            break;
+        }
+    }
+    return ret;
+}
+
+static char* scanner_dup(scanner_t* p_scanner, size_t start_idx, size_t len) {
+    char* p_str = (char*)malloc(len+1);
+    memcpy(p_str, &(p_scanner->p_line[start_idx]), len);
+    p_str[len] = '\0';
+    return p_str;
+}
+
diff --git a/source/sclpl/scanner.h b/source/sclpl/scanner.h
new file mode 100644 (file)
index 0000000..0cc14f1
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+  @file scanner.h
+  @brief TODO: Describe this file
+  $Revision$
+  $HeadURL$
+  */
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct {
+    char* p_line;
+    size_t index;
+    FILE* p_input;
+    char* p_prompt;
+} scanner_t;
+
+scanner_t* scanner_new(char* p_prompt, FILE* p_file);
+
+char* scanner_read(scanner_t* p_scanner);
+
+bool scanner_eof(scanner_t* p_scanner);
+
+bool scanner_eol(scanner_t* p_scanner);
+
+#endif /* SCANNER_H */