erpli.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // common state:
  2. // TODO check internal functions considering the atoms admit tables now
  3. static int lastchar = -1;
  4. static Table *globals = NULL;
  5. static List *stack = NULL;
  6. static int nil_symb[] = {3,'n','i','l'};
  7. // basic input:
  8. int _getchar () {
  9. int ch = getchar();
  10. if (ch == -1)
  11. exit(0);
  12. return ch;
  13. }
  14. Atom* _warning (char* msg) {
  15. puts(msg);
  16. return NULL;
  17. }
  18. Atom* _error (char* msg) {
  19. puts(msg);
  20. exit(1);
  21. return NULL;
  22. }
  23. // printing:
  24. void print_symbol (int* symb) {
  25. for (int a = 1; a <= symb[0]; a++)
  26. putchar(symb[a]);
  27. }
  28. void print_expression (Atom* expr) {
  29. if (!expr) {
  30. printf("nil");
  31. return;
  32. }
  33. if (expr->type == NUM) {
  34. printf("%d", expr->num);
  35. return;
  36. }
  37. if (expr->type == SYMB) {
  38. print_symbol(expr->symb);
  39. return;
  40. }
  41. putchar('(');
  42. if (expr->type == LAMBDA) {
  43. printf("lambda ");
  44. List *li = expr->list;
  45. while (li) {
  46. print_expression(li->head);
  47. li = li->tail;
  48. if (li)
  49. putchar(' ');
  50. }
  51. }
  52. if (expr->type == TABLE) {
  53. printf("table ");
  54. Table *ta = expr->table;
  55. while (ta) {
  56. print_symbol(ta->key);
  57. putchar(' ');
  58. print_expression(ta->value);
  59. ta = ta->next;
  60. if (ta)
  61. putchar(' ');
  62. }
  63. }
  64. putchar(')');
  65. }
  66. // stack manipulation:
  67. void stack_push (Atom* at, List** st) {
  68. List *nl = cons(duplicate_atom(at),*st);
  69. *st = nl;
  70. }
  71. void stack_pop (int how_much, List** st) {
  72. if (how_much < 0) {
  73. _error("STACK_POP: Invalid value");
  74. return;
  75. }
  76. if (how_much == 0) {
  77. free_list(*st);
  78. *st = NULL;
  79. return;
  80. }
  81. List *st2 = *st;
  82. while (how_much && st2) {
  83. how_much --;
  84. if (!how_much) {
  85. *st = st2->tail;
  86. st2->tail = NULL;
  87. break;
  88. }
  89. st2 = st2->tail;
  90. }
  91. free_list(st2);
  92. }
  93. // type operations:
  94. // test for nil before using this:
  95. int is_simple (Atom* at) {
  96. return at->type != LIST && at->type != LAMBDA;
  97. }
  98. int is_list (Atom* at) {
  99. return at == NULL || at->type == LIST;
  100. }
  101. // there are multiline symbols and simple symbols
  102. // multiline symbols carries a '"' as their first character, simple symbols don't
  103. int is_symbol (Atom* at) {
  104. return at != NULL &&
  105. at->type == SYMB &&
  106. at->symb[0] >= 1 &&
  107. at->symb[1] != '"';
  108. }
  109. int valid_lambda (List* body) {
  110. if (list_size(body) < 1)
  111. return (int)_warning("LAMBDA" TOO_SHORT);
  112. if (!is_list(body->head))
  113. return (int)_warning("LAMBDA" MUST_BE_LIST " (element 1)");
  114. if (body->head) {
  115. if (!is_symbol_list(body->head->list))
  116. return (int)_warning("LAMBDA" MUST_BE_SYMLIST " (element 1)");
  117. }
  118. return 1;
  119. }
  120. unsigned is_symbol_list (List* list) {
  121. while (list) {
  122. if (!is_symbol(list->head)) return 0;
  123. list = list->tail;
  124. }
  125. return 1;
  126. }
  127. // object comparation:
  128. unsigned equal (Atom* le, Atom* ri) {
  129. if (le == ri)
  130. return 1;
  131. if (le == NULL || ri == NULL)
  132. return 0;
  133. if (le->type != ri->type)
  134. return 0;
  135. if (le->type == NUM)
  136. return le->num == ri->num;
  137. if (le->type == SYMB)
  138. return symbols_are_equal(le->symb, ri->symb);
  139. return lists_are_equal(le->list, ri->list);
  140. }
  141. unsigned lists_are_equal (List* le, List* ri) {
  142. while (le && ri) {
  143. if (!equal(le->head, ri->head))
  144. return 0;
  145. le = le->tail;
  146. ri = ri->tail;
  147. }
  148. return le == NULL && ri == NULL;
  149. }
  150. int list_size (List* li) {
  151. int size = 0;
  152. while (li) {
  153. li = li->tail;
  154. size++;
  155. }
  156. return size;
  157. }
  158. #include "erplm.c" // memory operations
  159. #include "erplt.c" // table operations
  160. #include "erplp.c" // parsing