2 #include "st-compiler.h"
4 #include "st-universe.h"
5 #include "st-dictionary.h"
6 #include "st-behavior.h"
29 * @class: The class for which the compiled method will be bound.
30 * @string: Source code for the method
31 * @error: return location for errors
33 * This function will compile a source string into a new CompiledMethod,
34 * and place the method in the methodDictionary of the given class.
37 st_compile_string (st_oop
class, const char *string
, st_compiler_error
*error
)
43 st_assert (class != ST_NIL
);
45 lexer
= st_lexer_new (string
);
49 node
= st_parser_parse (lexer
, error
);
50 st_lexer_destroy (lexer
);
55 method
= st_generate_method (class, node
, error
);
56 if (method
== ST_NIL
) {
57 st_node_destroy (node
);
61 st_dictionary_at_put (ST_BEHAVIOR (class)->method_dictionary
,
62 node
->method
.selector
,
65 st_node_destroy (node
);
71 filein_error (FileInParser
*parser
, st_token
*token
, const char *message
)
73 fprintf (stderr
, "%s: %i: %s\n", parser
->filename
, parser
->line
+ ((token
) ? st_token_get_line (token
) : -90), message
);
79 next_token (FileInParser
*parser
, st_lexer
*lexer
)
83 token
= st_lexer_next_token (lexer
);
85 if (st_token_get_type (token
) == ST_TOKEN_COMMENT
)
86 return next_token (parser
, lexer
);
87 else if (st_token_get_type (token
) == ST_TOKEN_INVALID
)
88 filein_error (parser
, token
, st_lexer_error_message (lexer
));
95 next_chunk (FileInParser
*parser
)
100 parser
->line
= st_input_get_line (parser
->input
);
102 chunk
= st_input_next_chunk (parser
->input
);
106 lexer
= st_lexer_new (chunk
);
113 parse_method (FileInParser
*parser
,
118 st_token
*token
= NULL
;
120 st_compiler_error error
;
122 st_lexer_destroy (lexer
);
124 /* get class or metaclass */
125 class = st_global_get (class_name
);
127 filein_error (parser
, token
, "undefined class");
130 class = st_object_class (class);
132 /* parse method chunk */
133 lexer
= next_chunk (parser
);
135 filein_error (parser
, token
, "expected method definition");
140 node
= st_parser_parse (lexer
, &error
);
143 if (node
->type
!= ST_METHOD_NODE
)
144 printf ("%i\n", node
->type
);
146 method
= st_generate_method (class, node
, &error
);
147 if (method
== ST_NIL
)
150 st_dictionary_at_put (ST_BEHAVIOR (class)->method_dictionary
,
151 node
->method
.selector
,
155 st_node_destroy (node
);
156 st_lexer_destroy (lexer
);
157 st_free (class_name
);
162 st_node_destroy (node
);
163 fprintf (stderr
, "%s:%i: %s\n", parser
->filename
,
164 parser
->line
+ error
.line
- 1 ,
170 parse_class (FileInParser
*parser
, st_lexer
*lexer
, char *name
)
177 parse_chunk (FileInParser
*parser
, st_lexer
*lexer
)
182 token
= next_token (parser
, lexer
);
184 if (st_token_get_type (token
) == ST_TOKEN_IDENTIFIER
) {
186 name
= st_strdup (st_token_get_text (token
));
188 token
= next_token (parser
, lexer
);
190 if (st_token_get_type (token
) == ST_TOKEN_IDENTIFIER
191 && (streq (st_token_get_text (token
), "method")))
193 parse_method (parser
, lexer
, name
, false);
195 else if (st_token_get_type (token
) == ST_TOKEN_IDENTIFIER
196 || streq (st_token_get_text (token
), "classMethod"))
198 parse_method (parser
, lexer
, name
, true);
200 else if (st_token_get_type (token
) == ST_TOKEN_KEYWORD_SELECTOR
201 && streq (st_token_get_text (token
), "subclass:"))
203 parse_class (parser
, lexer
, name
);
205 else if (streq (name
, "Annotation") &&
206 st_token_get_type (token
) == ST_TOKEN_KEYWORD_SELECTOR
&&
207 streq (st_token_get_text (token
), "key:")) {
222 filein_error (parser
, token
, "unrecognised syntax");
226 parse_chunks (FileInParser
*parser
)
230 while (st_input_look_ahead (parser
->input
, 1) != ST_INPUT_EOF
) {
232 lexer
= next_chunk (parser
);
236 parse_chunk (parser
, lexer
);
240 /* isn't declared in glibc string.h */
241 char * basename (const char *FILENAME
);
244 st_compile_file_in (const char *filename
)
247 FileInParser
*parser
;
249 st_assert (filename
!= NULL
);
251 if (!st_file_get_contents (filename
, &buffer
)) {
255 parser
= st_new0 (FileInParser
);
257 parser
->input
= st_input_new (buffer
);
258 if (!parser
->input
) {
259 fprintf (stderr
, "could not validate input file '%s'", filename
);
263 parser
->filename
= basename (filename
);
266 parse_chunks (parser
);
269 st_input_destroy (parser
->input
);