#include #include #include #include #include "parser.h" using namespace std; ParseError::ParseError(const string &what_arg) :runtime_error(what_arg){} ParseError::ParseError(const char *what_arg) :runtime_error(what_arg){} static bool isinitwordchar(char c){ return isalpha(c)||c=='_'; } static bool iswordchar(char c){ return isalpha(c)||isdigit(c)||c=='_'; } static const vector tok_symbols={ "==", "!=", ">", "<", ">=", "<=", ":=", "=", "+", "-", "*", "/", "%", "(", ")", ",", "{", "}", "?{", "??{", "}&", }; static bool isSymbolPrefix(const string &s){ for(const string &sym : tok_symbols){ if(s.size()<=sym.size()&&sym.substr(0,s.size())==s)return true; } return false; } template static bool contains(const vector &v,const T &target){ for(const T &t : v){ if(t==target)return true; } return false; } class Token{ public: enum class Type{ word, number, string, symbol, }; Type type; string str; Site site; Token(Type type,const string &str,const Site &site) :type(type),str(str),site(site){} }; class Tokeniser{ const string &source; const string &filename; i64 idx,nextidx; i64 lnum,linex; Token::Type ttype; bool eof(i64 at){ return at>=(i64)source.size(); } string get_() const { if(eof())throw runtime_error("Tokeniser::get() on eof"); if(nextidx==-1)throw runtime_error("Tokeniser::get() before advance"); if(nextidx==-2)throw runtime_error("Tokeniser::get() after eof"); assert(nextidx>=0); return source.substr(idx,nextidx-idx); } public: Tokeniser(const string &source,const string &filename) :source(source),filename(filename), idx(0),nextidx(-1), lnum(1),linex(1){} bool eof() const { return idx>=(i64)source.size(); } Token get() const { return Token(ttype,get_(),Site(filename,lnum,linex)); } // Returns whether there are more tokens bool advance(){ if(eof())return false; while(idx