This commit is contained in:
Zengtudor 2025-07-18 20:50:40 +08:00
parent 126f995ec3
commit 679fe7a960
6 changed files with 157 additions and 46 deletions

View File

@ -1,5 +1,106 @@
#pragma once #pragma once
#include "Lexer.hpp"
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <format>
#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>
#include <vector>
namespace ztl{ namespace ztl{
inline void interpreter(const std::vector<Token> &tokens){
using ObjectType = std::variant<int64_t>;
std::map<std::string, ObjectType> objects;
const auto getValueOrLiteral = [&tokens,&objects](size_t i){
ObjectType a;
if(tokens[i].type==TokenType::Literal){
a=atoi(tokens[i].str.data());
}else if(tokens[i].type==TokenType::Identifier){
if(auto it = objects.find(tokens[i].str);it!=objects.end()){
a=(*it).second;
}else{
throw std::runtime_error(std::format("error in getting value named '{}'",tokens[i].str));
}
}else{
throw std::runtime_error("error in getting expression result");
}
return a;
};
const auto getExprAns = [&getValueOrLiteral,&objects,&tokens](size_t i)->std::pair<ObjectType, size_t>{
ObjectType a=getValueOrLiteral(i);
ObjectType b;
if(i+1<tokens.size()&&tokens[i+1].type==TokenType::Operator){
if(tokens[i+1].str=="+"){
if(i+2<tokens.size()){
b=getValueOrLiteral(i+2);
}else{
throw std::runtime_error(std::format("error getting a op b, b is not found. a named '{}'",tokens[i].str));
}
}else{
throw std::runtime_error(std::format("unknown operator '{}'",tokens[i+1].str));
}
}else{
return {a,1};
}
ObjectType res;
if(std::holds_alternative<int64_t>(a) && tokens[i+1].str=="+" && std::holds_alternative<int64_t>(b)){
res = std::get<int64_t>(a) + std::get<int64_t>(b);
}else{
throw std::runtime_error(std::format("unknown operator '{}' or value type '{}' ,'{}'",tokens[i+1].str,tokens[i].str,tokens[i+2].str));
}
return {res,3};
};
for(size_t i=0;i<tokens.size();i++){
if(tokens[i].type==TokenType::Keyword){
if(tokens[i].str=="int"){
if( i+2<tokens.size()
&&tokens[i+1].type==TokenType::Identifier
&& tokens[i+2].str=="="
){
std::string valueName = tokens[i+1].str;
i+=2;
auto res = getExprAns(i+1);
objects[valueName] = res.first;
i+=res.second;
}else{
throw std::runtime_error(std::format("error when creatting int value '{}'",tokens[i].str));
}
}else if(tokens[i].str=="print"){
if(i+1<tokens.size()&&tokens[i+1].str=="("){
i++;
}else{
throw std::runtime_error("cannot get '(' when printing value");
}
if(!(i+1<tokens.size()))throw std::runtime_error("cannot get value be printed when printing value");
auto [res,addi] = getExprAns(i+1);
i+=addi;
if(i+1<tokens.size()&&tokens[i+1].str==")"){
i++;
}else{
throw std::runtime_error("cannot get ')' when printing value");
}
std::visit([](auto &res){
std::cout<<res<<'\n';
},res);
}
else{
throw std::runtime_error(std::format("interpreter error Cannot find Keyword '{}'",tokens[i].str));
}
if(i+1<tokens.size()&&tokens[i+1].str==";"){
i++;
}else{
throw std::runtime_error(std::format("cannot get ';' after '{}'",tokens[i].str));
}
}else{
throw std::runtime_error(std::format("interpreter error at '{}'",tokens[i].str));
}
}
}
} }

View File

@ -14,7 +14,7 @@
#include <vector> #include <vector>
namespace ztl{ namespace ztl{
namespace readFileToStrType{ namespace readFileToStrType{
struct CannotOpenFile{}; struct CannotOpenFile{};
using ReturnType = std::variant< using ReturnType = std::variant<
@ -31,29 +31,29 @@ namespace ztl{
return s; return s;
} }
#define FOR_EACH FOR_EACH_V(Keyword)\ #define ZTL_FOR_EACH ZTL_FOR_EACH_V(Keyword)\
FOR_EACH_V(Identifier)\ ZTL_FOR_EACH_V(Identifier)\
FOR_EACH_V(Literal)\ ZTL_FOR_EACH_V(Literal)\
FOR_EACH_V(Operator)\ ZTL_FOR_EACH_V(Operator)\
FOR_EACH_V(Separator)\ ZTL_FOR_EACH_V(Separator)\
FOR_EACH_V(Whitespace)\ ZTL_FOR_EACH_V(Whitespace)\
#define FOR_EACH_V(v)v, #define ZTL_FOR_EACH_V(v)v,
enum class TokenType{ enum class TokenType{
FOR_EACH ZTL_FOR_EACH
}; };
#undef FOR_EACH_V #undef ZTL_FOR_EACH_V
inline std::string getTokenTypeName(TokenType t){ inline std::string getTokenTypeName(TokenType t){
switch (t) { switch (t) {
#define FOR_EACH_V(v)case TokenType::v:{return #v;} #define ZTL_FOR_EACH_V(v)case TokenType::v:{return #v;}
FOR_EACH ZTL_FOR_EACH
default: default:
throw std::runtime_error("unknown TokenType"); throw std::runtime_error("unknown TokenType");
} }
throw std::runtime_error("unreachable"); throw std::runtime_error("unreachable");
} }
#undef FOR_EACH_V #undef ZTL_FOR_EACH_V
#undef FOR_EACH #undef ZTL_FOR_EACH
struct Token{ struct Token{
TokenType type; TokenType type;
@ -97,14 +97,14 @@ namespace ztl{
} }
else if(isspace(s[i])){ else if(isspace(s[i])){
continue; continue;
}else if(s[i]=='='){ }else if(s[i]=='='||s[i]=='+'){
tokens.emplace_back(TokenType::Operator,"="); tokens.emplace_back(TokenType::Operator,std::string()+s[i]);
}else if(isdigit(s[i])){ }else if(isdigit(s[i])){
size_t begin = i; size_t begin = i;
while(isdigit(s[i])){ while(isdigit(s[i+1])){
i++; i++;
} }
tokens.emplace_back(TokenType::Literal,s.substr(begin,i-begin)); tokens.emplace_back(TokenType::Literal,s.substr(begin,i-begin+1));
} }
else if(s[i]==';'||s[i]=='('||s[i]==')'){ else if(s[i]==';'||s[i]=='('||s[i]==')'){
tokens.emplace_back(TokenType::Separator,std::string()+s[i]); tokens.emplace_back(TokenType::Separator,std::string()+s[i]);

View File

@ -1,14 +1,11 @@
#pragma once #pragma once
#include "Interpreter.hpp"
#include "Lexer.hpp"
#include <cstddef> #include <cstddef>
#include <iostream>
#include <ostream> #include <ostream>
#include <vector> #include <vector>
namespace ztl {
template<class ...Ts>
struct overloaded : Ts... {using Ts::operator()...;};
template<class ...Ts>
overloaded (Ts...) -> overloaded<Ts...>;
}
namespace std{ namespace std{
template<class T> template<class T>
@ -24,4 +21,25 @@ namespace std{
os<<" "<<v[v.size()-1]<<"]"; os<<" "<<v[v.size()-1]<<"]";
return os; return os;
} }
}
namespace ztl {
template<class ...Ts>
struct overloaded : Ts... {using Ts::operator()...;};
template<class ...Ts>
overloaded (Ts...) -> overloaded<Ts...>;
void inline runCodeFromPath(std::string_view v){
ztl::Lexer lexer = std::visit(ztl::overloaded{
[](std::string &&s){
return s;
},
[&v](const ztl::readFileToStrType::CannotOpenFile &){
throw std::runtime_error(std::format("Cannot open file :{}",v));
return std::string();
}
},ztl::readFileToStr(v));
std::cout<<"Lexer() return vector:\n"<<lexer.tokens<<'\n';
ztl::interpreter(lexer.tokens);
}
} }

View File

@ -1,26 +1,11 @@
#include "Lexer.hpp"
#include "Tools.hpp" #include "Tools.hpp"
#include <format>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string_view>
#include <variant>
int main(int argc,char *argv[]){ int main(int argc,char *argv[]){
if(argc<2){ if(argc<2){
throw std::runtime_error("Usage : ztl <filepath>"); throw std::runtime_error("Usage : ztl <filepath>");
} }
ztl::Lexer lexer = std::visit(ztl::overloaded{ ztl::runCodeFromPath(argv[1]);
[](std::string &&s){
return s;
},
[&argv](const ztl::readFileToStrType::CannotOpenFile &){
throw std::runtime_error(std::format("Cannot open file :{}",argv[1]));
return std::string();
}
},ztl::readFileToStr(argv[1]));
std::cout<<"Lexer() return vector:\n"<<lexer.tokens<<'\n';
} }

View File

@ -1,2 +1,5 @@
int a =1; int a =1 +100;
print(a); print(a);
int a = a+5;
print(a);
print(a+a);

View File

@ -1,3 +1,7 @@
int main(){ #include "Tools.hpp"
#include <string_view>
int main(int argc,char *argv[]){
ztl::runCodeFromPath("/root/dev/cpp/TudorLang/tests/main.ztl");
} }