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 CC = gcc
CFLAGS = -ansi -Wall -Werror -Wno-unused -g CFLAGS = -ansi -Wall -Wpedantic -Werror -Wno-unused -g
TESTS = $(wildcard tests/*.c) 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 ** mpc - Micro Parser Combinator library for C
**
** https://github.com/orangeduck/mpc ** https://github.com/orangeduck/mpc
**
** Daniel Holden - contact@daniel-holden.com ** Daniel Holden - contact@daniel-holden.com
** Licensed under BSD3 ** Licensed under BSD3
*/ */
#ifndef mpc_h #ifndef mpc_h
#define mpc_h #define mpc_h
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
/* /*
** Error Type ** Error Type
@@ -45,9 +48,9 @@ typedef union {
struct mpc_parser_t; struct mpc_parser_t;
typedef struct mpc_parser_t 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); int 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); int 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_filename(const char* filename, mpc_parser_t* p, mpc_result_t* r);
/* /*
** Function Types ** 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_range(char s, char e);
mpc_parser_t* mpc_oneof(const char* s); mpc_parser_t* mpc_oneof(const char* s);
mpc_parser_t* mpc_noneof(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); 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_add_child(mpc_ast_t* r, mpc_ast_t* a);
void mpc_ast_tag(mpc_ast_t* a, const char* t); void mpc_ast_tag(mpc_ast_t* a, const char* t);
void mpc_ast_print(mpc_ast_t* a); 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_fold_ast(mpc_val_t* a, mpc_val_t* b);
mpc_val_t* mpcf_afold_ast(int n, mpc_val_t** as); 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 ** Testing
*/ */
bool mpc_unmatch(mpc_parser_t* p, const char* s, void* d, int mpc_unmatch(mpc_parser_t* p, const char* s, void* d,
bool(*tester)(void*, void*), int(*tester)(void*, void*),
mpc_dtor_t destructor, mpc_dtor_t destructor,
void(*printer)(void*)); void(*printer)(void*));
bool mpc_match(mpc_parser_t* p, const char* s, void* d, int mpc_match(mpc_parser_t* p, const char* s, void* d,
bool(*tester)(void*, void*), int(*tester)(void*, void*),
mpc_dtor_t destructor, mpc_dtor_t destructor,
void(*printer)(void*)); void(*printer)(void*));

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,15 @@
#ifndef ptest_h #ifndef ptest_h
#define ptest_h #define ptest_h
#include <stdbool.h>
#include <string.h> #include <string.h>
#define PT_SUITE(name) void name(void) #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_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__) #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_test(void (*func)(void), const char* name, const char* suite);
void pt_add_suite(void (*func)(void)); void pt_add_suite(void (*func)(void));

View File

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