summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-14 02:05:13 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-14 02:05:13 +0800
commitd80958f987790f533f5048c2e0e8a1cd5fd9f5a1 (patch)
tree48f1fcc577eb9b92b2766a0d354f59f12cf8680f
parentc7d52437db42232d98e585a52ed2fdf75eb7f1af (diff)
use template to make literal nodes
-rw-r--r--CMakeLists.txt2
-rw-r--r--Lexer.hh59
-rw-r--r--Lexer.l77
-rw-r--r--Parser.y20
-rw-r--r--Version.cc13
-rw-r--r--node/BaseNode.cc2
-rw-r--r--node/LiteralNode.cc29
-rw-r--r--node/LiteralNode.hh20
-rw-r--r--node/Node.hh1
9 files changed, 135 insertions, 88 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a7ab1cf..388e050 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,5 +36,5 @@ target_include_directories(pcc PRIVATE
${CMAKE_SOURCE_DIR}/node
${CMAKE_CURRENT_BINARY_DIR})
-llvm_map_components_to_libnames(llvm_libs support core irreader all)
+llvm_map_components_to_libnames(llvm_libs support core)
target_link_libraries(pcc ${llvm_libs})
diff --git a/Lexer.hh b/Lexer.hh
index 1558d14..35b27cc 100644
--- a/Lexer.hh
+++ b/Lexer.hh
@@ -1,6 +1,8 @@
#ifndef PCC_LEXER_H
#define PCC_LEXER_H
+#include <map>
+
#include "Node.hh"
#include "Parser.hh"
@@ -10,6 +12,63 @@ YY_DECL;
namespace pcc {
namespace Lexer {
+char* GetUnescapedChar(char* s, char* end, char* out) {
+ static std::map<char, char> escape_map = {
+ {'\'', '\''}, {'?', '\?'}, {'\\', '\\'}, {'a', '\a'}, {'b', '\b'},
+ {'f', '\f'}, {'n', '\n'}, {'r', '\r'}, {'t', '\t'}, {'v', '\v'}};
+ if (s[0] != '\\') {
+ *out = s[0];
+ return s + 1;
+ } else if (s[1] == 'x') {
+ char c[3], *cend;
+ c[0] = s[2];
+ if (end - s > 3) {
+ c[1] = s[3];
+ c[2] = '\0';
+ } else {
+ c[1] = '\0';
+ }
+ *out = (char) std::strtol(c, &cend, 16);
+ return s + 2 + (cend - c);
+ } else if (s[1] >= '0' && s[1] <= '7') {
+ char c[4], *cend;
+ c[0] = s[1];
+ if (end - s > 4) {
+ c[1] = s[2];
+ c[2] = s[3];
+ c[3] = '\0';
+ } else if (end - s > 3) {
+ c[1] = s[2];
+ c[2] = '\0';
+ } else {
+ c[1] = '\0';
+ }
+ *out = (char) std::strtol(c, &cend, 8);
+ return s + 1 + (cend - c);
+ } else {
+ *out = escape_map[s[1]];
+ return s + 2;
+ }
+}
+
+Parser::symbol_type make_BOOLEAN_LITERAL(bool b, pcc::Driver& driver,
+ const Parser::location_type& loc) {
+ return Parser::make_BOOLEAN_LITERAL(
+ std::make_shared<BooleanLiteralNode>(&driver, b), loc);
+}
+
+Parser::symbol_type make_INTEGER_LITERAL(int v, pcc::Driver& driver,
+ const Parser::location_type& loc) {
+ return Parser::make_INTEGER_LITERAL(
+ std::make_shared<IntegerLiteralNode>(&driver, v), loc);
+}
+
+Parser::symbol_type make_REAL_LITERAL(float v, pcc::Driver& driver,
+ const Parser::location_type& loc) {
+ return Parser::make_REAL_LITERAL(
+ std::make_shared<RealLiteralNode>(&driver, v), loc);
+}
+
Parser::symbol_type make_STRING_LITERAL(char* s, pcc::Driver& driver,
const Parser::location_type& loc) {
return Parser::make_STRING_LITERAL(
diff --git a/Lexer.l b/Lexer.l
index cd1b634..6f43790 100644
--- a/Lexer.l
+++ b/Lexer.l
@@ -37,12 +37,12 @@ real_noexp [0-9]*\.[0-9]*
real [+-]?({real_exp}|{real_noexp})
-char [0-9a-zA-Z_{}[\]#()<>%:;.?*+\-/^&|~!=,\\" \t\n\v\f]
+trival_char [0-9a-zA-Z_{}[\]#()<>%:;.?*+\-/^&|~!=,\\" \t\n\v\f]
escaped_char \\[\'?\\abfnrtv]
hex_char \\x[0-9a-fA-F]{1,2}
oct_char \\[0-7]{1,3}
-string '({char}|{escaped_char}|{hex_char}|{oct_char}|\\')*'
+string '({trival_char}|{escaped_char}|{hex_char}|{oct_char}|\\')*'
identifier [a-z][0-9a-z]*
@@ -104,77 +104,30 @@ white [\t\f\r ]
"char" {return Parser::make_CHAR(loc);}
"real" {return Parser::make_REAL(loc);}
"string" {return Parser::make_STRING(loc);}
-"true" {return Parser::make_TRUE(loc);}
-"false" {return Parser::make_FALSE(loc);}
+
+"true" {return pcc::Lexer::make_BOOLEAN_LITERAL(true, driver, loc);}
+"false" {return pcc::Lexer::make_BOOLEAN_LITERAL(false, driver, loc);}
{integer} {
int number = std::strtol(yytext, NULL, 0);
- return pcc::Parser::make_INTEGER_LITERAL(number, loc);
+ return pcc::Lexer::make_INTEGER_LITERAL(number, driver, loc);
}
{real} {
float number = std::strtof(yytext, NULL);
- return pcc::Parser::make_REAL_LITERAL(number, loc);
+ return pcc::Lexer::make_REAL_LITERAL(number, driver, loc);
}
{string} {
- static std::map<char,char> escape_map={
- {'\'','\''},
- {'?','\?'},
- {'\\','\\'},
- {'a','\a'},
- {'b','\b'},
- {'f','\f'},
- {'n','\n'},
- {'r','\r'},
- {'t','\t'},
- {'v','\v'}
- };
- char *str = new char[yyleng];
- char *p = str;
- int i = 1;
- while(i<yyleng-1){
- if(yytext[i]!='\\'){
- *p++=yytext[i];
- i++;
- }
- else if(yytext[i+1]=='x'){
- char c[3], *cend;
- c[0]=yytext[i+2];
- if(i+3<yyleng-1){
- c[1]=yytext[i+3];
- c[2]='\0';
- } else {
- c[1]='\0';
- }
- *p++=(char)std::strtol(c,&cend,16);
- i+=(int)(cend-c)+2;
- }
- else if(yytext[i+1]>='0' && yytext[i+1]<='7'){
- char c[4], *cend;
- c[0]=yytext[i+1];
- if(i+3<yyleng-1){
- c[1]=yytext[i+2];
- c[2]=yytext[i+3];
- c[3]='\0';
- }
- else if(i+3<yyleng){
- c[1]=yytext[i+2];
- c[2]='\0';
- }
- else {
- c[1]='\0';
- }
- *p++=(char)std::strtol(c,&cend,8);
- i+=(int)(cend-c)+1;
- }
- else {
- *p++=escape_map[yytext[i+1]];
- i+=2;
- }
+ char *s, *end, *p;
+ s = p = yytext + 1;
+ end = s + yyleng - 2;
+ while (s < end) {
+ s = pcc::Lexer::GetUnescapedChar(s, end, p);
+ p++;
}
- *p++='\0';
- return pcc::Lexer::make_STRING_LITERAL(str, driver, loc);
+ *p = '\0';
+ return pcc::Lexer::make_STRING_LITERAL(yytext + 1, driver, loc);
}
{identifier} {
diff --git a/Parser.y b/Parser.y
index 522bd78..993867f 100644
--- a/Parser.y
+++ b/Parser.y
@@ -6,10 +6,10 @@
#include <memory>
#include "Location.hh"
+#include "Node.hh"
namespace pcc {
class Driver;
- class StringLiteralNode;
}
}
@@ -19,7 +19,6 @@ namespace pcc {
%code {
#include "Driver.hh"
-#include "Node.hh"
#define YY_DECL pcc::Parser::symbol_type yylex(pcc::Driver& driver)
YY_DECL;
@@ -36,15 +35,15 @@ YY_DECL;
%token COLON SEMICOLON COMMA DOT ASSIGN LBRACKET RBRACKET LPARENTHESIS RPARENTHESIS
%token PROGRAM IDENTIFIER CONST VAR BEGINS ENDS FUNCTION FILE_END
%token IF THEN ELSE WHILE DO
-%token INTEGER BOOLEAN CHAR REAL STRING
+%token BOOLEAN CHAR INTEGER REAL STRING
%token ADD SUB MUL REAL_DIV DIV MOD EXP LT LE GT GE EQ NE
-%token AND NOT OR XOR TRUE FALSE
-%token INTEGER_LITERAL REAL_LITERAL STRING_LITERAL
-
-%type <int> INTEGER_LITERAL
-%type <float> REAL_LITERAL
-%type <char*> IDENTIFIER
+%token AND NOT OR XOR
+%token INTEGER_LITERAL REAL_LITERAL STRING_LITERAL BOOLEAN_LITERAL CHAR_LITERAL
+%type <std::string> IDENTIFIER
+%type <std::shared_ptr<pcc::BooleanLiteralNode>> BOOLEAN_LITERAL
+%type <std::shared_ptr<pcc::IntegerLiteralNode>> INTEGER_LITERAL
+%type <std::shared_ptr<pcc::RealLiteralNode>> REAL_LITERAL
%type <std::shared_ptr<pcc::StringLiteralNode>> STRING_LITERAL
%%
@@ -229,8 +228,7 @@ arguments
;
literal
- : TRUE
- | FALSE
+ : BOOLEAN_LITERAL
| INTEGER_LITERAL
| REAL_LITERAL
| STRING_LITERAL
diff --git a/Version.cc b/Version.cc
index 9b8be86..2a58401 100644
--- a/Version.cc
+++ b/Version.cc
@@ -1,3 +1,5 @@
+#include <llvm/Config/llvm-config.h>
+
#include "Version.hh"
namespace pcc {
@@ -5,15 +7,18 @@ namespace pcc {
PCC_NORETURN void ShowVersion() {
std::cerr
<< PCC_NAME " version " PCC_VERSION_STRING "\n"
- << "Copyright (C) 2020 Hanjie Wu <nagi@zju.edu.cn>\n"
- "Platform: " PCC_OSNAME "\n"
- "Built on " __DATE__ " " __TIME__ "\n\n"
+ << "Copyright (C) 2020 Hanjie Wu <nagi@zju.edu.cn>\n\n"
"This program is free software; you can redistribute it and/or "
"modify\n"
"it under the terms of the GNU General Public License as published "
"by\n"
"the Free Software Foundation; either version 2 of the License, or\n"
- "(at your option) any later version."
+ "(at your option) any later version.\n\n"
+ "Configurations:\n"
+ " LLVM Version: " LLVM_VERSION_STRING "\n"
+ " Host Platform: " PCC_OSNAME "\n"
+ " Defaule Target: " LLVM_DEFAULT_TARGET_TRIPLE "\n"
+ " Built on: " __DATE__ " " __TIME__
<< std::endl;
std::exit(0);
}
diff --git a/node/BaseNode.cc b/node/BaseNode.cc
index 98ebb82..de38f55 100644
--- a/node/BaseNode.cc
+++ b/node/BaseNode.cc
@@ -1,4 +1,4 @@
-#include "BaseNode.hh"
+#include "Node.hh"
namespace pcc {
BaseNode::BaseNode(Driver* driver)
diff --git a/node/LiteralNode.cc b/node/LiteralNode.cc
index dd84ff9..1e9c4b7 100644
--- a/node/LiteralNode.cc
+++ b/node/LiteralNode.cc
@@ -1,11 +1,32 @@
+#include <llvm/ADT/APFloat.h>
+#include <llvm/ADT/APInt.h>
+
+#include "Driver.hh"
#include "Node.hh"
namespace pcc {
-StringLiteralNode::StringLiteralNode(Driver* driver, char* value)
- : BaseNode(driver)
- , value_(value) {}
+template <> Value BooleanLiteralNode::CodeGen() {
+ llvm::LLVMContext& context = driver_->GetModule()->getContext();
+ if (value_ == true) {
+ return llvm::ConstantInt::getTrue(context);
+ } else {
+ return llvm::ConstantInt::getFalse(context);
+ }
+}
+
+template <> Value IntegerLiteralNode::CodeGen() {
+ llvm::LLVMContext& context = driver_->GetModule()->getContext();
+ llvm::APInt value(32, (uint64_t) value_, true);
+ return llvm::ConstantInt::get(context, value);
+}
+
+template <> Value RealLiteralNode::CodeGen() {
+ llvm::LLVMContext& context = driver_->GetModule()->getContext();
+ llvm::APFloat value(value_);
+ return llvm::ConstantFP::get(context, value);
+}
-Value StringLiteralNode::CodeGen() {
+template <> Value StringLiteralNode::CodeGen() {
llvm::Module* module = driver_->GetModule();
llvm::LLVMContext& context = module->getContext();
llvm::Constant* str = llvm::ConstantDataArray::getString(context, value_);
diff --git a/node/LiteralNode.hh b/node/LiteralNode.hh
index 4f9a61a..1d5c1b8 100644
--- a/node/LiteralNode.hh
+++ b/node/LiteralNode.hh
@@ -6,14 +6,26 @@
#include "BaseNode.hh"
namespace pcc {
-class StringLiteralNode : public BaseNode {
+template <typename Type, typename Construct = Type>
+class LiteralNode : public BaseNode {
public:
- StringLiteralNode(Driver* driver, char* value);
- Value CodeGen() override;
+ LiteralNode(Driver* driver, Construct value);
+ Value CodeGen() override; // type-specific CodeGen() is in the .cc file.
private:
- std::string value_;
+ Type value_;
};
+
+template <typename Type, typename Construct>
+LiteralNode<Type, Construct>::LiteralNode(Driver* driver,
+ Construct value)
+ : BaseNode(driver)
+ , value_(value) {}
+
+using BooleanLiteralNode = LiteralNode<bool>;
+using IntegerLiteralNode = LiteralNode<int>;
+using RealLiteralNode = LiteralNode<float>;
+using StringLiteralNode = LiteralNode<std::string, char*>;
} // namespace pcc
#endif
diff --git a/node/Node.hh b/node/Node.hh
index 3a02689..daf99eb 100644
--- a/node/Node.hh
+++ b/node/Node.hh
@@ -1,7 +1,6 @@
#ifndef PCC_NODE_H
#define PCC_NODE_H
-#include "Driver.hh"
#include "BaseNode.hh"
#include "LiteralNode.hh"