Fix brainf*ck interpreter memory issue
[bob_language.git] / parser.y
blob6bc1ca82008005e4da1fcf641150e4da4dc1cc5e
1 %locations
2 %error-verbose
3 %{
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include "core.h"
10 #include "parser.h"
11 #include "dynstrings.h"
13 int yylex (void);
14 int yyparse (void);
15 void yyerror (char *err,...);
16 void yyerror_loc (YYLTYPE *yylloc,char *err,...);
18 extern FILE *yyin;
19 extern FILE *c_output;
20 extern TreeNode *root;
24 %union{
25 TreeNode *node;
28 %token FN NEWLINE SHL SHR EQU
29 %token<node> IF WHILE RETURN TRUE FALSE DECNUM HEXNUM STRNUM ID
31 %type<node> blob get_length get_element expr assign call_args callfn line startline codeblock function func_args init
33 %left ','
34 %left SHL SHR
35 %left '<' '>' EQU
36 %left '+' '-' '&' '|'
37 %left '*' '/' '%' '^'
38 %left NEG
39 %left PARS
41 %start init
45 init: /* EPSILON */ { $$ = NULL; }
46 | NEWLINE init { $$ = NULL; }
47 | function init { $$ = node_new(); $$->id = NODE_ROOT; node_bottom($$, $1); node_next(root, $$); }
50 function: FN ID '(' func_args ')' codeblock { $$ = node_new(); $$->id = NODE_FUNCTION; node_next($$, $4); node_next($$, $2); node_bottom($$, $6); }
51 | FN ID '(' ')' codeblock { $$ = node_new(); $$->id = NODE_FUNCTION; node_next($$, $2); node_bottom($$, $5); }
54 func_args: ID { $$ = node_new(); $$->id = NODE_FUNC_ARGS; node_bottom($$, $1); }
55 | ID ',' func_args { $$ = node_new(); $$->id = NODE_FUNC_ARGS; node_next($$, $3); node_bottom($$, $1); }
58 codeblock: '{' NEWLINE startline '}' NEWLINE { $$ = node_new(); $$->id = NODE_CODEBLOCK; node_bottom($$, $3); }
59 | NEWLINE '{' NEWLINE startline '}' NEWLINE { $$ = node_new(); $$->id = NODE_CODEBLOCK; node_bottom($$, $4); }
62 startline: /* EPSILON */ { $$ = node_new(); $$->id = NODE_LINE; node_bottom($$, node_new()); }
63 | NEWLINE startline { $$ = $2; }
64 | line startline { $$ = node_new(); $$->id = NODE_LINE; node_next($$, $2); node_bottom($$, $1); }
67 line: RETURN expr NEWLINE { $$ = $1; node_bottom($$, $2); }
68 | assign NEWLINE { $$ = $1; }
69 | callfn NEWLINE { $$ = node_new(); $$->id = NODE_VOID_RETURN; node_bottom($$, $1); }
70 | IF '(' expr ')' codeblock { $$ = $1; node_next($$, $3); node_bottom($$, $5); }
71 | WHILE '(' expr ')' codeblock { $$ = $1; node_next($$, $3); node_bottom($$, $5); }
74 blob: ID
75 | TRUE
76 | FALSE
77 | DECNUM
78 | HEXNUM
79 | STRNUM
80 | callfn
83 callfn: ID '(' call_args ')' { $$ = node_new(); $$->id = NODE_CALLFN; node_bottom($$, $3); node_bottom($$, $1); }
84 | ID '(' ')' { $$ = node_new(); $$->id = NODE_CALLFN; node_bottom($$, $1); }
87 call_args: expr { $$ = node_new(); $$->id = NODE_CALL_ARGS; node_bottom($$, $1); }
88 | expr ',' call_args { $$ = node_new(); $$->id = NODE_CALL_ARGS; node_bottom($$, $1); node_next($$, $3); }
91 expr: blob
92 | expr '+' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Add")); node_bottom($$, $1); node_bottom($$, $3); }
93 | expr '-' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Subtract")); node_bottom($$, $1); node_bottom($$, $3); }
94 | expr '*' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Multiply")); node_bottom($$, $1); node_bottom($$, $3); }
95 | expr '/' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Divide")); node_bottom($$, $1); node_bottom($$, $3); }
96 | expr '%' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Modulo")); node_bottom($$, $1); node_bottom($$, $3); }
97 | expr '^' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Xor")); node_bottom($$, $1); node_bottom($$, $3); }
98 | expr '&' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("And")); node_bottom($$, $1); node_bottom($$, $3); }
99 | expr '|' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Or")); node_bottom($$, $1); node_bottom($$, $3); }
100 | '!' expr %prec NEG { $$ = node_new(); $$->id = NODE_ARIT_UNARY; node_set($$, strdup("Not")); node_bottom($$, $2); }
101 | '-' expr %prec NEG { $$ = node_new(); $$->id = NODE_ARIT_UNARY; node_set($$, strdup("Negate")); node_bottom($$, $2); }
102 | expr SHL expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("ShiftLeft")); node_bottom($$, $1); node_bottom($$, $3); }
103 | expr SHR expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("ShiftRight")); node_bottom($$, $1); node_bottom($$, $3); }
104 | expr '>' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Greater")); node_bottom($$, $1); node_bottom($$, $3); }
105 | expr '<' expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Greater")); node_bottom($$, $3); node_bottom($$, $1); }
106 | expr EQU expr { $$ = node_new(); $$->id = NODE_ARIT_BINARY; node_set($$, strdup("Equals")); node_bottom($$, $1); node_bottom($$, $3); }
107 | get_element
108 | '$' get_length { $$ = node_new(); $$->id = NODE_GET_LENGTH; node_bottom($$, $2); }
109 | '(' expr ')' %prec PARS { $$ = $2; }
112 get_length: '$' get_length { $$ = node_new(); $$->id = NODE_GET_LENGTH; node_bottom($$, $2); }
113 | '(' expr ')' { $$ = $2; }
114 | blob
117 get_element: get_length '[' expr ']' { $$ = node_new(); $$->id = NODE_GET_ELEMENT; node_bottom($$, $1); node_bottom($$, $3); }
118 | get_element '[' expr ']' { $$ = node_new(); $$->id = NODE_GET_ELEMENT; node_bottom($$, $1); node_bottom($$, $3); }
121 assign: ID '=' expr { $$ = node_new(); $$->id = NODE_SET_VARIABLE; node_bottom($$, $1); node_bottom($$, $3); }
122 | ID '[' expr ']' '=' expr { $$ = node_new(); $$->id = NODE_SET_ELEMENT; node_bottom($$, $1); node_bottom($$, $3); node_bottom($$, $6); }
123 | '$' ID '=' expr { $$ = node_new(); $$->id = NODE_SET_LENGTH; node_bottom($$, $2); node_bottom($$, $4); }
128 void yyerror(char *err, ...) {
129 va_list list;
130 va_start(list, err);
131 core_error(str_printf("Error (at position %d:%d-%d:%d) : ", yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column));
132 core_error(str_vprintf(err, list));
133 core_error(strdup("\n"));
134 va_end(list);
137 void yyerrorloc(YYLTYPE *yylloc,char *err, ...) {
138 va_list list;
139 va_start(list, err);
140 core_error(str_printf("Error (at position %d:%d-%d:%d) : ", yylloc->first_line, yylloc->first_column, yylloc->last_line, yylloc->last_column));
141 core_error(str_vprintf(err, list));
142 core_error(strdup("\n"));
143 va_end(list);
146 int main(int argc, char **argv) {
147 core_initialize();
148 FILE *input;
149 if (argc > 1) {
150 input = fopen(argv[1], "r");
151 if (input == NULL) {
152 fprintf(stderr, "Error opening file \"%s\"\n", argv[1]);
153 return 1;
156 else {
157 input = stdin;
159 yyin = input;
160 c_output = stdout;
161 yylloc.first_line = yylloc.last_line = 1;
162 yylloc.first_column = yylloc.last_column = 1;
163 yyparse();
164 root_output();
165 core_finalize();
166 fclose(input);
167 return 0;