diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-14 02:05:13 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-14 02:05:13 +0800 |
| commit | d80958f987790f533f5048c2e0e8a1cd5fd9f5a1 (patch) | |
| tree | 48f1fcc577eb9b92b2766a0d354f59f12cf8680f | |
| parent | c7d52437db42232d98e585a52ed2fdf75eb7f1af (diff) | |
use template to make literal nodes
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | Lexer.hh | 59 | ||||
| -rw-r--r-- | Lexer.l | 77 | ||||
| -rw-r--r-- | Parser.y | 20 | ||||
| -rw-r--r-- | Version.cc | 13 | ||||
| -rw-r--r-- | node/BaseNode.cc | 2 | ||||
| -rw-r--r-- | node/LiteralNode.cc | 29 | ||||
| -rw-r--r-- | node/LiteralNode.hh | 20 | ||||
| -rw-r--r-- | node/Node.hh | 1 |
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}) @@ -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( @@ -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} { @@ -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 @@ -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" |
