yacc.y 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. %{
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "yacc.tab.h"
  5. #include "symtable.h"
  6. #include "ast_node.h"
  7. #include "parser.h"
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. extern FILE *yyin;
  11. extern YYSTYPE yylex(void);
  12. // line number (got from lex.l)
  13. extern int linenum;
  14. // buffer for general use
  15. #define DD_BUFFER_SIZE 1000
  16. char buffer[DD_BUFFER_SIZE];
  17. // error
  18. void yyerror(const char *str)
  19. {
  20. fprintf(stderr,"error: line %d: %s\n", linenum, str);
  21. _exit(-1);
  22. }
  23. // game node, parent of all nodes
  24. struct ast_node *game_node;
  25. char *keywords[] = {
  26. "echo",
  27. "def",
  28. "=",
  29. "+",
  30. "-",
  31. "*",
  32. "/",
  33. ">=",
  34. "==",
  35. "<=",
  36. "&&",
  37. "||",
  38. "<",
  39. ">",
  40. "group",
  41. "class",
  42. "function",
  43. "return",
  44. "array",
  45. "new",
  46. "if",
  47. };
  48. // init data, parse, exit
  49. int main(int argc, char *argv[])
  50. {
  51. /* tweakable data
  52. */
  53. int show_ast = 0;
  54. char *filename = 0;
  55. FILE *input_file = stdin;
  56. // parse arguments
  57. for (int i = 1; i < argc; i++) {
  58. // print abstract syntax tree
  59. if (strcmp(argv[i], "--print-ast") == 0) {
  60. show_ast = 1;
  61. }
  62. else
  63. // input file
  64. if (!filename) {
  65. filename = argv[i];
  66. }
  67. }
  68. // make sure the minimum to parse exists
  69. if (!filename) {
  70. printf("no filename given\n");
  71. return -1;
  72. }
  73. else {
  74. input_file = fopen(filename, "r");
  75. if (!input_file) {
  76. printf("unable to open input file: %s\n", filename);
  77. return -1;
  78. }
  79. yyin = input_file;
  80. }
  81. // init data
  82. linenum = 1;
  83. // initial symbols
  84. symtable_init();
  85. /* keywords
  86. */
  87. for (int i = 0; i < sizeof(keywords) /sizeof(char*); i++) {
  88. symtable_insert(keywords[i], DD_KEYWORD);
  89. }
  90. /*
  91. symtable_insert("DD_WIDTH", DD_INTERNAL_WIDTH);
  92. symtable_insert("DD_HEIGHT", DD_INTERNAL_HEIGHT);
  93. */
  94. game_node = ast_create(AST_GAME, 0);
  95. // init structs
  96. /*
  97. struct struct_entry *temp_entry = malloc(sizeof(struct struct_entry));
  98. temp_entry->name = "dd_world";
  99. struct_insert(temp_entry);
  100. temp_entry = malloc(sizeof(struct struct_entry));
  101. temp_entry->name = "dd_sprite";
  102. struct_insert(temp_entry);
  103. temp_entry = malloc(sizeof(struct struct_entry));
  104. temp_entry->name = "dd_vector2d";
  105. struct_insert(temp_entry);
  106. */
  107. // parse!
  108. yyparse();
  109. // parse resulting ast tree to a file
  110. parse_javascript("build/game.js", game_node);
  111. //struct_print();
  112. // print debug data and clean everything
  113. /*
  114. symtable_print();
  115. */
  116. if (show_ast) {
  117. ast_print(game_node);
  118. }
  119. // clean symtable and ast tree
  120. symtable_clean();
  121. ast_delete(game_node);
  122. // success!
  123. return 0;
  124. }
  125. %}
  126. // nothingness
  127. %token DD_ZERO
  128. // used for the languages keywords
  129. %token DD_KEYWORD
  130. /* constants */
  131. %token DD_CONSTANT_SYMBOL DD_CONSTANT_STRING DD_CONSTANT_NUMBER
  132. %%
  133. /* each rule creates a node,
  134. * possibly with children nodes,
  135. * all non-terminals are nodes that can be obtained with ast_pop() (left to right)
  136. */
  137. /* the game itself, contains commands
  138. */
  139. game:
  140. commands {
  141. ast_child_add(game_node, ast_pop());
  142. }
  143. ;
  144. /* commands,
  145. * at least one, but can be more
  146. * returns AST_GROUP
  147. */
  148. commands:
  149. /* single command, creates a group of itself
  150. */
  151. command {
  152. struct ast_node *n = ast_create(AST_GROUP, 0);
  153. ast_child_add(n, ast_pop());
  154. ast_push(n);
  155. }
  156. |
  157. /* single command but more are following,
  158. * add the command to the group
  159. */
  160. command commands {
  161. struct ast_node *n = ast_pop();
  162. ast_child_add_first(n, ast_pop());
  163. ast_push(n);
  164. }
  165. ;
  166. /* single command
  167. * has a keyword and optional arguments
  168. */
  169. command:
  170. '(' cmd_name optional_args ')' {
  171. // get nodes
  172. struct ast_node *opt_args = ast_pop();
  173. struct ast_node *cmd_name = ast_pop();
  174. // find out if keyword is an native keyword or a custom one
  175. struct entry *e = symtable_entryat(cmd_name->value);
  176. int type;
  177. if (strcmp(e->lexptr, "include") == 0) {
  178. // create new buffer
  179. struct ast_node *child = dd_da_get(&opt_args->children, 0);
  180. struct entry *opt_args_e = symtable_entryat(child->value);
  181. printf("include %s\n", opt_args_e->lexptr);
  182. // open file
  183. // push new buffer
  184. }
  185. if (e->token == DD_KEYWORD) {
  186. //printf("keyword symbol: %s\n", e->lexptr);
  187. if (strcmp(e->lexptr, "group") == 0) {
  188. type = AST_GROUP;
  189. }
  190. else {
  191. type = AST_COMMAND_NATIVE;
  192. }
  193. }
  194. // not a native keyword, assume custom one
  195. else {
  196. sprintf(buffer, "not a keyword: '%s'", e->lexptr);
  197. type = AST_COMMAND_CUSTOM;
  198. //yyerror(buffer);
  199. //printf("error symbol not keyword: %s\n", e->lexptr);
  200. }
  201. /* command node
  202. * construct it in such a way that the parent ast node is the command
  203. * if a custom command, then first child is its name
  204. */
  205. opt_args->node_type = type;
  206. opt_args->value = $2;
  207. if (type == AST_COMMAND_CUSTOM) {
  208. ast_child_add_first(opt_args, cmd_name);
  209. }
  210. ast_push(opt_args);
  211. };
  212. /* optional args
  213. */
  214. optional_args:
  215. arg optional_args {
  216. struct ast_node *n = ast_pop();
  217. struct ast_node *arg = ast_pop();
  218. ast_child_add_first(n, arg);
  219. ast_push(n);
  220. }
  221. |
  222. {
  223. ast_push(ast_create(AST_GROUP, 0));
  224. }
  225. ;
  226. /* argument
  227. */
  228. arg:
  229. DD_CONSTANT_NUMBER {
  230. struct ast_node *n = ast_create(AST_NUMBER, $1);
  231. ast_push(n);
  232. }
  233. |
  234. DD_CONSTANT_STRING {
  235. struct entry *e = symtable_entryat($1);
  236. struct ast_node *n = ast_create(AST_STRING, $1);
  237. ast_push(n);
  238. }
  239. |
  240. identifier {
  241. struct ast_node *n = ast_pop();
  242. ast_push(n);
  243. }
  244. |
  245. command
  246. ;
  247. /* command name
  248. * can be either one character or an identifier (chain of symbols)
  249. */
  250. cmd_name:
  251. identifier
  252. ;
  253. /* identifier
  254. * can be a chain of symbols (chains with '.')
  255. * example: this.my_obj.x
  256. */
  257. identifier:
  258. DD_CONSTANT_SYMBOL {
  259. struct ast_node *n = ast_create(AST_IDENTIFIER, $1);
  260. ast_push(n);
  261. }
  262. |
  263. identifier '.' DD_CONSTANT_SYMBOL {
  264. struct ast_node *new = ast_create(AST_IDENTIFIER, $3);
  265. struct ast_node *group = ast_pop();
  266. ast_child_add(group, new);
  267. ast_push(group);
  268. }
  269. ;