Advertisement
Guest User

Untitled

a guest
Dec 5th, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.24 KB | None | 0 0
  1. #ifndef MYLISP_HPP
  2. #define MYLISP_HPP
  3.  
  4. struct VM;
  5.  
  6. struct Atom;
  7. struct Buffer;
  8. struct Cons;
  9.  
  10. struct Buffer {
  11.     uint32_t size;
  12.     uint8_t* data;
  13. } bval;
  14.  
  15. struct Cons {
  16.     Atom* car;
  17.     Atom* cdr;
  18. } cval;
  19.  
  20. struct Atom {
  21.     enum Tag {
  22.         NIL, INT, REAL, STRING, SYMBOL, NATIVE, LAMBDA
  23.     } tag;
  24.    
  25.     union {
  26.         int64_t ival;
  27.         double fval;
  28.         Atom*(*native)(VM*, Cons*);
  29.         Buffer buffer;
  30.         Cons cons;
  31.     };
  32.    
  33.    
  34. };
  35.  
  36. struct VM {
  37.     enum Builtin {
  38.         NIL, CAR, CDR, APPLY, QUOTE, LAMBDA, DEF, DEFMACRO,
  39.         ADD, SUB, MUL, DIV, MOD, INV,
  40.         GT, LT, GTE, LTE, EQ, NE, NOT, T, F,
  41.         GET, SET,
  42.     };
  43.    
  44.     Atom* eval_tok(Token* tok);
  45.    
  46.     Atom* parse_list(Tokenizer* tokenizer);
  47.     Atom* parse(const std::string& code);
  48. };
  49.  
  50. #endif
  51.  
  52. //.cpp
  53. #include "mylisp.hpp"
  54.  
  55. struct Token {
  56.     enum Type {
  57.         LPAREN = '(', RPAREN = ')',
  58.         QUOTE = '\'', QUASIQUOTE = '`', UNQUOTE = ',',
  59.         INT, REAL, STRING = '"', SYMBOL,
  60.         COMMENT = ';', SPACE = ' ', EOF
  61.     } type;
  62.    
  63.     int line, col, pos;
  64.     std::string::iterator begin, end;
  65. };
  66.  
  67. void process_newline(std::string::iterator& it, int& line, int& col) {
  68.     switch(*(it++)) {
  69.         case '\r':
  70.             if(it != end && *it == '\n') {
  71.                 ++it;
  72.             }
  73.             break;
  74.        
  75.         case '\n':
  76.         case '\f':
  77.         case '\v':
  78.             break;
  79.        
  80.         default:
  81.             ++col;
  82.             return;
  83.     }
  84.    
  85.     ++line;
  86.     col = 0;
  87. }
  88.  
  89. bool isident(char c) {
  90.     if(c <= ' ') {
  91.         return false;
  92.     }
  93.    
  94.     switch(c) {
  95.         case '(':
  96.         case ')':
  97.         case '\'':
  98.         case '`':
  99.         case ',':
  100.         case '{':
  101.         case ';':
  102.             return false;
  103.     }
  104.    
  105.     return true;
  106. }
  107.  
  108. struct Tokenizer {
  109.     int line, col, pos;
  110.     std::string::iterator it, end;
  111.    
  112.     Tokenizer(std::string& code)
  113.         :line(1), col(0), pos(0), it(code.begin(), end(code.end()) {}
  114.    
  115.     Token next() {
  116.         std::string::iterator tokbegin = it;
  117.        
  118.         if(it == end) {
  119.             return Token{EOF, line, col, pos, tokbegin, it};
  120.         }
  121.        
  122.         switch(*(it++)) {
  123.             case '(':
  124.                 tt = Token::LPAREN;
  125.                 break;
  126.             case ')':
  127.                 tt = Token::RPAREN;
  128.                 break;
  129.             case '\'':
  130.                 tt = Token::QUOTE;
  131.                 break;
  132.             case '`':
  133.                 tt = Token::QUASIQUOTE;
  134.                 break;
  135.             case ',':
  136.                 tt = Token::UNQUOTE;
  137.                 break;
  138.            
  139.             case '{':
  140.                 while(it != end && *it == '}') {
  141.                     ++col;
  142.                     ++pos;
  143.                    
  144.                     process_newline(*&it, *&line, *&col);
  145.                 }
  146.                
  147.                 return Token{line, col, pos, tokbegin, it};
  148.            
  149.             case ';':
  150.                 while(it != end) {
  151.                     ++col;
  152.                     ++pos;
  153.                     process_newline(*&it, *&line, *&col);
  154.                     if(col == 0) {
  155.                         break;
  156.                     }
  157.                 }
  158.                
  159.                 return Token{line, col, pos, tokbegin, it};
  160.            
  161.             default:
  162.                 if(*it <= ' ') {
  163.                     do {
  164.                         process_newline(*&it, *&line, *&col);
  165.                     } while(*it <= ' ');
  166.                    
  167.                     return Token{line, col, pos, tokbegin, it};
  168.                 }
  169.                 else {
  170.                     tokbegin = it;
  171.                     do {
  172.                         ++it;
  173.                         ++col;
  174.                         ++pos;
  175.                     } while(isident(*it));
  176.                    
  177.                     return Token{line, col, pos, tokbegin, it};
  178.                 }
  179.                 break;
  180.         }
  181.     }
  182. };
  183.  
  184. Atom* VM::eval_tok(Token* tok) {
  185.     switch(tok->type) {
  186.        
  187.     }
  188. }
  189.  
  190. Atom* VM::read_list(Tokenizer* tokenizer, bool quasi) {
  191.     Atom* root = nullptr;
  192.     Atom** cur = &root;
  193.    
  194.     for(;;) {
  195.         Token tok = tokenizer.next();
  196.        
  197.         switch(tok.type) {
  198.             case Token::LPAREN:
  199.                 *cur = mkcons(read_list(tokenizer), builtin(NIL));
  200.                 break;
  201.            
  202.             case Token::RPAREN:
  203.                 return root;
  204.            
  205.             case Token::QUOTE:
  206.                 *cur = mkcons(builtin(QUOTE), read_atom(tokenizer));
  207.                 break;
  208.            
  209.             case Token::QUASIQUOTE:
  210.                 *cur = mkcons(builtin(QUOTE), read_atom(tokenizer, true));
  211.                 break;
  212.            
  213.             case Token::UNQUOTE:
  214.                 *cur = read_atom(tokenizer, quasi)->call(builtin(NIL));
  215.                 break;
  216.            
  217.             default:
  218.                 *cur = eval_tok(&tok);
  219.                 break;
  220.         }
  221.        
  222.         cur = &cur->cdr;
  223.     }
  224. }
  225.  
  226. Atom* VM::read_atom(Tokenizer* tokenizer) {
  227.     Token tok = tokenizer.next();
  228.    
  229.     switch(tok.type) {
  230.         case Token::LPAREN:
  231.             *cur = read_list(tokenizer);
  232.             break;
  233.        
  234.         case Token::QUOTE:
  235.             return quote(read_atom(tokenizer));
  236.     }
  237. }
  238.  
  239. Atom* VM::parse(const std::string& code) {
  240.     Tokenizer tokenizer{code};
  241.     Atom* root;
  242.     std::vector<Atom**> path;
  243.    
  244.     path.push_back(&root);
  245.    
  246.     while(path.size()) {
  247.         Token tok = tokenizer.next();
  248.        
  249.         switch(tok.type) {
  250.             case Token::LPAREN:
  251.                 path.push_back(mkatom());
  252.                 break;
  253.            
  254.             case Token::EOF:
  255.                 return nullptr;
  256.         }
  257.     }
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement