Skip to content

Commit

Permalink
[PP] Pragma directive
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisHsu committed Mar 23, 2024
1 parent 2c1fa70 commit 1f64e47
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/include/PreProcessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ struct PreProcessor {
PreProcessor(std::filesystem::path path, std::string source, std::vector<std::filesystem::path> include_paths = {});
PPToken get();

struct {
std::optional<bool> fp_contract;
std::optional<bool> fenv_access;
std::optional<bool> cx_limited_value;
} pragma;

#ifndef CCTEST
private:
#endif
Expand Down Expand Up @@ -148,7 +154,7 @@ struct PreProcessor {
void undef_directive();
void line_directive();
void error_directive();
// void pragma_directive(PPToken& token); // TODO:
void pragma_directive();
};

} // namespace WasmVM
Expand Down
40 changes: 39 additions & 1 deletion src/lib/PreProcessor/PreProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ PreProcessor::PPToken PreProcessor::get(){
}else if(direcitve_name == "error"){
error_directive();
}else if(direcitve_name == "pragma"){
// TODO:
pragma_directive();
}else if(direcitve_name == "include"){
include_directive();
}else{
Expand Down Expand Up @@ -378,3 +378,41 @@ void PreProcessor::error_directive(){
}
throw Exception::Error(pos, message.str());
}

void PreProcessor::pragma_directive(){
Line::iterator cur = skip_whitespace(line.begin(), line.end());
SourcePos pos = cur->value().pos;
if(cur != line.end() && cur->hold<TokenType::Identifier>()){
if(((TokenType::Identifier)cur->value()).sequence == "STDC"){
cur = skip_whitespace(std::next(cur), line.end());
if(cur != line.end() && cur->hold<TokenType::Identifier>()){
TokenType::Identifier name = cur->value();
cur = skip_whitespace(std::next(cur), line.end());
if(cur != line.end() && cur->hold<TokenType::Identifier>()){
TokenType::Identifier on_off = cur->value();
std::optional<bool> toggle;
if(on_off.sequence == "ON"){
toggle = true;
}else if(on_off.sequence == "OFF"){
toggle = false;
}else if(on_off.sequence == "DEFAULT"){
toggle.reset();
}else{
throw Exception::Error(cur->value().pos, "invalid value of ON/OFF switch");
}
if(name.sequence == "FP_CONTRACT"){
pragma.fp_contract.swap(toggle);
return;
}else if(name.sequence == "FENV_ACCESS"){
pragma.fenv_access.swap(toggle);
return;
}else if(name.sequence == "CX_LIMITED_RANGE"){
pragma.cx_limited_value.swap(toggle);
return;
}
}
}
}
}
throw Exception::Error(pos, "unknown pragma");
}
39 changes: 39 additions & 0 deletions test/pp_directive/pp_directive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,43 @@ Suite pp_directive {
PreProcessor pp(std::filesystem::path("error.c"));
Throw(Exception::Exception, pp.get());
})
Test("pragma", {
PreProcessor pp(std::filesystem::path("pragma.c"));
PreProcessor::PPToken token;
pp.get();
Expect(pp.pragma.fp_contract.has_value() && (pp.pragma.fp_contract.value() == true));
pp.get();

pp.get();
Expect(pp.pragma.fp_contract.has_value() && (pp.pragma.fp_contract.value() == false));
pp.get();

pp.get();
Expect(!pp.pragma.fp_contract.has_value());
pp.get();

pp.get();
Expect(pp.pragma.fenv_access.has_value() && (pp.pragma.fenv_access.value() == true));
pp.get();

pp.get();
Expect(pp.pragma.fenv_access.has_value() && (pp.pragma.fenv_access.value() == false));
pp.get();

pp.get();
Expect(!pp.pragma.fenv_access.has_value());
pp.get();

pp.get();
Expect(pp.pragma.cx_limited_value.has_value() && (pp.pragma.cx_limited_value.value() == true));
pp.get();

pp.get();
Expect(pp.pragma.cx_limited_value.has_value() && (pp.pragma.cx_limited_value.value() == false));
pp.get();

pp.get();
Expect(!pp.pragma.cx_limited_value.has_value());
pp.get();
})
};
17 changes: 17 additions & 0 deletions test/pp_directive/pragma.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma STDC FP_CONTRACT ON
;
#pragma STDC FP_CONTRACT OFF
;
#pragma STDC FP_CONTRACT DEFAULT
;
#pragma STDC FENV_ACCESS ON
;
#pragma STDC FENV_ACCESS OFF
;
#pragma STDC FENV_ACCESS DEFAULT
;
#pragma STDC CX_LIMITED_RANGE ON
;
#pragma STDC CX_LIMITED_RANGE OFF
;
#pragma STDC CX_LIMITED_RANGE DEFAULT

0 comments on commit 1f64e47

Please sign in to comment.