strictly ansi C now

This commit is contained in:
Daniel Holden
2013-09-30 20:55:57 +01:00
parent 3933a3a1bd
commit a625db585d
8 changed files with 452 additions and 331 deletions

View File

@@ -1,5 +1,5 @@
CC = gcc
CFLAGS = -ansi -Wall -Werror -Wno-unused -g
CFLAGS = -ansi -Wall -Wpedantic -Werror -Wno-unused -g
TESTS = $(wildcard tests/*.c)

600
mpc.c

File diff suppressed because it is too large Load Diff

25
mpc.h
View File

@@ -1,16 +1,19 @@
/*
** mpc - Micro Parser Combinator library for C
**
** https://github.com/orangeduck/mpc
**
** Daniel Holden - contact@daniel-holden.com
** Licensed under BSD3
*/
#ifndef mpc_h
#define mpc_h
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
/*
** Error Type
@@ -45,9 +48,9 @@ typedef union {
struct mpc_parser_t;
typedef struct mpc_parser_t mpc_parser_t;
bool mpc_parse(const char* filename, const char* s, mpc_parser_t* p, mpc_result_t* r);
bool mpc_parse_file(const char* filename, FILE* f, mpc_parser_t* p, mpc_result_t* r);
bool mpc_parse_filename(const char* filename, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse(const char* filename, const char* s, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse_file(const char* filename, FILE* f, mpc_parser_t* p, mpc_result_t* r);
int mpc_parse_filename(const char* filename, mpc_parser_t* p, mpc_result_t* r);
/*
** Function Types
@@ -88,7 +91,7 @@ mpc_parser_t* mpc_char(char c);
mpc_parser_t* mpc_range(char s, char e);
mpc_parser_t* mpc_oneof(const char* s);
mpc_parser_t* mpc_noneof(const char* s);
mpc_parser_t* mpc_satisfy(bool(*f)(char));
mpc_parser_t* mpc_satisfy(int(*f)(char));
mpc_parser_t* mpc_string(const char* s);
/*
@@ -247,7 +250,7 @@ mpc_ast_t* mpc_ast_insert_root(mpc_ast_t* a);
void mpc_ast_add_child(mpc_ast_t* r, mpc_ast_t* a);
void mpc_ast_tag(mpc_ast_t* a, const char* t);
void mpc_ast_print(mpc_ast_t* a);
bool mpc_ast_eq(mpc_ast_t* a, mpc_ast_t* b);
int mpc_ast_eq(mpc_ast_t* a, mpc_ast_t* b);
mpc_val_t* mpcf_fold_ast(mpc_val_t* a, mpc_val_t* b);
mpc_val_t* mpcf_afold_ast(int n, mpc_val_t** as);
@@ -274,13 +277,13 @@ mpc_err_t* mpca_lang_file(const char* filename, ...);
** Testing
*/
bool mpc_unmatch(mpc_parser_t* p, const char* s, void* d,
bool(*tester)(void*, void*),
int mpc_unmatch(mpc_parser_t* p, const char* s, void* d,
int(*tester)(void*, void*),
mpc_dtor_t destructor,
void(*printer)(void*));
bool mpc_match(mpc_parser_t* p, const char* s, void* d,
bool(*tester)(void*, void*),
int mpc_match(mpc_parser_t* p, const char* s, void* d,
int(*tester)(void*, void*),
mpc_dtor_t destructor,
void(*printer)(void*));

View File

@@ -4,9 +4,9 @@
#include <stdlib.h>
#include <string.h>
static bool int_eq(void* x, void* y) { return (*(int*)x == *(int*)y); }
static int int_eq(void* x, void* y) { return (*(int*)x == *(int*)y); }
static void int_print(void* x) { printf("'%i'", *((int*)x)); }
static bool string_eq(void* x, void* y) { return (strcmp(x, y) == 0); }
static int string_eq(void* x, void* y) { return (strcmp(x, y) == 0); }
static void string_print(void* x) { printf("'%s'", (char*)x); }
void test_ident(void) {
@@ -34,11 +34,18 @@ void test_ident(void) {
}
void test_maths(void) {
mpc_parser_t* Expr = mpc_new("expr");
mpc_parser_t* Factor = mpc_new("factor");
mpc_parser_t* Term = mpc_new("term");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr, *Factor, *Term, *Maths;
int r0 = 1;
int r1 = 5;
int r2 = 13;
int r3 = 0;
int r4 = 2;
Expr = mpc_new("expr");
Factor = mpc_new("factor");
Term = mpc_new("term");
Maths = mpc_new("maths");
mpc_define(Expr, mpc_else(
mpc_and(3, mpcf_maths, Factor, mpc_oneof("*/"), Factor, free, free),
@@ -57,11 +64,11 @@ void test_maths(void) {
mpc_define(Maths, mpc_enclose(Expr, free));
PT_ASSERT(mpc_match(Maths, "1", (int[]){ 1 }, int_eq, free, int_print));
PT_ASSERT(mpc_match(Maths, "(5)", (int[]){ 5 }, int_eq, free, int_print));
PT_ASSERT(mpc_match(Maths, "(4*2)+5", (int[]){ 13 }, int_eq, free, int_print));
PT_ASSERT(mpc_unmatch(Maths, "a", (int[]){ 0 }, int_eq, free, int_print));
PT_ASSERT(mpc_unmatch(Maths, "2b+4", (int[]){ 2 }, int_eq, free, int_print));
PT_ASSERT(mpc_match(Maths, "1", &r0, int_eq, free, int_print));
PT_ASSERT(mpc_match(Maths, "(5)", &r1, int_eq, free, int_print));
PT_ASSERT(mpc_match(Maths, "(4*2)+5", &r2, int_eq, free, int_print));
PT_ASSERT(mpc_unmatch(Maths, "a", &r3, int_eq, free, int_print));
PT_ASSERT(mpc_unmatch(Maths, "2b+4", &r4, int_eq, free, int_print));
mpc_cleanup(4, Expr, Factor, Term, Maths);
}

View File

@@ -3,24 +3,27 @@
void test_grammar(void) {
mpc_parser_t* Expr = mpc_new("expression");
mpc_parser_t* Prod = mpc_new("product");
mpc_parser_t* Value = mpc_new("value");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr, *Prod, *Value, *Maths;
mpc_ast_t *t0, *t1, *t2;
Expr = mpc_new("expression");
Prod = mpc_new("product");
Value = mpc_new("value");
Maths = mpc_new("maths");
mpc_define(Expr, mpca_grammar(" <product> (('+' | '-') <product>)* ", Prod));
mpc_define(Prod, mpca_grammar(" <value> (('*' | '/') <value>)* ", Value));
mpc_define(Value, mpca_grammar(" /[0-9]+/ | '(' <expression> ')' ", Expr));
mpc_define(Maths, mpca_total(Expr));
mpc_ast_t* t0 = mpc_ast_build(1, "root", mpc_ast_new("value", "24"));
mpc_ast_t* t1 = mpc_ast_build(1, "root",
t0 = mpc_ast_build(1, "root", mpc_ast_new("value", "24"));
t1 = mpc_ast_build(1, "root",
mpc_ast_build(3, "value",
mpc_ast_new("char", "("),
mpc_ast_new("value", "5"),
mpc_ast_new("char", ")")));
mpc_ast_t* t2 = mpc_ast_build(3, "root",
t2 = mpc_ast_build(3, "root",
mpc_ast_build(3, "value",
mpc_ast_new("char", "("),
@@ -39,12 +42,12 @@ void test_grammar(void) {
mpc_ast_new("char", "+"),
mpc_ast_new("value", "5"));
PT_ASSERT(mpc_match(Maths, " 24 ", t0, (bool(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_match(Maths, "(5)", t1, (bool(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_match(Maths, "(4 * 2 * 11 + 2) + 5", t2, (bool(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_unmatch(Maths, "a", t0, (bool(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_unmatch(Maths, "2b+4", t0, (bool(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_match(Maths, " 24 ", t0, (int(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_match(Maths, "(5)", t1, (int(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_match(Maths, "(4 * 2 * 11 + 2) + 5", t2, (int(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_unmatch(Maths, "a", t0, (int(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
PT_ASSERT(mpc_unmatch(Maths, "2b+4", t0, (int(*)(void*,void*))mpc_ast_eq, (mpc_dtor_t)mpc_ast_delete, (void(*)(void*))mpc_ast_print));
mpc_ast_delete(t0);
mpc_ast_delete(t1);
@@ -56,10 +59,12 @@ void test_grammar(void) {
void test_language(void) {
mpc_parser_t* Expr = mpc_new("expression");
mpc_parser_t* Prod = mpc_new("product");
mpc_parser_t* Value = mpc_new("value");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr, *Prod, *Value, *Maths;
Expr = mpc_new("expression");
Prod = mpc_new("product");
Value = mpc_new("value");
Maths = mpc_new("maths");
mpca_lang(
" \
@@ -75,10 +80,12 @@ void test_language(void) {
void test_language_file(void) {
mpc_parser_t* Expr = mpc_new("expression");
mpc_parser_t* Prod = mpc_new("product");
mpc_parser_t* Value = mpc_new("value");
mpc_parser_t* Maths = mpc_new("maths");
mpc_parser_t *Expr, *Prod, *Value, *Maths;
Expr = mpc_new("expression");
Prod = mpc_new("product");
Value = mpc_new("value");
Maths = mpc_new("maths");
mpca_lang_file("./tests/maths.grammar", Expr, Prod, Value, Maths);

View File

@@ -8,12 +8,20 @@
/* Globals */
#define MAX_NAME 512
#define MAX_ERROR 2048
#define MAX_TESTS 2048
enum {
MAX_NAME = 512
};
static bool test_passing = false;
static bool suite_passing = false;
enum {
MAX_ERROR = 2048
};
enum {
MAX_TESTS = 2048
};
static int test_passing = 0;
static int suite_passing = 0;
/* Colors */
@@ -33,7 +41,7 @@ enum {
LIGHT_RED = 0xC,
LIGHT_PURPLE = 0xD,
LIGHT_YELLOW = 0xE,
LIGHT_WHITE = 0xF,
LIGHT_WHITE = 0xF
};
#ifdef _WIN32
@@ -84,7 +92,7 @@ static char assert_err[MAX_ERROR];
static char assert_err_buff[MAX_ERROR];
static int assert_err_num = 0;
void pt_assert_run(bool result, const char* expr, const char* func, const char* file, int line) {
void pt_assert_run(int result, const char* expr, const char* func, const char* file, int line) {
num_asserts++;
test_passing = test_passing && result;
@@ -102,7 +110,7 @@ void pt_assert_run(bool result, const char* expr, const char* func, const char*
static void ptest_signal(int sig) {
test_passing = false;
test_passing = 0;
switch( sig ) {
case SIGFPE: sprintf(assert_err_buff, " %i. Division by Zero\n", assert_err_num+1); break;
@@ -125,15 +133,15 @@ static void ptest_signal(int sig) {
static void pt_title_case(char* output, const char* input) {
bool space = true;
int space = 1;
unsigned int i;
strcpy(output, input);
unsigned int i;
for(i = 0; i < strlen(output); i++) {
if (output[i] == '_' || output[i] == ' ') {
space = true;
space = 1;
output[i] = ' ';
continue;
}
@@ -143,7 +151,7 @@ static void pt_title_case(char* output, const char* input) {
continue;
}
space = false;
space = 0;
}
}
@@ -162,6 +170,8 @@ static int num_tests_fails = 0;
void pt_add_test(void (*func)(void), const char* name, const char* suite) {
test_t test;
if (num_tests == MAX_TESTS) {
printf("ERROR: Exceeded maximum test count of %i!\n", MAX_TESTS); abort();
}
@@ -174,7 +184,6 @@ void pt_add_test(void (*func)(void), const char* name, const char* suite) {
printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n", suite, MAX_NAME); abort();
}
test_t test;
test.func = func;
pt_title_case(test.name, name);
pt_title_case(test.suite, suite);
@@ -202,6 +211,9 @@ static char current_suite[MAX_NAME];
int pt_run(void) {
unsigned int i;
double total;
printf(" \n");
printf(" +-------------------------------------------+\n");
printf(" | ptest MicroTesting Magic for C |\n");
@@ -218,7 +230,6 @@ int pt_run(void) {
start = clock();
strcpy(current_suite, "");
unsigned int i;
for(i = 0; i < num_tests; i++) {
test_t test = tests[i];
@@ -235,14 +246,14 @@ int pt_run(void) {
}
}
suite_passing = true;
suite_passing = 1;
strcpy(current_suite, test.suite);
printf("\n\n ===== %s =====\n\n", current_suite);
}
/* Run Test */
test_passing = true;
test_passing = 1;
strcpy(assert_err, "");
strcpy(assert_err_buff, "");
assert_err_num = 0;
@@ -293,7 +304,7 @@ int pt_run(void) {
printf(" +---------++------------+-------------+-------------+\n");
printf(" \n");
double total = (double)(end - start) / CLOCKS_PER_SEC;
total = (double)(end - start) / CLOCKS_PER_SEC;
printf(" Total Running Time: %0.3fs\n\n", total);

View File

@@ -1,16 +1,15 @@
#ifndef ptest_h
#define ptest_h
#include <stdbool.h>
#include <string.h>
#define PT_SUITE(name) void name(void)
#define PT_TEST(name) auto void name(void); pt_add_test(name, #name, __func__); void name(void)
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
#define PT_ASSERT(expr) pt_assert_run((int)(expr), #expr, __func__, __FILE__, __LINE__)
#define PT_ASSERT_STR_EQ(fst, snd) pt_assert_run(strcmp(fst, snd) == 0, "strcmp( " #fst ", " #snd " ) == 0", __func__, __FILE__, __LINE__)
void pt_assert_run(bool result, const char* expr, const char* func, const char* file, int line);
void pt_assert_run(int result, const char* expr, const char* func, const char* file, int line);
void pt_add_test(void (*func)(void), const char* name, const char* suite);
void pt_add_suite(void (*func)(void));

View File

@@ -4,17 +4,19 @@
#include <string.h>
#include <stdlib.h>
static bool string_eq(void* x, void* y) { return (strcmp(x, y) == 0); }
static int string_eq(void* x, void* y) { return (strcmp(x, y) == 0); }
static void string_print(void* x) { printf("'%s'", (char*)x); }
void test_regex_basic(void) {
mpc_parser_t* re0 = mpc_re("abc|bcd");
mpc_parser_t* re1 = mpc_re("abc|bcd|e");
mpc_parser_t* re2 = mpc_re("ab()c(ab)*");
mpc_parser_t* re3 = mpc_re("abc(abdd)?");
mpc_parser_t* re4 = mpc_re("ab|c(abdd)?");
mpc_parser_t* re5 = mpc_re("abc(ab|dd)+g$");
mpc_parser_t *re0, *re1, *re2, *re3, *re4, *re5;
re0 = mpc_re("abc|bcd");
re1 = mpc_re("abc|bcd|e");
re2 = mpc_re("ab()c(ab)*");
re3 = mpc_re("abc(abdd)?");
re4 = mpc_re("ab|c(abdd)?");
re5 = mpc_re("abc(ab|dd)+g$");
PT_ASSERT(mpc_match(re0, "abc", "abc", string_eq, free, string_print));
PT_ASSERT(mpc_match(re0, "bcd", "bcd", string_eq, free, string_print));
@@ -36,10 +38,12 @@ void test_regex_basic(void) {
void test_regex_range(void) {
mpc_parser_t* re0 = mpc_re("abg[abcdef]");
mpc_parser_t* re1 = mpc_re("y*[a-z]");
mpc_parser_t* re2 = mpc_re("zz(p+)?[A-Z_0\\]123]*");
mpc_parser_t* re3 = mpc_re("^[^56hy].*$");
mpc_parser_t *re0, *re1, *re2, *re3, *re4;
re0 = mpc_re("abg[abcdef]");
re1 = mpc_re("y*[a-z]");
re2 = mpc_re("zz(p+)?[A-Z_0\\]123]*");
re3 = mpc_re("^[^56hy].*$");
/* TODO: Testing */