🚧 define notion of variable in snakefile.
parent
1ef177bfc8
commit
21cb7db86f
|
@ -5,7 +5,13 @@ DEPS ::= LITERAL*
|
|||
BLOCK ::= obrace CMD_LST cbrace
|
||||
CMD_LST ::= (CMD (comma CMD)* comma?)?
|
||||
CMD ::= LITERAL*
|
||||
LITERAL ::= ident | var | ARRAY | INDEX
|
||||
LITERAL ::=
|
||||
| ident
|
||||
| var
|
||||
| generic
|
||||
| ARRAY
|
||||
| INDEX
|
||||
|
||||
|
||||
VAR_DECL ::= var assign (LITERAL | ARRAY | INDEX)
|
||||
ARRAY ::= opar LITERAL* cpar
|
||||
|
|
|
@ -129,6 +129,11 @@ namespace sn
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO TRY GENERICS
|
||||
std::cout << "-> " << file << std::endl;
|
||||
}
|
||||
|
||||
m_state->update(file);
|
||||
}
|
||||
|
@ -407,12 +412,20 @@ namespace sn
|
|||
auto deps = *node->get(1);
|
||||
auto block = *node->get(2);
|
||||
|
||||
if (!target_node->collect(NODE_GENERIC).empty()
|
||||
|| !deps->collect(NODE_GENERIC).empty())
|
||||
// Generic rule here
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<std::string> target_values;
|
||||
std::vector<std::string> target_values_verbatim;
|
||||
|
||||
for (size_t i=0; i<target_node->size(); i++)
|
||||
{
|
||||
auto t = *target_node->get(i);
|
||||
|
||||
auto values = get_value(t);
|
||||
|
||||
std::copy(std::begin(values), std::end(values),
|
||||
|
|
|
@ -14,6 +14,25 @@ namespace sn
|
|||
{
|
||||
SN_ERROR(run_error);
|
||||
|
||||
/**
|
||||
* Represents a snakefile value.
|
||||
* (e.g a file, an array of files ...)
|
||||
**/
|
||||
struct Value {
|
||||
Value(std::filesystem::path p_file)
|
||||
: file { p_file }
|
||||
{
|
||||
}
|
||||
|
||||
Value(std::vector<std::filesystem::path> p_array)
|
||||
: array { p_array }
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> file;
|
||||
std::optional<std::vector<std::filesystem::path>> array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Process a snakefile AST and run build commands.
|
||||
* @see Node
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace sn
|
|||
add_text("}", NODE_CBRACE);
|
||||
add_text(",", NODE_COMMA);
|
||||
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_generic, this));
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_var, this));
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_ident, this));
|
||||
}
|
||||
|
@ -193,4 +194,39 @@ namespace sn
|
|||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<ScanInfo> Lexer::scan_generic()
|
||||
{
|
||||
size_t cursor = m_cursor;
|
||||
std::string repr;
|
||||
|
||||
if (cursor < m_source.size()
|
||||
&& m_source[cursor] == '^')
|
||||
{
|
||||
repr += '^';
|
||||
cursor++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
while (cursor < m_source.size()
|
||||
&& !is_separator(m_source[cursor]))
|
||||
{
|
||||
repr += m_source[cursor];
|
||||
cursor++;
|
||||
}
|
||||
|
||||
if (repr.empty() == false)
|
||||
{
|
||||
return ScanInfo {
|
||||
cursor,
|
||||
NODE_GENERIC,
|
||||
repr.substr(1)
|
||||
};
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace sn
|
|||
|
||||
std::optional<ScanInfo> scan_ident();
|
||||
std::optional<ScanInfo> scan_var();
|
||||
std::optional<ScanInfo> scan_generic();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
20
src/Node.cpp
20
src/Node.cpp
|
@ -53,4 +53,24 @@ namespace sn
|
|||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Node>> Node::collect(NodeType type)
|
||||
{
|
||||
std::vector<std::shared_ptr<Node>> results;
|
||||
|
||||
if (m_type == type)
|
||||
{
|
||||
return {shared_from_this()};
|
||||
}
|
||||
|
||||
for (auto child: m_children)
|
||||
{
|
||||
auto collected = child->collect(type);
|
||||
|
||||
std::copy(std::begin(collected), std::end(collected),
|
||||
std::back_inserter(results));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define sn_NODE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include <memory>
|
||||
|
||||
#define NODE_TYPES(G) \
|
||||
G(NODE_DOC), G(NODE_IDENT), G(NODE_RARROW), G(NODE_OBRACE), \
|
||||
|
@ -9,7 +10,7 @@
|
|||
G(NODE_BLOCK), G(NODE_TARGET), G(NODE_DEPS), G(NODE_RULE), \
|
||||
G(NODE_VAR), G(NODE_ASSIGN), G(NODE_VAR_DECL), G(NODE_OPAR), \
|
||||
G(NODE_CPAR), G(NODE_ARRAY), G(NODE_INDEX), G(NODE_OSQUARE), \
|
||||
G(NODE_CSQUARE)
|
||||
G(NODE_CSQUARE), G(NODE_GENERIC)
|
||||
|
||||
namespace sn
|
||||
{
|
||||
|
@ -18,7 +19,7 @@ namespace sn
|
|||
/**
|
||||
* A node is an element of the snake AST.
|
||||
**/
|
||||
class Node
|
||||
class Node: public std::enable_shared_from_this<Node>
|
||||
{
|
||||
public:
|
||||
explicit Node(NodeType type, std::string const& repr="");
|
||||
|
@ -33,6 +34,7 @@ namespace sn
|
|||
std::optional<std::shared_ptr<Node>> get(size_t index);
|
||||
|
||||
std::string string() const;
|
||||
std::vector<std::shared_ptr<Node>> collect(NodeType type);
|
||||
|
||||
private:
|
||||
NodeType m_type;
|
||||
|
|
|
@ -187,7 +187,8 @@ namespace sn
|
|||
}
|
||||
|
||||
if (type_is(NODE_IDENT)
|
||||
|| type_is(NODE_VAR))
|
||||
|| type_is(NODE_VAR)
|
||||
|| type_is(NODE_GENERIC))
|
||||
{
|
||||
return *consume();
|
||||
}
|
||||
|
|
|
@ -452,3 +452,39 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_constructor")
|
|||
test_contains(result, res);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(InterpreterTest, "Interpreter_generics", "[.]")
|
||||
{
|
||||
SECTION("no rule to apply")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "^.o -> ^.cpp {" << std::endl;
|
||||
ss << "$IN $OUT" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a"));
|
||||
REQUIRE(res.empty());
|
||||
}
|
||||
|
||||
SECTION("call left")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "^.o -> ^.cpp ^.el {" << std::endl;
|
||||
ss << "$IN $OUT" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a.cpp"));
|
||||
test_contains("a.o a.cpp", res);
|
||||
}
|
||||
|
||||
SECTION("call right")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "^.o -> ^.cpp ^.el {" << std::endl;
|
||||
ss << "$IN $OUT" << std::endl;
|
||||
ss << "}" << std::endl;
|
||||
|
||||
auto res = TEST_RUN(ss.str(), std::filesystem::path("a.el"));
|
||||
test_contains("a.o a.el", res);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,3 +62,14 @@ TEST_CASE_METHOD(LexerTest, "Lexer_arrays")
|
|||
test_next("CSQUARE");
|
||||
test_end();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_generic")
|
||||
{
|
||||
m_lexer.scan(" ^.o ^.cpp ^.tar.gz ");
|
||||
|
||||
test_next("GENERIC[.o]");
|
||||
test_next("GENERIC[.cpp]");
|
||||
test_next("GENERIC[.tar.gz]");
|
||||
|
||||
test_end();
|
||||
}
|
||||
|
|
|
@ -216,3 +216,20 @@ TEST_CASE_METHOD(ParserTest, "Parser_replace_ext_index")
|
|||
")))",
|
||||
ss.str());
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_generic")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << " ^.o -> ^.c {" << std::endl;
|
||||
ss << " g++ $IN -o $OUT " << std::endl;
|
||||
ss << " }" << std::endl;
|
||||
|
||||
test_parse("DOC("
|
||||
"RULE("
|
||||
"TARGET(GENERIC[.o])"
|
||||
",DEPS(GENERIC[.c])"
|
||||
",BLOCK("
|
||||
"CMD(IDENT[g++],VAR[IN],IDENT[-o],VAR[OUT])"
|
||||
")))",
|
||||
ss.str());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue