135 lines
5.2 KiB
C++
135 lines
5.2 KiB
C++
#pragma once
|
|
|
|
#include "Lexer.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <format>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
namespace ztl{
|
|
struct AST{
|
|
struct Literal{
|
|
using LiteralType = std::variant<int64_t>;
|
|
LiteralType value;
|
|
};
|
|
struct Identifier{
|
|
std::string name;
|
|
};
|
|
struct BinaryExpression{
|
|
enum OperatorType{
|
|
Add,
|
|
};
|
|
OperatorType Operator;
|
|
using LRType = std::variant<
|
|
Identifier,
|
|
std::unique_ptr<BinaryExpression>
|
|
>;
|
|
LRType left;
|
|
LRType right;
|
|
};
|
|
struct UnaryExpression{
|
|
enum struct Operator{
|
|
Not='!',
|
|
Minus='-'
|
|
}op;
|
|
std::variant<Identifier,Literal> right;
|
|
};
|
|
struct Expression{
|
|
std::variant<BinaryExpression,Identifier,UnaryExpression> son;
|
|
};
|
|
struct VariableDeclaration{
|
|
Identifier id;
|
|
BinaryExpression init;
|
|
};
|
|
struct BlockStatement{
|
|
using BodyType = std::vector<std::variant<VariableDeclaration>>;
|
|
BodyType body;
|
|
};
|
|
auto getExpr(std::vector<Token> &tokens,int64_t begin,int64_t end)->std::tuple<VariableDeclaration,int64_t>{
|
|
std::list<std::variant<Token,BinaryExpression,UnaryExpression,Literal,Identifier>> l(tokens.begin()+begin,tokens.begin()+end);
|
|
for (auto it = l.begin();it!=l.end();it++) { // 转化字面量和变量名
|
|
if(std::holds_alternative<Token>(*it)){
|
|
if(std::get<Token>(*it).type==ztl::TokenType::Identifier){
|
|
(*it)=Identifier{
|
|
.name = std::get<Token>(*it).str
|
|
};
|
|
}else if(std::get<Token>(*it).type==ztl::TokenType::Literal){
|
|
(*it)=Literal{
|
|
.value = atoi(std::get<Token>(*it).str.data())
|
|
};
|
|
}else if(std::get<Token>(*it).type==ztl::TokenType::Operator){
|
|
continue;
|
|
}else{
|
|
std::runtime_error("only Identifier Literal Operator can be put into a Expr");
|
|
}
|
|
}else{
|
|
std::runtime_error("unknown type when AST");
|
|
}
|
|
}
|
|
for(auto it = l.begin();it!=l.end();it++){ // 一元表达式
|
|
if(!(std::holds_alternative<Token>(*it)))continue;
|
|
auto nit = it;
|
|
nit++;
|
|
if(!(nit!=l.end()&&(std::holds_alternative<Literal>(*nit)||std::holds_alternative<Identifier>(*nit))))throw std::runtime_error(std::format("no char after char '{}' when AST or no value after it",std::get<Token>(*it).str));
|
|
std::variant<Identifier,Literal> right;
|
|
right = std::visit([](auto &i){
|
|
using T = std::decay_t<decltype(i)> ;
|
|
if constexpr(std::is_same_v<Literal, T>||std::is_same_v<Identifier, T>){
|
|
return std::variant<Identifier, Literal>(i);
|
|
}else{
|
|
throw std::runtime_error("cannot get type when AST");
|
|
}
|
|
std::unreachable();
|
|
return std::variant<Identifier, Literal>();
|
|
},
|
|
*nit);
|
|
l.erase(nit);
|
|
if(std::get<Token>(*it).str=="-"){
|
|
(*it) = UnaryExpression{
|
|
.op = UnaryExpression::Operator::Minus,
|
|
.right = right
|
|
};
|
|
continue;
|
|
}else if(std::get<Token>(*it).str=="!"){
|
|
(*it) = UnaryExpression{
|
|
.op = UnaryExpression::Operator::Not,
|
|
.right = right
|
|
};
|
|
continue;
|
|
}
|
|
else{
|
|
throw std::runtime_error(std::format("unknown UnaryExpression char '{}'",std::get<Token>(*it).str));
|
|
}
|
|
}
|
|
for(auto it = l.begin();it!=l.end();it++){ //二元表达式*
|
|
if(std::holds_alternative<UnaryExpression>(*it)||std::holds_alternative<Literal>(*it)||std::holds_alternative<Identifier>(*it)){
|
|
auto nit = it;
|
|
nit++;
|
|
if(nit!=l.end()&&std::holds_alternative<Token>(*nit)&&(std::get<Token>(*nit).str=="*"||std::get<Token>(*nit).str=="/"))
|
|
}else{
|
|
throw std::runtime_error("cannot get type when AST");
|
|
}
|
|
}
|
|
}
|
|
AST(std::vector<Token> tokens){
|
|
|
|
for(size_t i=0;i<tokens.size();i++){
|
|
if(tokens[i].str=="int"){
|
|
|
|
}else{
|
|
throw std::runtime_error(std::format("unknown token '{}' when AST",tokens[i].str));
|
|
}
|
|
}
|
|
}
|
|
};
|
|
} |