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

View File

@ -1,14 +1,11 @@
#pragma once
#include "Interpreter.hpp"
#include "Lexer.hpp"
#include <cstddef>
#include <iostream>
#include <ostream>
#include <vector>
namespace ztl {
template<class ...Ts>
struct overloaded : Ts... {using Ts::operator()...;};
template<class ...Ts>
overloaded (Ts...) -> overloaded<Ts...>;
}
namespace std{
template<class T>
@ -24,4 +21,25 @@ namespace std{
os<<" "<<v[v.size()-1]<<"]";
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 <format>
#include <iostream>
#include <stdexcept>
#include <string>
#include <variant>
#include <string_view>
int main(int argc,char *argv[]){
if(argc<2){
throw std::runtime_error("Usage : ztl <filepath>");
}
ztl::Lexer lexer = std::visit(ztl::overloaded{
[](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';
ztl::runCodeFromPath(argv[1]);
}

View File

@ -1,2 +1,5 @@
int a =1;
print(a);
int a =1 +100;
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");
}