#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;
}
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
}\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
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
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
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
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
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
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
*/\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
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
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
}\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
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
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
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
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
x++;\r
}\r
mpc_input_unmark(i);\r
-\r
+ \r
*o = malloc(strlen(c) + 1);\r
strcpy(*o, c);\r
return 1;\r
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
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
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
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
\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
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
** 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
#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
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
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
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
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
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
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
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
}\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
}\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
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
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
}\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
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
\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
}\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
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
}\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
** 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
*/\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
}\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
** 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
\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
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
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
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
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
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
** 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
** ### Regular Expression Grammar\r
**\r
** <regex> : <term> | (<term> "|" <regex>)\r
-**\r
+** \r
** <term> : <factor>*\r
**\r
** <factor> : <base>\r
** | <base> "+"\r
** | <base> "?"\r
** | <base> "{" <digits> "}"\r
-**\r
+** \r
** <base> : <char>\r
** | "\" <char>\r
** | "(" <regex> ")"\r
}\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
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
}\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
free(s);\r
return p;\r
}\r
-\r
+ \r
/* Regex Standard */\r
p = mpc_char(s[0]);\r
free(s);\r
}\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
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
} 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
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
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
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
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
}\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
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
}\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
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
}\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
}\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
*/\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
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
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
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
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
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
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
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
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
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
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
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
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
*/\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
}\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
}\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
}\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
}\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
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
** ### Grammar Grammar\r
**\r
** <grammar> : (<term> "|" <grammar>) | <term>\r
-**\r
+** \r
** <term> : <factor>*\r
**\r
** <factor> : <base>\r
** | <base> "+"\r
** | <base> "?"\r
** | <base> "{" <digits> "}"\r
-**\r
+** \r
** <base> : "<" (<digits> | <ident>) ">"\r
** | <string_lit>\r
** | <char_lit>\r
\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
}\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
}\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
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
}\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
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
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
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
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
} 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
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
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
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
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
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
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