tree.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /* Copyright (c) 2007 by Ian Piumarta
  2. * All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the 'Software'),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, provided that the above copyright notice(s) and this
  10. * permission notice appear in all copies of the Software. Acknowledgement
  11. * of the use of this Software in supporting documentation would be
  12. * appreciated but is not required.
  13. *
  14. * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
  15. *
  16. * Last edited: 2007-05-15 10:32:09 by piumarta on emilia
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <assert.h>
  22. #include "tree.h"
  23. Node *actions= 0;
  24. Node *rules= 0;
  25. Node *thisRule= 0;
  26. Node *start= 0;
  27. FILE *output= 0;
  28. int actionCount= 0;
  29. int ruleCount= 0;
  30. int lastToken= -1;
  31. static inline Node *_newNode(int type, int size)
  32. {
  33. Node *node= calloc(1, size);
  34. node->type= type;
  35. return node;
  36. }
  37. #define newNode(T) _newNode(T, sizeof(struct T))
  38. Node *makeRule(char *name)
  39. {
  40. Node *node= newNode(Rule);
  41. node->rule.name= strdup(name);
  42. node->rule.id= ++ruleCount;
  43. node->rule.flags= 0;
  44. node->rule.next= rules;
  45. rules= node;
  46. return node;
  47. }
  48. Node *findRule(char *name)
  49. {
  50. Node *n;
  51. char *ptr;
  52. for (ptr= name; *ptr; ptr++) if ('-' == *ptr) *ptr= '_';
  53. for (n= rules; n; n= n->any.next)
  54. {
  55. assert(Rule == n->type);
  56. if (!strcmp(name, n->rule.name))
  57. return n;
  58. }
  59. return makeRule(name);
  60. }
  61. Node *beginRule(Node *rule)
  62. {
  63. actionCount= 0;
  64. return thisRule= rule;
  65. }
  66. void Rule_setExpression(Node *node, Node *expression)
  67. {
  68. assert(node);
  69. #ifdef DEBUG
  70. Node_print(node); fprintf(stderr, " [%d]<- ", node->type); Node_print(expression); fprintf(stderr, "\n");
  71. #endif
  72. assert(Rule == node->type);
  73. node->rule.expression= expression;
  74. if (!start || !strcmp(node->rule.name, "start"))
  75. start= node;
  76. }
  77. Node *makeVariable(char *name)
  78. {
  79. Node *node;
  80. assert(thisRule);
  81. for (node= thisRule->rule.variables; node; node= node->variable.next)
  82. if (!strcmp(name, node->variable.name))
  83. return node;
  84. node= newNode(Variable);
  85. node->variable.name= strdup(name);
  86. node->variable.next= thisRule->rule.variables;
  87. thisRule->rule.variables= node;
  88. return node;
  89. }
  90. Node *makeName(Node *rule)
  91. {
  92. Node *node= newNode(Name);
  93. node->name.rule= rule;
  94. node->name.variable= 0;
  95. rule->rule.flags |= RuleUsed;
  96. return node;
  97. }
  98. Node *makeDot(void)
  99. {
  100. return newNode(Dot);
  101. }
  102. Node *makeCharacter(char *text)
  103. {
  104. Node *node= newNode(Character);
  105. node->character.value= strdup(text);
  106. return node;
  107. }
  108. Node *makeString(char *text)
  109. {
  110. Node *node= newNode(String);
  111. node->string.value= strdup(text);
  112. return node;
  113. }
  114. Node *makeClass(char *text)
  115. {
  116. Node *node= newNode(Class);
  117. node->cclass.value= (unsigned char *)strdup(text);
  118. return node;
  119. }
  120. Node *makeAction(char *text)
  121. {
  122. Node *node= newNode(Action);
  123. char name[1024];
  124. assert(thisRule);
  125. sprintf(name, "_%d_%s", ++actionCount, thisRule->rule.name);
  126. node->action.name= strdup(name);
  127. node->action.text= strdup(text);
  128. node->action.list= actions;
  129. node->action.rule= thisRule;
  130. actions= node;
  131. {
  132. char *ptr;
  133. for (ptr= node->action.text; *ptr; ++ptr)
  134. if ('$' == ptr[0] && '$' == ptr[1])
  135. ptr[1]= ptr[0]= 'y';
  136. }
  137. return node;
  138. }
  139. Node *makePredicate(char *text)
  140. {
  141. Node *node= newNode(Predicate);
  142. node->predicate.text= strdup(text);
  143. return node;
  144. }
  145. Node *makeAlternate(Node *e)
  146. {
  147. if (Alternate != e->type)
  148. {
  149. Node *node= newNode(Alternate);
  150. assert(e);
  151. assert(!e->any.next);
  152. node->alternate.first=
  153. node->alternate.last= e;
  154. return node;
  155. }
  156. return e;
  157. }
  158. Node *Alternate_append(Node *a, Node *e)
  159. {
  160. assert(a);
  161. a= makeAlternate(a);
  162. assert(a->alternate.last);
  163. assert(e);
  164. a->alternate.last->any.next= e;
  165. a->alternate.last= e;
  166. return a;
  167. }
  168. Node *makeSequence(Node *e)
  169. {
  170. if (Sequence != e->type)
  171. {
  172. Node *node= newNode(Sequence);
  173. assert(e);
  174. assert(!e->any.next);
  175. node->sequence.first=
  176. node->sequence.last= e;
  177. return node;
  178. }
  179. return e;
  180. }
  181. Node *Sequence_append(Node *a, Node *e)
  182. {
  183. assert(a);
  184. a= makeSequence(a);
  185. assert(a->sequence.last);
  186. assert(e);
  187. a->sequence.last->any.next= e;
  188. a->sequence.last= e;
  189. return a;
  190. }
  191. Node *makePeekFor(Node *e)
  192. {
  193. Node *node= newNode(PeekFor);
  194. node->peekFor.element= e;
  195. return node;
  196. }
  197. Node *makePeekNot(Node *e)
  198. {
  199. Node *node= newNode(PeekNot);
  200. node->peekNot.element= e;
  201. return node;
  202. }
  203. Node *makeQuery(Node *e)
  204. {
  205. Node *node= newNode(Query);
  206. node->query.element= e;
  207. return node;
  208. }
  209. Node *makeStar(Node *e)
  210. {
  211. Node *node= newNode(Star);
  212. node->star.element= e;
  213. return node;
  214. }
  215. Node *makePlus(Node *e)
  216. {
  217. Node *node= newNode(Plus);
  218. node->plus.element= e;
  219. return node;
  220. }
  221. static Node *stack[1024];
  222. static Node **stackPointer= stack;
  223. #ifdef DEBUG
  224. static void dumpStack(void)
  225. {
  226. Node **p;
  227. for (p= stack + 1; p <= stackPointer; ++p)
  228. {
  229. fprintf(stderr, "### %d\t", p - stack);
  230. Node_print(*p);
  231. fprintf(stderr, "\n");
  232. }
  233. }
  234. #endif
  235. Node *push(Node *node)
  236. {
  237. assert(node);
  238. assert(stackPointer < stack + 1023);
  239. #ifdef DEBUG
  240. dumpStack(); fprintf(stderr, " PUSH "); Node_print(node); fprintf(stderr, "\n");
  241. #endif
  242. return *++stackPointer= node;
  243. }
  244. Node *top(void)
  245. {
  246. assert(stackPointer > stack);
  247. return *stackPointer;
  248. }
  249. Node *pop(void)
  250. {
  251. assert(stackPointer > stack);
  252. #ifdef DEBUG
  253. dumpStack(); fprintf(stderr, " POP\n");
  254. #endif
  255. return *stackPointer--;
  256. }
  257. static void Node_fprint(FILE *stream, Node *node)
  258. {
  259. assert(node);
  260. switch (node->type)
  261. {
  262. case Rule: fprintf(stream, " %s", node->rule.name); break;
  263. case Name: fprintf(stream, " %s", node->name.rule->rule.name); break;
  264. case Dot: fprintf(stream, " ."); break;
  265. case Character: fprintf(stream, " '%s'", node->character.value); break;
  266. case String: fprintf(stream, " \"%s\"", node->string.value); break;
  267. case Class: fprintf(stream, " [%s]", node->cclass.value); break;
  268. case Action: fprintf(stream, " { %s }", node->action.text); break;
  269. case Predicate: fprintf(stream, " ?{ %s }", node->action.text); break;
  270. case Alternate: node= node->alternate.first;
  271. fprintf(stream, " (");
  272. Node_fprint(stream, node);
  273. while ((node= node->any.next))
  274. {
  275. fprintf(stream, " |");
  276. Node_fprint(stream, node);
  277. }
  278. fprintf(stream, " )");
  279. break;
  280. case Sequence: node= node->sequence.first;
  281. fprintf(stream, " (");
  282. Node_fprint(stream, node);
  283. while ((node= node->any.next))
  284. Node_fprint(stream, node);
  285. fprintf(stream, " )");
  286. break;
  287. case PeekFor: fprintf(stream, "&"); Node_fprint(stream, node->query.element); break;
  288. case PeekNot: fprintf(stream, "!"); Node_fprint(stream, node->query.element); break;
  289. case Query: Node_fprint(stream, node->query.element); fprintf(stream, "?"); break;
  290. case Star: Node_fprint(stream, node->query.element); fprintf(stream, "*"); break;
  291. case Plus: Node_fprint(stream, node->query.element); fprintf(stream, "+"); break;
  292. default:
  293. fprintf(stream, "\nunknown node type %d\n", node->type);
  294. exit(1);
  295. }
  296. }
  297. void Node_print(Node *node) { Node_fprint(stderr, node); }
  298. static void Rule_fprint(FILE *stream, Node *node)
  299. {
  300. assert(node);
  301. assert(Rule == node->type);
  302. fprintf(stream, "%s.%d =", node->rule.name, node->rule.id);
  303. if (node->rule.expression)
  304. Node_fprint(stream, node->rule.expression);
  305. else
  306. fprintf(stream, " UNDEFINED");
  307. fprintf(stream, " ;\n");
  308. }
  309. void Rule_print(Node *node) { Rule_fprint(stderr, node); }