mumble

A Lisp written in C, following the *Build Your Own Lisp* book
Log | Files | Refs | README

core.c (7011B)


      1 #include "ptest.h"
      2 #include "../mpc.h"
      3 
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 static int int_eq(const void* x, const void* y) { return (*(int*)x == *(int*)y); }
      8 static void int_print(const void* x) { printf("'%i'", *((int*)x)); }
      9 static int streq(const void* x, const void* y) { return (strcmp(x, y) == 0); }
     10 static void strprint(const void* x) { printf("'%s'", (char*)x); }
     11 
     12 void test_ident(void) {
     13 
     14   /* ^[a-zA-Z_][a-zA-Z0-9_]*$ */
     15 
     16   mpc_parser_t* Ident = mpc_whole(
     17     mpc_and(2, mpcf_strfold,
     18       mpc_or(2, mpc_alpha(), mpc_underscore()),
     19       mpc_many1(mpcf_strfold, mpc_or(3, mpc_alpha(), mpc_underscore(), mpc_digit())),
     20       free),
     21     free
     22   );
     23 
     24   PT_ASSERT(mpc_test_pass(Ident, "test", "test", streq, free, strprint));
     25   PT_ASSERT(mpc_test_fail(Ident, "  blah", "", streq, free, strprint));
     26   PT_ASSERT(mpc_test_pass(Ident, "anoth21er", "anoth21er", streq, free, strprint));
     27   PT_ASSERT(mpc_test_pass(Ident, "du__de", "du__de", streq, free, strprint));
     28   PT_ASSERT(mpc_test_fail(Ident, "some spaces", "", streq, free, strprint));
     29   PT_ASSERT(mpc_test_fail(Ident, "", "", streq, free, strprint));
     30   PT_ASSERT(mpc_test_fail(Ident, "18nums", "", streq, free, strprint));
     31 
     32   mpc_delete(Ident);
     33 
     34 }
     35 
     36 static mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) {
     37   int **vs = (int**)xs;
     38   (void) n;
     39 
     40   switch(((char*)xs[1])[0])
     41   {
     42     case '*': { *vs[0] *= *vs[2]; }; break;
     43     case '/': { *vs[0] /= *vs[2]; }; break;
     44     case '%': { *vs[0] %= *vs[2]; }; break;
     45     case '+': { *vs[0] += *vs[2]; }; break;
     46     case '-': { *vs[0] -= *vs[2]; }; break;
     47     default: break;
     48   }
     49 
     50   free(xs[1]); free(xs[2]);
     51 
     52   return xs[0];
     53 }
     54 
     55 void test_maths(void) {
     56 
     57   mpc_parser_t *Expr, *Factor, *Term, *Maths;
     58   int r0 = 1, r1 = 5, r2 = 13, r3 = 0, r4 = 2;
     59 
     60   Expr   = mpc_new("expr");
     61   Factor = mpc_new("factor");
     62   Term   = mpc_new("term");
     63   Maths  = mpc_new("maths");
     64 
     65   mpc_define(Expr, mpc_or(2,
     66     mpc_and(3, mpcf_maths, Factor, mpc_oneof("+-"), Factor, free, free),
     67     Factor
     68   ));
     69 
     70   mpc_define(Factor, mpc_or(2,
     71     mpc_and(3, mpcf_maths, Term, mpc_oneof("*/"), Term, free, free),
     72     Term
     73   ));
     74 
     75   mpc_define(Term, mpc_or(2,
     76     mpc_int(),
     77     mpc_parens(Expr, free)
     78   ));
     79 
     80   mpc_define(Maths, mpc_whole(Expr, free));
     81 
     82   PT_ASSERT(mpc_test_pass(Maths, "1", &r0, int_eq, free, int_print));
     83   PT_ASSERT(mpc_test_pass(Maths, "(5)", &r1, int_eq, free, int_print));
     84   PT_ASSERT(mpc_test_pass(Maths, "(4*2)+5", &r2, int_eq, free, int_print));
     85   PT_ASSERT(mpc_test_pass(Maths, "4*2+5", &r2, int_eq, free, int_print));
     86   PT_ASSERT(mpc_test_fail(Maths, "a", &r3, int_eq, free, int_print));
     87   PT_ASSERT(mpc_test_fail(Maths, "2b+4", &r4, int_eq, free, int_print));
     88 
     89   mpc_cleanup(4, Expr, Factor, Term, Maths);
     90 }
     91 
     92 void test_strip(void) {
     93 
     94   mpc_parser_t *Stripperl = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtriml);
     95   mpc_parser_t *Stripperr = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtrimr);
     96   mpc_parser_t *Stripper  = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtrim);
     97 
     98   PT_ASSERT(mpc_test_pass(Stripperl, " asdmlm dasd  ", "asdmlm dasd  ", streq, free, strprint));
     99   PT_ASSERT(mpc_test_pass(Stripperr, " asdmlm dasd  ", " asdmlm dasd", streq, free, strprint));
    100   PT_ASSERT(mpc_test_pass(Stripper,  " asdmlm dasd  ", "asdmlm dasd", streq, free, strprint));
    101 
    102   mpc_delete(Stripperl);
    103   mpc_delete(Stripperr);
    104   mpc_delete(Stripper);
    105 
    106 }
    107 
    108 void test_repeat(void) {
    109 
    110   int success;
    111   mpc_result_t r;
    112   mpc_parser_t *p = mpc_count(3, mpcf_strfold, mpc_digit(), free);
    113 
    114   success = mpc_parse("test", "046", p, &r);
    115   PT_ASSERT(success);
    116   PT_ASSERT_STR_EQ(r.output, "046");
    117   free(r.output);
    118 
    119   success = mpc_parse("test", "046aa", p, &r);
    120   PT_ASSERT(success);
    121   PT_ASSERT_STR_EQ(r.output, "046");
    122   free(r.output);
    123 
    124   success = mpc_parse("test", "04632", p, &r);
    125   PT_ASSERT(success);
    126   PT_ASSERT_STR_EQ(r.output, "046");
    127   free(r.output);
    128 
    129   success = mpc_parse("test", "04", p, &r);
    130   PT_ASSERT(!success);
    131   mpc_err_delete(r.error);
    132 
    133   mpc_delete(p);
    134 
    135 }
    136 
    137 void test_copy(void) {
    138 
    139   int success;
    140   mpc_result_t r;
    141   mpc_parser_t* p = mpc_or(2, mpc_char('a'), mpc_char('b'));
    142   mpc_parser_t* q = mpc_and(2, mpcf_strfold, p, mpc_copy(p), free);
    143 
    144   success = mpc_parse("test", "aa", q, &r);
    145   PT_ASSERT(success);
    146   PT_ASSERT_STR_EQ(r.output, "aa");
    147   free(r.output);
    148 
    149   success = mpc_parse("test", "bb", q, &r);
    150   PT_ASSERT(success);
    151   PT_ASSERT_STR_EQ(r.output, "bb");
    152   free(r.output);
    153 
    154   success = mpc_parse("test", "ab", q, &r);
    155   PT_ASSERT(success);
    156   PT_ASSERT_STR_EQ(r.output, "ab");
    157   free(r.output);
    158 
    159   success = mpc_parse("test", "ba", q, &r);
    160   PT_ASSERT(success);
    161   PT_ASSERT_STR_EQ(r.output, "ba");
    162   free(r.output);
    163 
    164   success = mpc_parse("test", "c", p, &r);
    165   PT_ASSERT(!success);
    166   mpc_err_delete(r.error);
    167 
    168   mpc_delete(mpc_copy(p));
    169   mpc_delete(mpc_copy(q));
    170 
    171   mpc_delete(q);
    172 
    173 }
    174 
    175 static int line_count = 0;
    176 
    177 static mpc_val_t* read_line(mpc_val_t* line) {
    178   line_count++;
    179   return line;
    180 }
    181 
    182 void test_reader(void) {
    183 
    184   mpc_parser_t* Line = mpc_many(
    185     mpcf_strfold,
    186     mpc_apply(mpc_re("[^\\n]*(\\n|$)"), read_line));
    187 
    188   line_count = 0;
    189 
    190   PT_ASSERT(mpc_test_pass(Line,
    191     "hello\nworld\n\nthis\nis\ndan",
    192     "hello\nworld\n\nthis\nis\ndan", streq, free, strprint));
    193 
    194   PT_ASSERT(line_count == 6);
    195 
    196   line_count = 0;
    197 
    198   PT_ASSERT(mpc_test_pass(Line,
    199     "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg",
    200     "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", streq, free, strprint));
    201 
    202   PT_ASSERT(line_count == 7);
    203 
    204   mpc_delete(Line);
    205 
    206 }
    207 
    208 static int token_count = 0;
    209 
    210 static mpc_val_t *print_token(mpc_val_t *x) {
    211   /*printf("Token: '%s'\n", (char*)x);*/
    212   token_count++;
    213   return x;
    214 }
    215 
    216 void test_tokens(void) {
    217 
    218   mpc_parser_t* Tokens = mpc_many(
    219     mpcf_strfold,
    220     mpc_apply(mpc_strip(mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")), print_token));
    221 
    222   token_count = 0;
    223 
    224   PT_ASSERT(mpc_test_pass(Tokens,
    225     "  hello 4352 ,  \n foo.bar   \n\n  test:ing   ",
    226     "hello4352,foo.bartest:ing", streq, free, strprint));
    227 
    228   PT_ASSERT(token_count == 9);
    229 
    230   mpc_delete(Tokens);
    231 
    232 }
    233 
    234 void test_eoi(void) {
    235 
    236   mpc_parser_t* Line = mpc_re("[^\\n]*$");
    237 
    238   PT_ASSERT(mpc_test_pass(Line, "blah", "blah", streq, free, strprint));
    239   PT_ASSERT(mpc_test_pass(Line, "blah\n", "blah\n", streq, free, strprint));
    240 
    241   mpc_delete(Line);
    242 
    243 }
    244 
    245 void suite_core(void) {
    246   pt_add_test(test_ident,  "Test Ident",  "Suite Core");
    247   pt_add_test(test_maths,  "Test Maths",  "Suite Core");
    248   pt_add_test(test_strip,  "Test Strip",  "Suite Core");
    249   pt_add_test(test_repeat, "Test Repeat", "Suite Core");
    250   pt_add_test(test_copy,   "Test Copy",   "Suite Core");
    251   pt_add_test(test_reader, "Test Reader", "Suite Core");
    252   pt_add_test(test_tokens, "Test Tokens", "Suite Core");
    253   pt_add_test(test_eoi,    "Test EOI",    "Suite Core");
    254 }