Skip to content

Commit

Permalink
[PP] Obj-like macro define
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisHsu committed Jan 21, 2025
1 parent bdecd79 commit 30f8e94
Show file tree
Hide file tree
Showing 15 changed files with 353 additions and 278 deletions.
22 changes: 11 additions & 11 deletions src/exec/wasmvm-cc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,17 @@ int main(int argc, const char* argv[]){
if(args["pp"]){
for(std::filesystem::path source_path : source_files){
PreProcessor pp(source_path);
// if(args["output"]){
// std::ofstream output_file(std::get<std::string>(args["output"].value()));
// for(PreProcessor::PPToken tok = pp.get(); tok.has_value(); tok = pp.get()){
// output_file << tok.value();
// }
// output_file.close();
// }else{
// for(PreProcessor::PPToken tok = pp.get(); tok.has_value(); tok = pp.get()){
// std::cout << tok.value();
// }
// }
if(args["output"]){
std::ofstream output_file(std::get<std::string>(args["output"].value()));
for(std::optional<PreProcessor::Token> token = pp.get(); token.has_value(); token = pp.get()){
output_file << token->text;
}
output_file.close();
}else{
for(std::optional<PreProcessor::Token> token = pp.get(); token.has_value(); token = pp.get()){
std::cout << token->text;
}
}
}
return 0;
}
Expand Down
14 changes: 12 additions & 2 deletions src/include/PreProcessor.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#ifndef WVMCC_PreProcessor_DEF
#define WVMCC_PreProcessor_DEF

#include <istream>
#include <sstream>
#include <ostream>
#include <filesystem>
#include <stack>
#include <deque>
#include <string>
#include <optional>
#include <unordered_map>
#include <common.hpp>

namespace WasmVM {
Expand All @@ -22,13 +22,23 @@ struct PreProcessor {
SourcePos pos;
};

struct Macro {
std::string name;
std::optional<std::vector<std::string>> params;
std::vector<Token> replacement;
bool operator==(const Macro& op) const;
};

PreProcessor(std::filesystem::path filepath);
std::optional<Token> get();

protected:
struct Visitor;
std::stack<std::shared_ptr<Visitor>> visitors;
std::deque<Token> buffer;
std::unordered_map<std::string, Macro> macros;

friend struct Visitor;
};

} // namespace WasmVM
Expand Down
1 change: 0 additions & 1 deletion src/lib/PreProcessor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ include_directories(

add_library(pp
PreProcessor.cpp
ErrorListener.cpp
PPLexer.cpp
PPParser.cpp
Visitor.cpp
Expand Down
19 changes: 0 additions & 19 deletions src/lib/PreProcessor/ErrorListener.cpp

This file was deleted.

14 changes: 0 additions & 14 deletions src/lib/PreProcessor/ErrorListener.hpp

This file was deleted.

13 changes: 10 additions & 3 deletions src/lib/PreProcessor/PP.g4
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ options {

import PPToken;

group : text_line | EOF;
group : control_line | text_line;

text_line : pp_token* NewLine?;
control_line : define_obj
| Hash pp_token* line_end;

pp_token : HeaderName | Identifier | PPNumber | CharConst | StringLiteral | Punctuator | BlockComment | LineComment | WhiteSpace;
text_line : pp_token* line_end;

define_obj : Hash WhiteSpace* 'define' WhiteSpace+ Identifier WhiteSpace+ pp_token* line_end;

line_end : NewLine? EOF | NewLine;

pp_token : HeaderName | Identifier | PPNumber | CharConst | StringLiteral | Punctuator | BlockComment | LineComment | WhiteSpace;
4 changes: 3 additions & 1 deletion src/lib/PreProcessor/PPToken.g4
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ Escape : BSlash_ ([abfnrtv'"?\\] | BSlash_ | [0-7] [0-7]? [0-7]? | 'x' HexDigit
StringLiteral : ([LuU] | 'u8')? '"' (~["\\\n] | Escape)* '"';

/* Punctuator */
Punctuator : '%:%:' | '<<=' | '>>=' | '...' | '%:' | '++' | '<'[:%<]? | [:%>]?'>' | ([*/%+\-&^|><!=] | Bar_ | Caret_)?'=' | '&&' | '##' | Hash_ Hash_ | '-' [\->] | BraceL_ | BraceR_ | BracketL_ | BracketR_ | (Bar_ Bar_?) | Caret_ | Tlide_ | Hash_ | [().&*+\-!/%?:;,];
HashHash : '%:%:' | Hash_ Hash_;
Hash : '%:' | Hash_;
Punctuator : '<<=' | '>>=' | '...' | '++' | '<'[:%<]? | [:%>]?'>' | ([*/%+\-&^|><!=] | Bar_ | Caret_)?'=' | '&&' | '-' [\->] | BraceL_ | BraceR_ | BracketL_ | BracketR_ | (Bar_ Bar_?) | Caret_ | Tlide_ | [().&*+\-!/%?:;,];

/* White space */
WhiteSpace : [\t\f\r \u000B]+ ;
Expand Down
19 changes: 19 additions & 0 deletions src/lib/PreProcessor/PreProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,23 @@ std::optional<PreProcessor::Token> PreProcessor::get(){
Token token = buffer.front();
buffer.pop_front();
return token;
}

bool PreProcessor::Macro::operator==(const PreProcessor::Macro& op) const {
if((op.name != name) || (op.params.has_value() != params.has_value()) || (op.replacement.size() != replacement.size())){
return false;
}
for(auto op_it = op.replacement.begin(), it = replacement.begin(); op_it != op.replacement.end(); op_it = std::next(op_it), it = std::next(it)){
if((op_it->type != it->type) || (op_it->text != it->text)){
return false;
}
}
if(op.params.has_value()){
for(auto op_it = op.params->begin(), it = params->begin(); op_it != op.params->end(); op_it = std::next(op_it), it = std::next(it)){
if(*op_it != *it){
return false;
}
}
}
return true;
}
60 changes: 48 additions & 12 deletions src/lib/PreProcessor/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "Visitor.hpp"
#include <Error.hpp>
#include <exception.hpp>

using namespace WasmVM;

Expand All @@ -25,24 +26,17 @@ PreProcessor::Visitor::Visitor(std::filesystem::path path, PreProcessor& pp) : p
lexer = std::make_unique<PPLexer>(input.get());
tokens = std::make_unique<antlr4::CommonTokenStream>(lexer.get());
parser = std::make_unique<PPParser>(tokens.get());
parser->removeErrorListeners();
parser->addErrorListener(&parseErrorListener);
}

bool PreProcessor::Visitor::fetch(){
auto* group = parser->group();
visitGroup(group);
return !parser->isMatchedEOF();
return std::any_cast<bool>(visitGroup(parser->group()));
}

std::any PreProcessor::Visitor::visitGroup(PPParser::GroupContext *ctx){
return visitChildren(ctx);
}

std::any PreProcessor::Visitor::visitText_line(PPParser::Text_lineContext *ctx){
for(auto pp_token : ctx->pp_token()){
pp.buffer.emplace_back(std::any_cast<Token>(visitPp_token(pp_token)));
}
std::any PreProcessor::Visitor::visitLine_end(PPParser::Line_endContext* ctx){
antlr4::tree::TerminalNode* newline = ctx->NewLine();
if(newline){
pp.buffer.emplace_back(Token {
Expand All @@ -54,10 +48,26 @@ std::any PreProcessor::Visitor::visitText_line(PPParser::Text_lineContext *ctx){
.col = newline->getSymbol()->getCharPositionInLine() + 1
}
});
return ctx->pp_token().size() + 1;
}
if(ctx->EOF()){
if(newline == nullptr){
Exception::Warning("no new-line in the end of file");
}
return false;
}else{
return ctx->pp_token().size();
return true;
}
}

std::any PreProcessor::Visitor::visitText_line(PPParser::Text_lineContext *ctx){
for(auto pp_token : ctx->pp_token()){
pp.buffer.emplace_back(std::any_cast<Token>(visitPp_token(pp_token)));
}
return visitLine_end(ctx->line_end());
}

std::any PreProcessor::Visitor::visitControl_line(PPParser::Control_lineContext *ctx){
return visitChildren(ctx);
}

std::any PreProcessor::Visitor::visitPp_token(PPParser::Pp_tokenContext *ctx){
Expand All @@ -81,6 +91,32 @@ std::any PreProcessor::Visitor::visitPp_token(PPParser::Pp_tokenContext *ctx){
case PPLexer::WhiteSpace:
return Token {.type = Token::WhiteSpace, .text = " ", .pos = pos};
default:
throw Exception::SyntaxError(pos, std::string("unknown pre-processor token '") + token->getText() + "'");
throw Exception::SyntaxError(pos, "unknown pre-processor token '" + token->getText() + "'");
}
}

std::any PreProcessor::Visitor::visitDefine_obj(PPParser::Define_objContext *ctx){
std::string name = ctx->Identifier()->getText();
Macro macro {.name = name};
for(auto pp_token : ctx->pp_token()){
macro.replacement.emplace_back(std::any_cast<Token>(visitPp_token(pp_token)));
}
if(pp.macros.contains(name)){
if(pp.macros[name] != macro){
SourcePos pos {
.file = path,
.line = ctx->getStart()->getLine(),
.col = ctx->getStart()->getCharPositionInLine() + 1
};
throw Exception::SyntaxError(pos, "duplicated macro '" + name + "'");
}
}else{
pp.macros[name] = macro;
std::cout << "define macro [" << name << "]: ";
for(Token token : macro.replacement){
std::cout << token.text;
}
std::cout << std::endl;
}
return visitLine_end(ctx->line_end());
}
9 changes: 5 additions & 4 deletions src/lib/PreProcessor/Visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
#include <PPLexer.h>
#include <optional>
#include <memory>

#include "ErrorListener.hpp"
#include <fstream>

namespace WasmVM {

Expand All @@ -17,13 +16,15 @@ struct PreProcessor::Visitor : public PPVisitor {
bool fetch(); // false if match EOF

std::filesystem::path path;
ParseErrorListener parseErrorListener;


protected:
virtual std::any visitGroup(PPParser::GroupContext *) override;
virtual std::any visitText_line(PPParser::Text_lineContext *) override;
virtual std::any visitPp_token(PPParser::Pp_tokenContext *ctx) override;
virtual std::any visitLine_end(PPParser::Line_endContext* ctx) override;
virtual std::any visitControl_line(PPParser::Control_lineContext* ctx) override;
virtual std::any visitDefine_obj(PPParser::Define_objContext* ctx) override;

std::ifstream fin;
std::unique_ptr<antlr4::ANTLRInputStream> input;
std::unique_ptr<PPLexer> lexer;
Expand Down
5 changes: 5 additions & 0 deletions src/lib/PreProcessor/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#define foo const int test1
foo = 1;
#define foo2 test1 +
#define val 4
int test2 = foo2 val;
2 changes: 1 addition & 1 deletion src/lib/PreProcessor/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main(int argc, char const *argv[])
std::cerr << "Warning : " << message << std::endl;
});

PreProcessor pp("test.txt");
PreProcessor pp("test.c");

try{
for(std::optional<PreProcessor::Token> token = pp.get(); token.has_value(); token = pp.get()){
Expand Down
3 changes: 0 additions & 3 deletions src/lib/PreProcessor/test.txt

This file was deleted.

4 changes: 2 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ macro(add_test_suite suite_name)
endmacro(add_test_suite)

add_test_suite(pp_token)
# add_test_suite(pp_directive)
# add_test_suite(pp_macro)
add_test_suite(pp_macro)
# add_test_suite(pp_directive)
Loading

0 comments on commit 30f8e94

Please sign in to comment.