Advertisement
Guest User

lex.cpp

a guest
Oct 16th, 2019
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.01 KB | None | 0 0
  1. Vector<Token> lex(Source& src) {
  2.   LexerIterator it = LexerIterator::create(src);
  3.   Vector<Token> tokens = Vector<Token>::create(2056);
  4.  
  5.   while(it.valid()) {
  6.     while(it.is_whitespace()) { it.advance(); }
  7.     if(it.current() == '#') {
  8.       while(!it.is_newline() && it.valid()) { it.advance(); }
  9.       continue;
  10.     }
  11.     if(it.is_alphabetical()) {
  12.       KeywordKind kwkind = KeywordKind::none;
  13.  
  14.       it.mark();
  15.       it.advance();
  16.       while(it.is_alphanumeric()) { it.advance(); }
  17.       for(size_t i = 0; i < VOID_ARRAY_LEN(KEYWORDS); ++ i) {
  18.         ReservedToken const& kw = KEYWORDS[i];
  19.  
  20.         if(it.mark_distance() == kw.str_len && memcmp(it.mark_it, kw.str, kw.str_len) == 0) {
  21.           kwkind = KeywordKind(i);
  22.           break;
  23.         }
  24.       }
  25.       if(kwkind == KeywordKind::none) { tokens.add(Token::create(it.mark_it, it.it)); }
  26.       else { tokens.add(Token::create(kwkind, it.mark_it, it.it)); }
  27.     }
  28.     if(it.current() == '0' && (it.next() == 'x' || it.next() == 'X')) {
  29.       bool invalid_char = false;
  30.  
  31.       it.mark();
  32.       it.advance(2);
  33.       while(it.is_alphanumeric()) {
  34.         if(!it.is_hexadecimal()) { invalid_char = true; }
  35.         it.advance();
  36.       }
  37.       unsigned long long val = 0;
  38.  
  39.       if(distance(it.mark_it + 2, it.it) == 0) {
  40.         src.error(it.mark_it, it.it, "Expected hexadecimal numbers");
  41.       }
  42.       if(invalid_char) { src.error(it.mark_it, it.it, "Invalid hexadecimal character"); }
  43.       if(!hex_str_to_u64(it.mark_it, distance(it.mark_it, it.it), val)) {
  44.         src.error(it.mark_it, it.it, "Invalid hexadecimal literal");
  45.       }
  46.       tokens.add(Token::create(val, it.mark_it, it.it));
  47.     }
  48.     if(it.current() == '0' && (it.next() == 'b' || it.next() == 'B')) {
  49.       bool invalid_char = false;
  50.  
  51.       it.mark();
  52.       it.advance(2);
  53.       while(it.is_alphanumeric()) {
  54.         if(!it.is_binary()) { invalid_char = true; }
  55.         it.advance();
  56.       }
  57.       unsigned long long val = 0;
  58.  
  59.       if(distance(it.mark_it + 2, it.it) == 0) {
  60.         src.error(it.mark_it, it.it, "Expected binary numbers");
  61.       }
  62.       if(invalid_char) { src.error(it.mark_it, it.it, "Invalid binary character"); }
  63.       if(!bin_str_to_u64(it.mark_it + 2, distance(it.mark_it, it.it) - 2, val)) {
  64.         src.error(it.mark_it, it.it, "Invalid binary literal");
  65.       }
  66.       tokens.add(Token::create(val, it.mark_it, it.it));
  67.     }
  68.     if(it.is_numeric() || (it.current() == '.' && it.is_next_numeric())) {
  69.       int exponent_cnt = 0;
  70.       bool expect_num = false;
  71.       bool is_point = false;
  72.      
  73.       it.mark();
  74.       while(it.is_alphanumeric()) {
  75.         if(it.current() == 'e' || it.current() == 'E') {
  76.           is_point = true;
  77.           ++ exponent_cnt;
  78.           it.advance();
  79.           if(it.current() == '-' || it.current() == '+') { it.advance(); }
  80.           if(!it.is_numeric()) { expect_num = true; }
  81.           continue;
  82.         }
  83.         it.advance();
  84.       }
  85.       if(it.current() == '.' && it.is_next_numeric()) {
  86.         is_point = true;
  87.         it.advance();
  88.       }
  89.       while(it.is_alphanumeric()) {
  90.         if(it.current() == 'e' || it.current() == 'E') {
  91.           is_point = true;
  92.           ++ exponent_cnt;
  93.           it.advance();
  94.           if(it.current() == '-' || it.current() == '+') { it.advance(); }
  95.           if(!it.is_numeric()) { expect_num = true; }
  96.           continue;
  97.         }
  98.         it.advance();
  99.       }
  100.       if(exponent_cnt > 1) { src.error(it.mark_it, it.it, "Too many exponentials in floating point literal"); }
  101.       if(expect_num) { src.error(it.mark_it, it.it, "Expected number after exponential"); }
  102.       unsigned long long int_val = 0;
  103.       double point_val = 0;
  104.  
  105.       if(is_point) {
  106.         if(!str_to_f64(it.mark_it, it.mark_distance(), point_val)) {
  107.           src.error(it.mark_it, it.it, "Invalid floating point literal");
  108.         }
  109.         tokens.add(Token::create(point_val, it.mark_it, it.it));
  110.       } else {
  111.         if(!str_to_u64(it.mark_it, it.mark_distance(), int_val)) {
  112.           src.error(it.mark_it, it.it, "Invalid integer literal");
  113.         }
  114.         tokens.add(Token::create(int_val, it.mark_it, it.it));
  115.       }
  116.     }
  117.     for(size_t i = 0; i < VOID_ARRAY_LEN(OPERATORS); ++ i) {
  118.       ReservedToken const& op = OPERATORS[i];
  119.  
  120.       if(memcmp(it.it, op.str, op.str_len) == 0) {
  121.         it.mark();
  122.         it.advance(op.str_len);
  123.         tokens.add(Token::create(OperatorKind(i), it.mark_it, it.it));
  124.         break;
  125.       }
  126.     }
  127.     if(it.current() == '"') {
  128.       String str = String::create();
  129.       bool closed = false;
  130.  
  131.       it.mark();
  132.       it.advance();
  133.       while(it.valid()) {
  134.         if(it.current() == '"') {
  135.           it.advance();
  136.           closed = true;
  137.           break;
  138.         }
  139.         if(it.current() == '\\') {
  140.           char const* start = it.it;
  141.  
  142.           it.advance();
  143.           switch(it.current()) {
  144.             case 'a':
  145.             case 'A':
  146.               str.add('\a');
  147.               it.advance();
  148.             break;
  149.             case 'b':
  150.             case 'B':
  151.               str.add('\b');
  152.               it.advance();
  153.             break;
  154.             case 'f':
  155.             case 'F':
  156.               str.add('\f');
  157.               it.advance();
  158.             break;
  159.             case 'n':
  160.             case 'N':
  161.               str.add('\n');
  162.               it.advance();
  163.             break;
  164.             case 'r':
  165.             case 'R':
  166.               str.add('\r');
  167.               it.advance();
  168.             break;
  169.             case 't':
  170.             case 'T':
  171.               str.add('\t');
  172.               it.advance();
  173.             break;
  174.             case 'v':
  175.             case 'V':
  176.               str.add('\v');
  177.               it.advance();
  178.             break;
  179.             case '\\':
  180.               str.add('\\');
  181.               it.advance();
  182.             break;
  183.             case '\'':
  184.               str.add('\'');
  185.               it.advance();
  186.             break;
  187.             case '\"':
  188.               str.add('\"');
  189.               it.advance();
  190.             break;
  191.             case '\?':
  192.               str.add('\?');
  193.               it.advance();
  194.             break;
  195.             case '0':
  196.               str.add('\0');
  197.               it.advance();
  198.             break;
  199.             case 'U':
  200.             case 'u':
  201.             {
  202.               size_t len = 0;
  203.               bool invalid_char = false;
  204.  
  205.               it.advance();
  206.               for(size_t i = 0; i < 8; ++ i) {
  207.                 if(it.current() == '"') { break; }
  208.                 if(it.current() == '\\') { it.advance(); break; }
  209.                 if(!it.is_hexadecimal()) { invalid_char = true; }
  210.                 it.advance();
  211.                 ++ len;
  212.               }
  213.               unsigned long long val = 0;
  214.  
  215.               if(len == 0) { src.error(start, it.it, "Expected hexadecimal numbers"); }
  216.               if(invalid_char) { src.error(start, it.it, "Invalid character in hexadecimal literal"); }
  217.               if(!hex_str_to_u64(start + 2, len, val)) {
  218.                 src.error(start, it.it, "Invalid unicode escape sequence");
  219.               }
  220.               char c_cache[5] {};
  221.  
  222.               to_utf8_str(val, c_cache);
  223.               str.add(c_cache);
  224.             }
  225.             break;
  226.             default:
  227.               it.advance();
  228.               src.error(start, it.it, "Unknown escape sequence");
  229.             break;
  230.           }
  231.           continue;
  232.         }
  233.         str.add(it.it, it.char_size());
  234.         it.advance();
  235.       }
  236.       if(!closed) { src.error(it.mark_it, it.it, "Expected closing `\"`"); }
  237.       tokens.add(Token::create(str, it.mark_it, it.it));
  238.     }
  239.     if(it.current() == '\'') {
  240.       String str = String::create();
  241.       bool closed = false;
  242.  
  243.       it.mark();
  244.       it.advance();
  245.       while(it.valid()) {
  246.         if(it.current() == '\'') {
  247.           it.advance();
  248.           closed = true;
  249.           break;
  250.         }
  251.         if(it.current() == '\\') {
  252.           char const* start = it.it;
  253.  
  254.           it.advance();
  255.           switch(it.current()) {
  256.             case 'a':
  257.             case 'A':
  258.               str.add('\a');
  259.               it.advance();
  260.             break;
  261.             case 'b':
  262.             case 'B':
  263.               str.add('\b');
  264.               it.advance();
  265.             break;
  266.             case 'f':
  267.             case 'F':
  268.               str.add('\f');
  269.               it.advance();
  270.             break;
  271.             case 'n':
  272.             case 'N':
  273.               str.add('\n');
  274.               it.advance();
  275.             break;
  276.             case 'r':
  277.             case 'R':
  278.               str.add('\r');
  279.               it.advance();
  280.             break;
  281.             case 't':
  282.             case 'T':
  283.               str.add('\t');
  284.               it.advance();
  285.             break;
  286.             case 'v':
  287.             case 'V':
  288.               str.add('\v');
  289.               it.advance();
  290.             break;
  291.             case '\\':
  292.               str.add('\\');
  293.               it.advance();
  294.             break;
  295.             case '\'':
  296.               str.add('\'');
  297.               it.advance();
  298.             break;
  299.             case '\"':
  300.               str.add('\"');
  301.               it.advance();
  302.             break;
  303.             case '\?':
  304.               str.add('\?');
  305.               it.advance();
  306.             break;
  307.             case '0':
  308.               str.add('\0');
  309.               it.advance();
  310.             break;
  311.             case 'U':
  312.             case 'u':
  313.             {
  314.               size_t len = 0;
  315.               bool invalid_char = false;
  316.  
  317.               it.advance();
  318.               for(size_t i = 0; i < 8; ++ i) {
  319.                 if(it.current() == '\'') { break; }
  320.                 if(it.current() == '\\') { it.advance(); break; }
  321.                 if(!it.is_hexadecimal()) { invalid_char = true; }
  322.                 it.advance();
  323.                 ++ len;
  324.               }
  325.               unsigned long long val = 0;
  326.  
  327.               if(len == 0) { src.error(start, it.it, "Expected hexadecimal numbers"); }
  328.               if(invalid_char) { src.error(start, it.it, "Invalid character in hexadecimal literal"); }
  329.               if(!hex_str_to_u64(start + 2, len, val)) {
  330.                 src.error(start, it.it, "Invalid unicode escape sequence");
  331.               }
  332.               char c_cache[5] {};
  333.  
  334.               to_utf8_str(val, c_cache);
  335.               str.add(c_cache);
  336.             }
  337.             break;
  338.             default:
  339.               it.advance();
  340.               src.error(start, it.it, "Unknown escape sequence");
  341.             break;
  342.           }
  343.           continue;
  344.         }
  345.         str.add(it.it, it.char_size());
  346.         it.advance();
  347.       }
  348.       if(str.len == 0) { src.error(it.mark_it, it.it, "Expected character"); }
  349.       if(char_size(str.data) < str.len) {
  350.         src.error(it.mark_it, it.it, "Too many characters in character literal");
  351.       }
  352.       if(!closed) { src.error(it.mark_it, it.it, "Expected closing `'`"); }
  353.       tokens.add(Token::create(to_utf32_char(str.data), it.mark_it, it.it));
  354.     }
  355.   }
  356.   return tokens;
  357. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement