--- a/src/lexer.cc Sat Jan 18 02:11:45 2014 +0200 +++ b/src/lexer.cc Sun Jan 19 20:16:00 2014 +0200 @@ -34,25 +34,33 @@ static string_list g_file_name_stack; static lexer* g_main_lexer = null; +// ============================================================================= +// lexer::lexer() { assert (g_main_lexer == null); g_main_lexer = this; } +// ============================================================================= +// lexer::~lexer() { g_main_lexer = null; } +// ============================================================================= +// void lexer::process_file (string file_name) { + g_file_name_stack << file_name; FILE* fp = fopen (file_name, "r"); if (fp == null) error ("couldn't open %1 for reading: %2", file_name, strerror (errno)); lexer_scanner sc (fp); + check_file_header (sc); while (sc.get_next_token()) { @@ -82,13 +90,58 @@ tok.column = sc.get_column(); tok.type = sc.get_token_type(); tok.text = sc.get_token_text(); - // devf ("Token #%1: %2:%3:%4: %5 (%6)\n", m_tokens.size(), - // tok.file, tok.line, tok.column, describe_token (&tok), describe_token_type (tok.type)); + + // devf ("Token #%1: %2:%3:%4: %5 (%6)\n", m_tokens.size(), + // tok.file, tok.line, tok.column, describe_token (&tok), describe_token_type (tok.type)); + m_tokens << tok; } } m_token_position = m_tokens.begin() - 1; + g_file_name_stack.remove (file_name); +} + +// ============================================================================ +// +static bool is_valid_header (string header) +{ + if (header.ends_with ("\n")) + header.remove_from_end (1); + + string_list tokens = header.split (" "); + + if (tokens.size() != 2 || tokens[0] != "#!botc" || tokens[1].empty()) + return false; + + string_list nums = tokens[1].split ("."); + + if (nums.size() == 2) + nums << "0"; + elif (nums.size() != 3) + return false; + + bool ok_a, ok_b, ok_c; + long major = nums[0].to_long (&ok_a); + long minor = nums[1].to_long (&ok_b); + long patch = nums[2].to_long (&ok_c); + + if (!ok_a || !ok_b || !ok_c) + return false; + + if (VERSION_NUMBER < MAKE_VERSION_NUMBER (major, minor, patch)) + error ("The script file requires " APPNAME " v%1, this is v%2", + make_version_string (major, minor, patch), get_version_string (e_short_form)); + + return true; +} + +// ============================================================================ +// +void lexer::check_file_header (lexer_scanner& sc) +{ + if (!is_valid_header (sc.read_line())) + error ("Not a valid botscript file! File must start with '#!botc <version>'"); } // ============================================================================= @@ -125,14 +178,23 @@ // ============================================================================= // eugh.. // -void lexer::must_get_next_from_scanner (lexer_scanner& sc, e_token tok) +void lexer::must_get_next_from_scanner (lexer_scanner& sc, e_token tt) { if (!sc.get_next_token()) error ("unexpected EOF"); - if (tok != tk_any && sc.get_token_type() != tok) - error ("expected %1, got %2", describe_token_type (tok), - describe_token (get_token())); + if (tt != tk_any && sc.get_token_type() != tt) + { // TODO + token tok; + tok.type = sc.get_token_type(); + tok.text = sc.get_token_text(); + + error ("at %1:%2: expected %3, got %4", + g_file_name_stack.last(), + sc.get_line(), + describe_token_type (tt), + describe_token (&tok)); + } } // ============================================================================= @@ -199,20 +261,11 @@ switch (tok_type) { - case tk_symbol: - return tok ? tok->text : "a symbol"; - - case tk_number: - return tok ? tok->text : "a number"; - - case tk_string: - return tok ? ("\"" + tok->text + "\"") : "a string"; - - case tk_any: - return tok ? tok->text : "any token"; - - default: - break; + case tk_symbol: return tok ? tok->text : "a symbol"; + case tk_number: return tok ? tok->text : "a number"; + case tk_string: return tok ? ("\"" + tok->text + "\"") : "a string"; + case tk_any: return tok ? tok->text : "any token"; + default: break; } return "";