X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Ftokenizer.cpp;h=4064d805e732dc8adaf5dbb912df1ce0824909bb;hp=e73afd5273add2dec2f907f223b2b1e5421b9f9d;hb=38712d8ecc57d043a2419ffbaeeb57f7a6586f14;hpb=c1ec86d6b9ceb6c71f787fed3b2ea6c75457a474 diff --git a/source/glsl/tokenizer.cpp b/source/glsl/tokenizer.cpp index e73afd52..4064d805 100644 --- a/source/glsl/tokenizer.cpp +++ b/source/glsl/tokenizer.cpp @@ -10,16 +10,14 @@ namespace Msp { namespace GL { namespace SL { -Tokenizer::Tokenizer(): - allow_preprocess(true) +Tokenizer::Tokenizer() { static string empty; iter = empty.begin(); source_end = empty.end(); - location.line = 0; } -void Tokenizer::begin(const string &name, const string &src) +void Tokenizer::begin(const string &src, const string &name) { iter = src.begin(); source_end = src.end(); @@ -34,11 +32,13 @@ const string &Tokenizer::peek_token(unsigned index) { while(next_tokens.size()<=index) next_tokens.push_back(parse_token_()); - return (last_token = next_tokens[index]); + return next_tokens[index]; } const string &Tokenizer::parse_token() { + progress_mark = true; + if(!next_tokens.empty()) { last_token = next_tokens.front(); @@ -56,6 +56,12 @@ void Tokenizer::expect(const string &token) throw parse_error(location, parsed, format("'%s'", token)); } +void Tokenizer::set_location(const Location &loc) +{ + location = loc; + suppress_line_advance = true; +} + string Tokenizer::parse_token_() { while(1) @@ -74,7 +80,9 @@ string Tokenizer::parse_token_() return parse_identifier(); else if(isdigit(*iter)) return parse_number(); - else if(*iter=='"' || *iter=='#' || *iter=='$' || *iter=='\'' || *iter=='@' || *iter=='\\' || *iter=='`') + else if(*iter=='"') + return parse_string(); + else if(*iter=='#' || *iter=='$' || *iter=='\'' || *iter=='@' || *iter=='\\' || *iter=='`') throw syntax_error(location, string(1, *iter), "Invalid character in source"); else return parse_other(); @@ -85,7 +93,7 @@ void Tokenizer::preprocess() { SetForScope > clear_tokens(next_tokens, deque()); - string::const_iterator line_end = iter; + auto line_end = iter; for(; (line_end!=source_end && *line_end!='\n'); ++line_end) ; SetForScope stop_at_line_end(source_end, line_end); @@ -126,7 +134,9 @@ string Tokenizer::parse_number() } bool require_digit = false; - if(iter!=source_end && (*iter=='e' || *iter=='E')) + if(iter==source_end) + ; + else if(*iter=='e' || *iter=='E') { number += *iter++; if(iter!=source_end && (*iter=='-' || *iter=='+')) @@ -142,16 +152,39 @@ string Tokenizer::parse_number() else break; } + if(!require_digit && iter!=source_end && *iter=='f') + number += *iter++; } + else if(*iter=='u' || *iter=='f') + number += *iter++; if(require_digit) throw syntax_error(location, number, "Incomplete numeric literal"); - else if(isalnum(*iter) || *iter=='_') + else if(iter!=source_end && (isalnum(*iter) || *iter=='_')) throw syntax_error(location, number, "Garbage at end of numeric literal"); return number; } +string Tokenizer::parse_string() +{ + string str(1, *iter++); + bool escape = false; + while(iter!=source_end) + { + char c = *iter++; + str += c; + if(c=='\\') + escape = true; + else if(c=='"' && !escape) + break; + else + escape = false; + } + + return str; +} + string Tokenizer::parse_other() { if(iter==source_end) @@ -219,12 +252,15 @@ void Tokenizer::skip_comment_and_whitespace() if(*iter=='\n') { - ++location.line; + if(!suppress_line_advance) + ++location.line; allow_preprocess = (comment<3); } ++iter; } + + suppress_line_advance = false; } } // namespace SL