Skip to content

Instantly share code, notes, and snippets.

@GeertVL-zz
Created August 3, 2012 17:32
Show Gist options
  • Save GeertVL-zz/3249829 to your computer and use it in GitHub Desktop.
Save GeertVL-zz/3249829 to your computer and use it in GitHub Desktop.
Little Compiler 2
#include "llvm/DerivedTypes.h"
#include "llvm/IRBuilder.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/raw_os_ostream.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <tuple>
#include <string>
using namespace llvm;
// Token
enum Token {
tok_eof = -1,
tok_number = -2,
tok_function = -3,
tok_openparen = -4,
tok_closeparen = -5
};
// AST
class ExprAST {
public:
virtual ~ExprAST() {}
virtual llvm::Value *Codegen() = 0;
};
class NumberExprAST : public ExprAST {
double Val;
public:
NumberExprAST(double val) : Val(val) {}
virtual llvm::Value *Codegen();
};
class FunctionExprAST {
std::string Name;
std::vector<ExprAST*> Args;
ExprAST *Body;
public:
FunctionExprAST(const std::string name, std::vector<ExprAST*> args, ExprAST *body)
: Name(name), Args(args), Body(body) {}
Function *Codegen();
};
// Scanner
static char lastchar = ' ';
std::vector<std::tuple<int, std::string>> tokens;
std::tuple<int, std::string> gettok(std::ifstream* file)
{
while (isspace(lastchar))
file->get(lastchar);
if (lastchar == '(') {
file->get(lastchar);
return std::tuple<int, std::string>(tok_openparen, "");
}
if (lastchar == ')') {
file->get(lastchar);
return std::tuple<int, std::string>(tok_closeparen, "");
}
if (isalpha(lastchar)) {
std::string identifierstr;
do {
identifierstr.push_back(lastchar);
file->get(lastchar);
} while (isalpha(lastchar));
return std::tuple<int, std::string>(tok_function, identifierstr);
}
if (isdigit(lastchar)) {
std::string numstr;
do {
numstr.push_back(lastchar);
file->get(lastchar);
} while (isdigit(lastchar));
return std::tuple<int, std::string>(tok_number, numstr);
}
return std::tuple<int, std::string>();
}
// Parser
std::vector<ExprAST*> getNumbers(std::vector<std::tuple<int, std::string>>::iterator pos)
{
std::vector<ExprAST*> numbers;
pos++;
while (std::get<0>(*pos) == tok_number) {
auto value = atof(std::get<1>(*pos).c_str());
NumberExprAST number(value);
numbers.push_back(&number);
pos++;
};
return numbers;
}
ExprAST* getBody(std::vector<ExprAST*> arguments)
{
return 0;
}
// Codegeneration
static llvm::Module *TheModule;
static IRBuilder<> Builder(getGlobalContext());
llvm::Value *NumberExprAST::Codegen()
{
return llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(Val));
}
Function *FunctionExprAST::Codegen()
{
std::vector<Type*> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", F);
Builder.SetInsertPoint(BB);
Value *RetVal = Builder.CreateFAdd(Args[0]->Codegen(), Args[1]->Codegen(), "addtmp");
Builder.CreateRet(RetVal);
return F;
}
// Main environment
int main()
{
std::ifstream file("sample1.lc");
if (!file.is_open()) {
std::cout << "Could not open the file" << std::endl;
} else {
// Scanning
do {
auto token = gettok(&file);
std::cout << std::get<0>(token) << " : " << std::get<1>(token) << std::endl;
tokens.push_back(token);
} while (!file.eof());
// Parsing
std::vector<FunctionExprAST> functions;
auto pos = tokens.begin();
while (pos != tokens.end()) {
if (std::get<0>(*pos) == tok_openparen) {
auto functionToken = ++pos;
auto args = getNumbers(pos);
auto body = getBody(args);
FunctionExprAST function(std::get<1>(*functionToken), args, body);
functions.push_back(function);
}
pos++;
};
// Codegen
std::cout << "Codegeneration dump: " << std::endl;
for (auto iter = functions.begin(); iter != functions.end(); ++iter) {
auto fun = iter->Codegen();
fun->dump();
}
}
std::cout << "Finished" << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment