|
|
- #pragma once
-
- #include "gp/containers/array.hpp"
- #include "gp/containers/vector.hpp"
- #include "gp/text/ascii.hpp"
-
- using string = gp::vector<char>;
-
- #define FOREACH_LEXEME_TYPE \
- LEX(leftBracket) \
- LEX(rightBracket) \
- LEX(leftParenthesis) \
- LEX(rightParenthesis) \
- LEX(leftCurlyBrace) \
- LEX(rightCurlyBrace) \
- LEX(period) \
- LEX(semicolon) \
- LEX(colon) \
- LEX(doubleColon) \
- LEX(comma) \
- LEX(at) \
- LEX(pointer) \
- LEX(as) \
- LEX(try_) \
- LEX(catch_) \
- LEX(raise_) \
- LEX(defer) \
- LEX(assign) \
- LEX(addAssign) \
- LEX(substractAssign) \
- LEX(multiplyAssign) \
- LEX(divideAssign) \
- LEX(concatenateAssign) \
- LEX(remainderAssign) \
- LEX(powerAssign) \
- LEX(plus) \
- LEX(minus) \
- LEX(add) \
- LEX(substract) \
- LEX(multiply) \
- LEX(divide) \
- LEX(concatenate) \
- LEX(remainder) \
- LEX(power) \
- LEX(equal) \
- LEX(doubleEqual) \
- LEX(threeWayComparison) \
- LEX(notEqual) \
- LEX(greaterOrEqual) \
- LEX(greater) \
- LEX(lesserOrEqual) \
- LEX(lesser) \
- LEX(leftShift) \
- LEX(rightShift) \
- LEX(and_) \
- LEX(or_) \
- LEX(xor_) \
- LEX(not_) \
- LEX(increment) \
- LEX(decrement) \
- LEX(identifier) \
- LEX(integer) \
- LEX(float_) \
- LEX(boolean) \
- LEX(string_) \
- LEX(null_) \
- LEX(public_) \
- LEX(main_) \
- LEX(type_) \
- LEX(event_) \
- LEX(class_) \
- LEX(enum_) \
- LEX(template_) \
- LEX(new_) \
- LEX(copy) \
- LEX(send) \
- LEX(receive) \
- LEX(intType) \
- LEX(floatType) \
- LEX(boolType) \
- LEX(stringType) \
- LEX(arrayType) \
- LEX(functionType) \
- LEX(taskType) \
- LEX(chanType) \
- LEX(autoType) \
- LEX(if_) \
- LEX(unless) \
- LEX(else_) \
- LEX(switch_) \
- LEX(select) \
- LEX(case_) \
- LEX(while_) \
- LEX(do_) \
- LEX(until) \
- LEX(for_) \
- LEX(loop) \
- LEX(return_) \
- LEX(self) \
- LEX(kill) \
- LEX(killAll) \
- LEX(yield) \
- LEX(break_) \
- LEX(continue_)
-
- #define LEX(x) x,
- enum class gr_lexeme_type {
- FOREACH_LEXEME_TYPE
- };
- #undef LEX
-
- #define LEX(x) case gr_lexeme_type::x: return #x;
- constexpr inline const char* to_string(const gr_lexeme_type& value) {
- switch(value) {
- FOREACH_LEXEME_TYPE
- }
- }
- #undef LEX
-
- #define LEX(x) +1
- constexpr inline const char* to_pretty_string(const gr_lexeme_type& value) {
- constexpr gp::array<const char*, 0 + FOREACH_LEXEME_TYPE> names = {
- "[", "]", "(", ")", "{", "}", ".", ";", ":", "::", ",", "@", "&", "as",
- "try", "catch", "raise", "defer", "=", "+=", "-=", "*=", "/=", "~=",
- "%=", "^=", "+", "-", "+", "-", "*", "/", "~", "%", "^", "==", "===",
- "<=>", "!=", ">=", ">", "<=", "<", "<<", ">>", "and", "or", "xor", "not", "++",
- "--", "identifier", "const_int", "const_float", "const_bool",
- "const_str", "null", "pub", "main", "type", "event", "class", "enum",
- "template", "new", "copy", "send", "receive", "int", "float", "bool",
- "string", "array", "func", "task", "chan", "let", "if", "unless",
- "else", "switch", "select", "case", "while", "do", "until", "for", "loop",
- "return", "self", "kill", "killall", "yield", "break", "continue"
- };
- return names[(size_t)value];
- }
- #undef LEX
-
- struct gr_lexeme;
-
- class gr_lexer {
- public:
- using file_loader_t = gp::function<gp::vector<char>(const gp::vector<char>&)>;
- gp::allocator& _allocator;
- file_loader_t file_loader;
- private:
- gp::vector<string> _files_to_import, _files_imported, _lines;
-
- string _file, _text;
- uint64_t _line, _current, _position_of_line, _file_id;
-
- gp::vector<gr_lexeme> _lexemes;
-
- char get(ssize_t offset = 0);
- bool advance(bool start_from_current = false);
- void scan_script();
- void scan_number();
- void scan_string();
- void scan_operator();
- void scan_word();
- void scan_file_path();
- void scan_use();
- string convert_path_to_import(string&);
-
- public:
-
- gr_lexer(gp::allocator& alloc, file_loader_t& loader)
- : _allocator(alloc)
- , file_loader(loader)
- , _files_to_import(_allocator)
- , _files_imported(_allocator)
- , _lines(_allocator)
- , _file(_allocator)
- , _text(_allocator)
- , _lexemes(_allocator)
- {}
-
- const gp::vector<gr_lexeme>& lexemes() {
- return _lexemes;
- }
-
- void scan_file(gp::vector<char>& file_name);
-
- const string& get_line(const gr_lexeme&) const;
- const string& get_file(const gr_lexeme&) const;
- const string& get_file(const size_t&) const;
- };
-
- struct gr_lexeme {
- const gr_lexer& lexer;
- size_t _file_id;
- size_t _line, _column, _text_length = 1;
-
- gr_lexeme_type type;
- bool
- is_literal,
- is_operator,
- is_keyword,
- is_type;
- int ivalue;
- float fvalue;
- bool bvalue;
- string svalue;
-
- gr_lexeme(const gr_lexer& v)
- : lexer(v)
- , svalue(v._allocator)
- {}
-
- const string& get_line() const {
- return lexer.get_line(*this);
- }
-
- const string& get_file() {
- return lexer.get_file(*this);
- }
- };
-
- inline char gr_lexer::get(ssize_t offset) {
- const uint position = ssize_t(_current) + offset;
- gp_config::assertion(!(position < 0 || position >= _text.size()), "Unexpected end of script");
- return _text[position];
- }
-
- inline const string& gr_lexer::get_line(const gr_lexeme& lex) const {
- gp_config::assertion(!(lex._file_id >= _files_imported.size()), "Lexeme file id out of bounds");
- // TODO: Implement this
- return _files_imported[lex._file_id];
- }
-
- inline const string& gr_lexer::get_file(const gr_lexeme& lex) const {
- gp_config::assertion(!(lex._file_id >= _files_imported.size()), "Lexeme file id out of bounds");
- return _files_imported[lex._file_id];
- }
-
- inline const string& gr_lexer::get_file(const size_t& file_id) const {
- gp_config::assertion(!(file_id >= _files_imported.size()), "File id out of bounds");
- return _files_imported[file_id];
- }
-
- inline bool gr_lexer::advance(bool start_from_current) {
- if(!start_from_current) {
- _current++;
- }
-
- if(_current >= _text.size()) {
- return false;
- }
-
- char symbol = _text[_current];
-
- whileLoop: while(symbol <= 0x20 || symbol == '/' || symbol == '#') {
- if(_current >= _text.size()) {
- return false;
- }
-
- symbol = _text[_current];
-
- if(symbol == '\n') {
- _position_of_line = _current;
- _line++;
- }
- else if(symbol == '#')
- {
- do {
- if(_current >= _text.size()) return false;
- _current++;
- } while (_text[_current] != '\n');
- _position_of_line = _current;
- _line++;
- }
- else if(symbol == '/')
- {
- if((_current + 1) >= _text.size()) {
- return false;
- }
-
- switch(_text[_current + 1]) {
- case '/': {
- do {
- if(_current >= _text.size()) {
- return false;
- }
- } while(_current < _text.size() && _text[_current] != '\n');
- _position_of_line = _current;
- _line++;
- }break;
- case '*': {
- for(;;) {
- if((_current + 1) >= _text.size()) {
- _current++;
- return false;
- }
-
- if(_text[_current] == '\n') {
- _position_of_line = _current;
- _line++;
- }
-
- if(_text[_current] == '*' && _text[_current + 1] == '/') {
- _current++;
- break;
- }
-
- _current++;
- }
- }break;
- default:
- // Goto honorable
- goto whileLoop;
- }
- }
-
- _current++;
-
- if(_current >= _text.size()) {
- return false;
- }
-
- symbol = _text[_current];
- }
- return true;
- }
-
- inline void gr_lexer::scan_script() {
- advance(true);
-
- constexpr static auto is_operator = [](char v) {
- if(v == '!') return true;
- if(v >= '#' && v <='&') return true;
- if(v >= '(' && v <='-') return true;
- if(v == '/') return true;
- if(v >= ':' && v <='@') return true;
- if(v >= '[' && v <='^') return true;
- if(v >= '{' && v <='~') return true;
- return false;
- };
-
- do {
- if (_current >= _text.size())
- break;
- auto c = get();
- if(is_digit(c)) scan_number();
- else if(c == '.') {
- if (get(1) >= '0' && get(1) <= '9')
- scan_number();
- else
- scan_operator();
- }
- else if(is_operator(c)) scan_operator();
- else if(c == '\"') scan_string();
- else scan_word();
- }while (advance());
- }
-
- inline void gr_lexer::scan_number(){
- gr_lexeme lex = gr_lexeme(*this);
- lex.is_literal = true;
-
- bool isFloat;
- string buffer(_allocator);
- for (;;) {
- char symbol = get();
-
- if (symbol >= '0' && symbol <= '9')
- buffer.push_back(symbol);
- else if (symbol == '_') {
- // Do nothing, only cosmetic (e.g. 1_000_000).
- }
- else if (symbol == '.') {
- if (isFloat)
- break;
- isFloat = true;
- buffer.push_back(symbol);
- }
- else if (symbol == 'f') {
- isFloat = true;
- break;
- }
- else {
- if (_current)
- _current--;
- break;
- }
-
- _current++;
-
- if (_current >= _text.size())
- break;
- }
- }
-
- inline void gr_lexer::scan_string(){
- gr_lexeme lex = gr_lexeme(*this);
- lex.type = gr_lexeme_type::string_;
- lex.is_literal = true;
-
- gp_config::assertion(get() != '\"',"Expected \'\"\' at the beginning of the string.");
- _current++;
-
- string buffer(_allocator);
- bool escape = false;
- bool wasEscape = false;
- for (;;) {
- gp_config::assertion(_current >= _text.size(),"Missing \'\"\' character.");
- char symbol = get();
-
- if (symbol == '\n') {
- _position_of_line = _current;
- _line++;
- }
- else if (symbol == '\"' && (!wasEscape))
- break;
- else if (symbol == '\\' && (!wasEscape)) {
- escape = true;
- }
-
- if (!escape) {
- if (!wasEscape) {
- buffer.push_back(symbol);
- }
- else {
- if (symbol == 'n')
- buffer.push_back('\n');
- else
- buffer.push_back(symbol);
- }
- }
- wasEscape = escape;
- escape = false;
-
- _current++;
- }
-
- lex._text_length = size_t(buffer.size() + 2u);
- lex.svalue = buffer;
- _lexemes.push_back(lex);
- }
-
- inline void gr_lexer::scan_operator(){
- gr_lexeme lex = gr_lexeme(*this);
- lex.is_operator = true;
-
- switch (get()) {
- case '{':
- lex.type = gr_lexeme_type::leftCurlyBrace;
- break;
- case '}':
- lex.type = gr_lexeme_type::rightCurlyBrace;
- break;
- case '(':
- lex.type = gr_lexeme_type::leftParenthesis;
- break;
- case ')':
- lex.type = gr_lexeme_type::rightParenthesis;
- break;
- case '[':
- lex.type = gr_lexeme_type::leftBracket;
- break;
- case ']':
- lex.type = gr_lexeme_type::rightBracket;
- break;
- case '.':
- lex.type = gr_lexeme_type::period;
- break;
- case ';':
- lex.type = gr_lexeme_type::semicolon;
- break;
- case ':':
- lex.type = gr_lexeme_type::colon;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == ':') {
- lex.type = gr_lexeme_type::doubleColon;
- lex._text_length = 2;
- _current++;
- }
- break;
- case ',':
- lex.type = gr_lexeme_type::comma;
- break;
- case '^':
- lex.type = gr_lexeme_type::power;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::powerAssign;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '@':
- lex.type = gr_lexeme_type::at;
- break;
- case '&':
- lex.type = gr_lexeme_type::pointer;
- break;
- case '~':
- lex.type = gr_lexeme_type::concatenate;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::concatenateAssign;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '+':
- lex.type = gr_lexeme_type::add;
- if (_current + 1 >= _text.size())
- break;
- switch (get(1)) {
- case '=':
- lex.type = gr_lexeme_type::addAssign;
- lex._text_length = 2;
- _current++;
- break;
- case '+':
- lex.type = gr_lexeme_type::increment;
- lex._text_length = 2;
- _current++;
- break;
- default:
- break;
- }
- break;
- case '-':
- lex.type = gr_lexeme_type::substract;
- if (_current + 1 >= _text.size())
- break;
- switch (get(1)) {
- case '=':
- lex.type = gr_lexeme_type::substractAssign;
- lex._text_length = 2;
- _current++;
- break;
- case '-':
- lex.type = gr_lexeme_type::decrement;
- lex._text_length = 2;
- _current++;
- break;
- default:
- break;
- }
- break;
- case '*':
- lex.type = gr_lexeme_type::multiply;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::multiplyAssign;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '/':
- lex.type = gr_lexeme_type::divide;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::divideAssign;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '%':
- lex.type = gr_lexeme_type::remainder;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::remainderAssign;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '=':
- lex.type = gr_lexeme_type::assign;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::equal;
- lex._text_length = 2;
- _current++;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::doubleEqual;
- lex._text_length = 3;
- _current++;
- }
- }
- break;
- case '<':
- lex.type = gr_lexeme_type::lesser;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::lesserOrEqual;
- lex._text_length = 2;
- _current++;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '>') {
- lex.type = gr_lexeme_type::threeWayComparison;
- lex._text_length = 3;
- _current++;
- }
- }
- else if (get(1) == '-') {
- lex.type = gr_lexeme_type::send;
- lex._text_length = 2;
- _current++;
- }
- else if (get(1) == '<') {
- lex.type = gr_lexeme_type::leftShift;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '>':
- lex.type = gr_lexeme_type::greater;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::greaterOrEqual;
- lex._text_length = 2;
- _current++;
- }
- else if (get(1) == '>') {
- lex.type = gr_lexeme_type::rightShift;
- lex._text_length = 2;
- _current++;
- }
- break;
- case '!':
- lex.type = gr_lexeme_type::not_;
- if (_current + 1 >= _text.size())
- break;
- if (get(1) == '=') {
- lex.type = gr_lexeme_type::notEqual;
- lex._text_length = 2;
- _current++;
- }
- break;
- default:
- gp_config::assertion(false, "GrLexer: invalid operator");
- }
-
- _lexemes.push_back(lex);
- }
-
- namespace _hidden {
- bool operator==(const gp::vector<char>& lhs, const char* rhs) {
- for(size_t index = 0; index < lhs.size() && rhs[index] != 0; index++){
- if(lhs[index] != rhs[index]) return false;
- }
- return true;
- }
- }
-
- inline void gr_lexer::scan_word(){
- gr_lexeme lex = gr_lexeme(*this);
- lex.is_keyword = true;
-
- string symbol_buffer(_allocator);
- for (;;) {
- if (_current >= _text.size())
- break;
-
- char symbol = get();
- if (symbol == '!' || symbol == '?') {
- symbol_buffer.push_back(symbol);
- _current++;
- break;
- }
- if (symbol <= '&' || (symbol >= '(' && symbol <= '/') || (symbol >= ':'
- && symbol <= '@') || (symbol >= '[' && symbol <= '^')
- || (symbol >= '{' && symbol <= 0x7F))
- break;
-
- symbol_buffer.push_back(symbol);
- _current++;
- }
- _current--;
-
- lex._text_length = symbol_buffer.size();
-
- using namespace _hidden;
-
- if(symbol_buffer == "use"){
- scan_use();
- return;
- }
- else if(symbol_buffer == "pub"){
- lex.type = gr_lexeme_type::public_;
- }
- else if(symbol_buffer == "main"){
- lex.type = gr_lexeme_type::main_;
- }
- else if(symbol_buffer == "type"){
- lex.type = gr_lexeme_type::type_;
- }
- else if(symbol_buffer == "event"){
- lex.type = gr_lexeme_type::event_;
- }
- else if(symbol_buffer == "class"){
- lex.type = gr_lexeme_type::class_;
- }
- else if(symbol_buffer == "enum"){
- lex.type = gr_lexeme_type::enum_;
- }
- else if(symbol_buffer == "template"){
- lex.type = gr_lexeme_type::template_;
- }
- else if(symbol_buffer == "if"){
- lex.type = gr_lexeme_type::if_;
- }
- else if(symbol_buffer == "unless"){
- lex.type = gr_lexeme_type::unless;
- }
- else if(symbol_buffer == "else"){
- lex.type = gr_lexeme_type::else_;
- }
- else if(symbol_buffer == "switch"){
- lex.type = gr_lexeme_type::switch_;
- }
- else if(symbol_buffer == "select"){
- lex.type = gr_lexeme_type::select;
- }
- else if(symbol_buffer == "case"){
- lex.type = gr_lexeme_type::case_;
- }
- else if(symbol_buffer == "while"){
- lex.type = gr_lexeme_type::while_;
- }
- else if(symbol_buffer == "do"){
- lex.type = gr_lexeme_type::do_;
- }
- else if(symbol_buffer == "until"){
- lex.type = gr_lexeme_type::until;
- }
- else if(symbol_buffer == "for"){
- lex.type = gr_lexeme_type::for_;
- }
- else if(symbol_buffer == "loop"){
- lex.type = gr_lexeme_type::loop;
- }
- else if(symbol_buffer == "return"){
- lex.type = gr_lexeme_type::return_;
- }
- else if(symbol_buffer == "self"){
- lex.type = gr_lexeme_type::self;
- }
- else if(symbol_buffer == "kill"){
- lex.type = gr_lexeme_type::kill;
- }
- else if(symbol_buffer == "killall"){
- lex.type = gr_lexeme_type::killAll;
- }
- else if(symbol_buffer == "yield"){
- lex.type = gr_lexeme_type::yield;
- }
- else if(symbol_buffer == "break"){
- lex.type = gr_lexeme_type::break_;
- }
- else if(symbol_buffer == "continue"){
- lex.type = gr_lexeme_type::continue_;
- }
- else if(symbol_buffer == "as"){
- lex.type = gr_lexeme_type::as;
- }
- else if(symbol_buffer == "try"){
- lex.type = gr_lexeme_type::try_;
- }
- else if(symbol_buffer == "catch"){
- lex.type = gr_lexeme_type::catch_;
- }
- else if(symbol_buffer == "raise"){
- lex.type = gr_lexeme_type::raise_;
- }
- else if(symbol_buffer == "defer"){
- lex.type = gr_lexeme_type::defer;
- }
- else if(symbol_buffer == "task"){
- lex.type = gr_lexeme_type::taskType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "func"){
- lex.type = gr_lexeme_type::functionType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "int"){
- lex.type = gr_lexeme_type::intType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "float"){
- lex.type = gr_lexeme_type::floatType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "bool"){
- lex.type = gr_lexeme_type::boolType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "string"){
- lex.type = gr_lexeme_type::stringType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "array"){
- lex.type = gr_lexeme_type::arrayType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "chan"){
- lex.type = gr_lexeme_type::chanType;
- lex.is_type = true;
- }
- else if(symbol_buffer == "new"){
- lex.type = gr_lexeme_type::new_;
- lex.is_type = false;
- }
- else if(symbol_buffer == "let"){
- lex.type = gr_lexeme_type::autoType;
- lex.is_type = false;
- }
- else if(symbol_buffer == "true"){
- lex.type = gr_lexeme_type::boolean;
- lex.is_keyword = false;
- lex.is_literal = true;
- lex.bvalue = true;
- }
- else if(symbol_buffer == "false"){
- lex.type = gr_lexeme_type::boolean;
- lex.is_keyword = false;
- lex.is_literal = true;
- lex.bvalue = false;
- }
- else if(symbol_buffer == "null"){
- lex.type = gr_lexeme_type::null_;
- lex.is_keyword = false;
- lex.is_literal = true;
- }
- else if(symbol_buffer == "not"){
- lex.type = gr_lexeme_type::not_;
- lex.is_keyword = false;
- lex.is_operator = true;
- }
- else if(symbol_buffer == "and"){
- lex.type = gr_lexeme_type::and_;
- lex.is_keyword = false;
- lex.is_operator = true;
- }
- else if(symbol_buffer == "or"){
- lex.type = gr_lexeme_type::or_;
- lex.is_keyword = false;
- lex.is_operator = true;
- }
- else if(symbol_buffer == "xor"){
- lex.type = gr_lexeme_type::xor_;
- lex.is_keyword = false;
- lex.is_operator = true;
- } else {
- lex.is_keyword = false;
- lex.type = gr_lexeme_type::identifier;
- lex.svalue = symbol_buffer;
- }
-
- _lexemes.push_back(lex);
- }
-
- inline string gr_lexer::convert_path_to_import(string& path) {
- return path;
- }
-
- inline void gr_lexer::scan_file(gp::vector<char>& file_name){
- _files_to_import.push_back(file_name);
-
- while (_files_to_import.size()) {
- _file = _files_to_import[_files_to_import.size()-1];
- _files_imported.push_back(_file);
- _text = file_loader(file_name);
- _files_to_import.pop_back();
-
- _line = 0u;
- _current = 0u;
- _lines = gp::vector<string>(_allocator);
-
- gp::vector<char> tmp(_allocator);
- for(char c : _text) {
- if(c == '\n') {
- _lines.push_back(tmp);
- tmp = gp::vector<char>(_allocator);
- } else {
- tmp.push_back(c);
- }
- }
-
- scan_script();
-
- _file_id++;
- }
- }
-
- inline void gr_lexer::scan_file_path(){
- gp_config::assertion(get() != '\"', "Expected \'\"\' at the beginning of the import.");
- _current++;
-
- string buffer(_allocator);
- for (;;) {
- gp_config::assertion(_current >= _text.size(), "Missing \'\"\' character.");
- char symbol = get();
- if (symbol == '\n') {
- _position_of_line = _current;
- _line++;
- }
- else if (symbol == '\"')
- break;
-
- buffer.push_back(symbol);
- _current++;
- }
- buffer = convert_path_to_import(buffer);
-
- for(auto& file : _files_imported) {
- if(file == buffer) return;
- }
- for(auto& file : _files_to_import) {
- if(file == buffer) return;
- }
-
- _files_to_import.push_back(buffer);
- }
-
- inline void gr_lexer::scan_use(){
- advance();
-
- // Multiple files import.
- if (get() == '{') {
- advance();
- bool isFirst = true;
- for (;;) {
- if (isFirst)
- isFirst = false;
- else if (get() == '\"')
- advance();
- else
- gp_config::assertion(false, "Missing \'}\' after import list.");
- // EOF
- gp_config::assertion(_current >= _text.size(), "Missing \'}\' after import list.");
- // End of the import list.
- if (get() == '}')
- break;
- // Scan
- scan_file_path();
- }
- }
- else {
- scan_file_path();
- }
- }
|