Browse Source

#include is now used for static include while import will be used (currently unimplemented) to perform runtime imports.

Marco Bambini 8 years ago
parent
commit
410aafcb18
3 changed files with 108 additions and 66 deletions
  1. 86 66
      src/compiler/gravity_parser.c
  2. 17 0
      test/include_test.gravity
  3. 5 0
      test/test.inc

+ 86 - 66
src/compiler/gravity_parser.c

@@ -1471,7 +1471,7 @@ loop:
 	return params;
 }
 
-// MARK: - UnitTest -
+// MARK: - Macro -
 
 typedef enum {
 	UNITTEST_NONE,
@@ -1483,7 +1483,7 @@ typedef enum {
 	UNITTEST_NOTE
 } unittest_t;
 
-static unittest_t parse_unittest_identifier(const char *identifier) {
+static unittest_t parse_unittest_identifier (const char *identifier) {
 	if (string_cmp(identifier, "name") == 0) return UNITTEST_NAME;
 	if (string_cmp(identifier, "note") == 0) return UNITTEST_NOTE;
 	if (string_cmp(identifier, "error") == 0) return UNITTEST_ERROR;
@@ -1494,9 +1494,9 @@ static unittest_t parse_unittest_identifier(const char *identifier) {
 	return UNITTEST_NONE;
 }
 
-static gnode_t *parse_unittest_declaration(gravity_parser_t *parser) {
+static gnode_t *parse_unittest_macro (gravity_parser_t *parser) {
+	DEBUG_PARSER("parse_unittest_macro");
 	DECLARE_LEXER;
-	DEBUG_PARSER("parse_unittest_declaration");
 	
 	// @unittest {
 	//		name: "Unit test name";
@@ -1659,6 +1659,65 @@ handle_error:
 	return NULL;
 }
 
+static gnode_t *parse_include_macro (gravity_parser_t *parser) {
+	DEBUG_PARSER("parse_include_macro");
+	DECLARE_LEXER;
+	
+	// process filename (can be an identifier or a literal string)
+	// only literals are supported in this version
+	gtoken_t		type;
+	gtoken_s		token;
+	const char		*module_name;
+	gravity_lexer_t	*newlexer;
+	
+loop:
+	newlexer = NULL;
+	type = gravity_lexer_next(lexer);
+	token = gravity_lexer_token(lexer);
+	
+	// check if it is a string token
+	if (type != TOK_STRING) {
+		REPORT_ERROR(token, "Expected file name but found %s.", token_name(type));
+		return NULL;
+	}
+	
+	// check pre-requisites
+	if ((!parser->delegate) || (!parser->delegate->loadfile_callback)) {
+		REPORT_ERROR(gravity_lexer_token(lexer), "%s", "Unable to load file because no loadfile callback registered in delegate.");
+		return NULL;
+	}
+	
+	// parse string
+	module_name = cstring_from_token(parser, token);
+	size_t size = 0;
+	uint32_t fileid = 0;
+	
+	// module_name is a filename and it is used by lexer to store filename into tokens
+	// tokens are then stored inside AST nodes in order to locate errors into source code
+	// AST can live a lot longer than both lexer and parser so we need a way to persistent
+	// store these chuncks of memory
+	const char *source = parser->delegate->loadfile_callback(module_name, &size, &fileid, parser->delegate->xdata);
+	if (source) newlexer = gravity_lexer_create(source, size, fileid, false);
+	
+	if (newlexer) {
+		// push new lexer into lexer stack
+		marray_push(gravity_lexer_t*, *parser->lexer, newlexer);
+	} else {
+		REPORT_ERROR(token, "Unable to load file %s.", module_name);
+	}
+	
+	// check for optional comma
+	if (gravity_lexer_peek(lexer) == TOK_OP_COMMA) {
+		gravity_lexer_next(lexer); // consume TOK_OP_COMMA
+		goto loop;
+	}
+	
+	// parse semicolon
+	parse_semicolon(parser);
+	
+	return NULL;
+}
+
 // MARK: - Statements -
 
 static gnode_t *parse_label_statement (gravity_parser_t *parser) {
@@ -1899,70 +1958,20 @@ static gnode_t *parse_declaration_statement (gravity_parser_t *parser) {
 }
 
 static gnode_t *parse_import_statement (gravity_parser_t *parser) {
+	#pragma unused(parser)
 	DEBUG_PARSER("parse_import_statement");
 	
-	DECLARE_LEXER;
-
-	// parse import keyword
-	gravity_lexer_next(lexer);
-	
-	// process filename (can be an identifier or a literal string)
-	// identifier to import modules ?
-	// only literals are supported in this version
-	gtoken_t		type;
-	gtoken_s		token;
-	const char		*module_name;
-	gravity_lexer_t	*newlexer;
-	
-loop:
-	newlexer = NULL;
-	type = gravity_lexer_next(lexer);
-	token = gravity_lexer_token(lexer);
-	
-	// check if it is a string token
-	if (type != TOK_STRING) {
-		REPORT_ERROR(token, "Expected file name but found %s.", token_name(type));
-		return NULL;
-	}
-	
-	// check pre-requisites
-	if ((!parser->delegate) || (!parser->delegate->loadfile_callback)) {
-		REPORT_ERROR(gravity_lexer_token(lexer), "%s", "Unable to load file because no loadfile callback registered in delegate.");
-		return NULL;
-	}
-	
-	// parse string
-	module_name = cstring_from_token(parser, token);
-	size_t size = 0;
-	uint32_t fileid = 0;
-	
-	// module_name is a filename and it is used by lexer to store filename into tokens
-	// tokens are then stored inside AST nodes in order to locate errors into source code
-	// AST can live a lot longer than both lexer and parser so we need a way to persistent
-	// store these chuncks of memory
-	const char *source = parser->delegate->loadfile_callback(module_name, &size, &fileid, parser->delegate->xdata);
-	if (source) newlexer = gravity_lexer_create(source, size, fileid, false);
-
-	if (newlexer) {
-		// push new lexer into lexer stack
-		marray_push(gravity_lexer_t*, *parser->lexer, newlexer);
-	} else {
-		REPORT_ERROR(token, "Unable to load file %s.", module_name);
-	}
-	
-	// check for optional comma
-	if (gravity_lexer_peek(lexer) == TOK_OP_COMMA) {
-		gravity_lexer_next(lexer); // consume TOK_OP_COMMA
-		goto loop;
-	}
-
-	// parse semicolon
-	parse_semicolon(parser);
-	
+	// import is a syntactic sugar for System.import
 	return NULL;
 }
 
 static gnode_t *parse_macro_statement (gravity_parser_t *parser) {
+	typedef enum {
+		MACRO_UNKNOWN = 0,
+		MACRO_UNITEST = 1,
+		MACRO_INCLUDE = 2
+	} builtin_macro;
+	
 	DEBUG_PARSER("parse_macro_statement");
 	DECLARE_LEXER;
 	
@@ -1986,12 +1995,23 @@ static gnode_t *parse_macro_statement (gravity_parser_t *parser) {
 	const char *macroid = parse_identifier(parser);
 	if (macroid == NULL) goto handle_error;
 	
-	// check #unittest macro
-	bool is_unittest = (string_cmp(macroid, "unittest") == 0);
+	// check macro
+	builtin_macro macro_type = MACRO_UNKNOWN;
+	if (string_cmp(macroid, "unittest") == 0) macro_type = MACRO_UNITEST;
+	else if (string_cmp(macroid, "include") == 0) macro_type = MACRO_INCLUDE;
 	mem_free(macroid);
 	
-	if (is_unittest) {
-		return parse_unittest_declaration(parser);
+	switch (macro_type) {
+		case MACRO_UNITEST:
+			return parse_unittest_macro(parser);
+			break;
+			
+		case MACRO_INCLUDE:
+			return parse_include_macro(parser);
+			break;
+			
+		case MACRO_UNKNOWN:
+			break;
 	}
 	
 handle_error:

+ 17 - 0
test/include_test.gravity

@@ -0,0 +1,17 @@
+#unittest {
+	name: "Test #include macro.";
+	error: NONE;
+	result: 90;
+};
+
+#include "test.inc"
+
+func sum2 (a, b) {
+	return a + b;
+}
+
+func main() {
+	var n1 = sum2(10, 20);
+	var n2 = sum3(10, 20, 30);
+	return n1 + n2;
+}

+ 5 - 0
test/test.inc

@@ -0,0 +1,5 @@
+// this is a test file to be included in include_test.gravity
+
+func sum3 (a, b, c) {
+	return a + b + c;
+}