annotate lwbasic/compiler.c @ 25:87590f43e76d

Started lwbasic parser; checkpoint
author lost@l-w.ca
date Mon, 24 Jan 2011 20:08:09 -0700
parents
children 26aa76da75ad
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
25
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
1 /*
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
2 compiler.c
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
3
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
4 Copyright © 2011 William Astle
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
5
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
6 This file is part of LWTOOLS.
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
7
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
9 terms of the GNU General Public License as published by the Free Software
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
10 Foundation, either version 3 of the License, or (at your option) any later
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
11 version.
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
12
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
13 This program is distributed in the hope that it will be useful, but WITHOUT
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
16 more details.
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
17
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
18 You should have received a copy of the GNU General Public License along with
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
19 this program. If not, see <http://www.gnu.org/licenses/>.
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
20 */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
21
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
22 /*
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
23 This is the actual compiler bit; it drives the parser and code generation
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
24 */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
25
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
26 #include <stdio.h>
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
27
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
28 #include "lwbasic.h"
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
29
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
30 /* parse a type; the next token will be acquired as a result */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
31 /* the token advancement is to provide consistency */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
32 static int parse_type(cstate *state)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
33 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
34 int pt = -1;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
35
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
36 switch (state -> lexer_token)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
37 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
38 case token_kw_integer:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
39 pt = 1;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
40 break;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
41
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
42 default:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
43 lwb_error("Invalid type specification");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
44 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
45 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
46 /* look for "unsigned" modifier for integer types */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
47 return pt;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
48 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
49
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
50
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
51 /* issub means RETURNS is not allowed; !issub means RETURNS is required */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
52 static void parse_subfunc(cstate *state, int issub)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
53 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
54 int pt;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
55
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
56 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
57 if (state -> lexer_token != token_identifier)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
58 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
59 lwb_error("Invalid sub name '%s'", state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
60 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
61
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
62 printf("<name> = %s\n", state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
63
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
64 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
65 if (state -> lexer_token == token_kw_public || state -> lexer_token == token_kw_private)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
66 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
67 printf("<type> = %s\n", state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
68 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
69 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
70
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
71 /* ignore the "PARAMS" keyword if present */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
72 if (state -> lexer_token == token_kw_params)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
73 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
74
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
75 if (state -> lexer_token == token_eol)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
76 goto noparms;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
77
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
78 paramagain:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
79 if (state -> lexer_token != token_identifier)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
80 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
81 lwb_error("Parameter name expected, get %d, %s\n", state -> lexer_token, state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
82 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
83 printf("Got <param> = %s\n", state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
84 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
85
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
86 if (state -> lexer_token != token_kw_as)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
87 lwb_error("Expecting AS\n");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
88 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
89
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
90 pt = parse_type(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
91 printf("Got <type> = %d\n", pt);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
92
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
93 if (state -> lexer_token == token_char && state -> lexer_token_string[0] == ',')
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
94 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
95 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
96 goto paramagain;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
97 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
98
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
99 noparms:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
100 if (!issub)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
101 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
102 int rt;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
103
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
104 if (state -> lexer_token != token_kw_returns)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
105 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
106 lwb_error("FUNCTION must have RETURNS\n");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
107 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
108 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
109 if (state -> lexer_token == token_identifier)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
110 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
111 printf("Return value named: %s\n", state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
112 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
113 if (state -> lexer_token != token_kw_as)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
114 lwb_error("Execting AS after RETURNS");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
115 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
116 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
117 rt = parse_type(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
118 printf("Return type: %d\n", rt);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
119 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
120 else
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
121 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
122 if (state -> lexer_token == token_kw_returns)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
123 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
124 lwb_error("SUB cannot specify RETURNS\n");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
125 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
126 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
127
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
128
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
129 if (state -> lexer_token != token_eol)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
130 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
131 lwb_error("EOL expected; found %d, %s\n", state -> lexer_token, state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
132 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
133 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
134
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
135 void compiler(cstate *state)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
136 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
137 state -> lexer_curchar = -1;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
138
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
139 /* now look for a global declaration */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
140 for (;;)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
141 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
142 state -> parser_state = parser_state_global;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
143 lexer(state);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
144 switch (state -> lexer_token)
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
145 {
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
146 case token_kw_function:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
147 printf("Function\n");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
148 parse_subfunc(state, 0);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
149 break;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
150
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
151 case token_kw_sub:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
152 printf("Sub\n");
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
153 parse_subfunc(state, 1);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
154 break;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
155
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
156 /* blank lines are allowed */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
157 case token_eol:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
158 continue;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
159
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
160 /* EOF is allowed - end of parsing */
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
161 case token_eof:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
162 return;
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
163
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
164 default:
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
165 lwb_error("Invalid token %d, %s in global state\n", state -> lexer_token, state -> lexer_token_string);
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
166 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
167 }
87590f43e76d Started lwbasic parser; checkpoint
lost@l-w.ca
parents:
diff changeset
168 }