✨ extension selector.
parent
c0aecff8b3
commit
35996484b2
|
@ -9,4 +9,5 @@ LITERAL ::= ident | var | ARRAY | INDEX
|
|||
|
||||
VAR_DECL ::= var assign (LITERAL | ARRAY | INDEX)
|
||||
ARRAY ::= opar LITERAL* cpar
|
||||
INDEX ::= (var|ARRAY) osquare ident csquare
|
||||
INDEX ::=
|
||||
| (var|ARRAY) osquare ident (assign ident)? csquare
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace sn
|
|||
}
|
||||
|
||||
std::vector<std::string>
|
||||
Interpreter::get_value(std::shared_ptr<Node> node)
|
||||
Interpreter::get_value(std::shared_ptr<Node> node) const
|
||||
{
|
||||
if (node->type() == NODE_IDENT)
|
||||
{
|
||||
|
@ -167,20 +167,67 @@ namespace sn
|
|||
auto var = *node->get(0);
|
||||
auto val = *node->get(1);
|
||||
|
||||
auto values = get_value(var);
|
||||
ssize_t index = std::stoi(val->repr());
|
||||
|
||||
if (index < 0)
|
||||
if (node->size() > 2)
|
||||
// Extension replacement
|
||||
{
|
||||
index = values.size() + index;
|
||||
}
|
||||
auto old_values = get_value(var);
|
||||
std::vector<std::string> values;
|
||||
std::string src_extension = val->repr();
|
||||
std::string dest_extension = (*node->get(2))->repr();
|
||||
|
||||
if (index >= static_cast<ssize_t>(values.size()))
|
||||
std::transform(std::begin(old_values), std::end(old_values),
|
||||
std::back_inserter(values),
|
||||
[src_extension, dest_extension]
|
||||
(auto const& val){
|
||||
auto val_p = std::filesystem::path(val);
|
||||
|
||||
if (val_p.has_extension()
|
||||
&& val_p.extension() == src_extension)
|
||||
{
|
||||
return val_p.replace_extension(dest_extension);
|
||||
}
|
||||
else
|
||||
{
|
||||
return val_p;
|
||||
}
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
else if (val->repr().size() > 0 && val->repr()[0] == '.')
|
||||
// Extension modifier
|
||||
{
|
||||
throw run_error {"invalid index '" + std::to_string(index) + "'"};
|
||||
}
|
||||
auto old_values = get_value(var);
|
||||
std::vector<std::string> values;
|
||||
std::string extension = val->repr();
|
||||
|
||||
return { values[index] };
|
||||
std::transform(std::begin(old_values), std::end(old_values),
|
||||
std::back_inserter(values),
|
||||
[extension](auto const& val){
|
||||
auto val_p = std::filesystem::path(val);
|
||||
return val_p.replace_extension(extension);
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
else
|
||||
// Index selector
|
||||
{
|
||||
auto values = get_value(var);
|
||||
ssize_t index = std::stoi(val->repr());
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = values.size() + index;
|
||||
}
|
||||
|
||||
if (index >= static_cast<ssize_t>(values.size()))
|
||||
{
|
||||
throw run_error {"invalid index '" + std::to_string(index) + "'"};
|
||||
}
|
||||
|
||||
return { values[index] };
|
||||
}
|
||||
}
|
||||
|
||||
throw run_error {"cannot find value for '"
|
||||
|
@ -289,33 +336,19 @@ namespace sn
|
|||
auto cmd = *block->get(i);
|
||||
|
||||
std::string script;
|
||||
std::string sep;
|
||||
|
||||
for (size_t j=0; j<cmd->size(); j++)
|
||||
{
|
||||
auto c = *cmd->get(j);
|
||||
|
||||
if (c->type() == NODE_IDENT)
|
||||
{
|
||||
script += sep + c->repr();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto var = *m_sym.get(c->repr());
|
||||
std::string vsep;
|
||||
auto values = get_value(c);
|
||||
std::string vsep = (j > 0) ? " " : "";
|
||||
|
||||
if (j > 0)
|
||||
{
|
||||
vsep = " ";
|
||||
}
|
||||
for (auto const& v: var.values)
|
||||
{
|
||||
script += vsep + v;
|
||||
vsep = " ";
|
||||
}
|
||||
for (auto val: values)
|
||||
{
|
||||
script += vsep + val;
|
||||
vsep = " ";
|
||||
}
|
||||
|
||||
sep = " ";
|
||||
}
|
||||
|
||||
result.push_back(script);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace sn
|
|||
std::vector<std::string>> m_scripts;
|
||||
SymTable m_sym;
|
||||
|
||||
std::vector<std::string> get_value(std::shared_ptr<Node> node);
|
||||
std::vector<std::string> get_value(std::shared_ptr<Node> node) const;
|
||||
|
||||
std::vector<std::filesystem::path>
|
||||
targets(std::filesystem::path path) const;
|
||||
|
|
|
@ -262,6 +262,13 @@ namespace sn
|
|||
|
||||
consume(NODE_OSQUARE);
|
||||
node->add_child(*consume(NODE_IDENT));
|
||||
|
||||
if (type_is(NODE_ASSIGN))
|
||||
{
|
||||
consume();
|
||||
node->add_child(*consume(NODE_IDENT));
|
||||
}
|
||||
|
||||
consume(NODE_CSQUARE);
|
||||
|
||||
return node;
|
||||
|
|
|
@ -227,7 +227,7 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_index")
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_literal_index", "[.]")
|
||||
TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_literal_index")
|
||||
{
|
||||
SECTION("get second: ok")
|
||||
{
|
||||
|
@ -277,3 +277,45 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_literal_index", "[.]")
|
|||
test_not_contains("executed", res);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(InterpreterTest, "Interpreter_select_ext")
|
||||
{
|
||||
SECTION("on var")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "$Y = g.h" << std::endl;
|
||||
ss << "d -> a {" << std::endl;
|
||||
ss << "$Y $Y[.hpp] $Y[.cpp]" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a"));
|
||||
test_contains("g.h g.hpp g.cpp", res);
|
||||
}
|
||||
|
||||
SECTION("on array")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "$Y = (x.c y.c z.d)" << std::endl;
|
||||
ss << "d -> a {" << std::endl;
|
||||
ss << "$Y[.cpp]" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a"));
|
||||
test_contains("x.cpp y.cpp z.cpp", res);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(InterpreterTest, "Interpreter_replace_ext")
|
||||
{
|
||||
SECTION("on array")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "$Y = (x.c y.c z.d w t.h)" << std::endl;
|
||||
ss << "d -> a {" << std::endl;
|
||||
ss << "$Y[.c=.h]" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a"));
|
||||
test_contains("x.h y.h z.d w t.h", res);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,3 +187,32 @@ TEST_CASE_METHOD(ParserTest, "Parser_array_index_literal")
|
|||
")))",
|
||||
ss.str());
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_replace_ext_index")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "$BIM = hello.cpp" << std::endl;
|
||||
ss << "$BAM = (world.hpp world.cpp)[14]" << std::endl;
|
||||
ss << " $BIM -> (hello.cpp world.cpp) {" << std::endl;
|
||||
ss << " g++ $BIM[.c=.o] -o hello.elf, " << std::endl;
|
||||
ss << " ls " << std::endl;
|
||||
ss << " }" << std::endl;
|
||||
|
||||
test_parse("DOC("
|
||||
"VAR_DECL(VAR[BIM],IDENT[hello.cpp]),"
|
||||
"VAR_DECL(VAR[BAM],"
|
||||
"INDEX(ARRAY(IDENT[world.hpp],IDENT[world.cpp]),IDENT[14])),"
|
||||
"RULE("
|
||||
"TARGET("
|
||||
"VAR[BIM]"
|
||||
"),DEPS("
|
||||
"ARRAY(IDENT[hello.cpp],IDENT[world.cpp])"
|
||||
"),BLOCK("
|
||||
"CMD("
|
||||
"IDENT[g++],INDEX(VAR[BIM],IDENT[.c],IDENT[.o]),IDENT[-o],IDENT[hello.elf]"
|
||||
"),CMD("
|
||||
"IDENT[ls]"
|
||||
")"
|
||||
")))",
|
||||
ss.str());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue