diff --git a/common/jinja/jinja-compiler.h b/common/jinja/jinja-compiler.h deleted file mode 100644 index 32792d6050..0000000000 --- a/common/jinja/jinja-compiler.h +++ /dev/null @@ -1,79 +0,0 @@ -#include "common.h" -#include -#include - -namespace jinja { - -struct compiler { - common_chat_peg_native_builder builder; - common_peg_parser root; - - compiler() : root(builder.choice()) { - auto & p = builder; - - auto ws = p.rule("ws", p.chars("[ \t]", 0, -1)); - auto num = p.rule("num", p.chars("[0-9]", 1, -1)); - - // - // expressions - // - - auto expression = p.choice(); - - auto var_name = p.rule("var_name", p.chars("[a-zA-Z_]", 1, -1) << p.chars("[a-zA-Z0-9_]", 0, -1)); - expression |= var_name; - - // value - auto p_int = p.rule("value_int", num); - auto p_flt = p.rule("value_flt", num << "." << p.optional(num)); - auto p_str = p.rule("value_str", - p.json_string() | - p.literal("'") + p.chars("[^']*", 0, -1) + p.literal("'") - ); - - expression |= p_int; - expression |= p_flt; - expression |= p_str; - - // function calls - auto p_args = p.rule("args", expression << ws << p.zero_or_more("," << ws << expression)); - auto p_func = p.rule("func", ws << var_name << ws << "(" << ws << p_args << ws << ")"); - expression |= p_func; - - // indexing - auto p_idx = p.rule("idx", ws << "[" << ws << expression << ws << "]"); - expression |= p_idx; - - // set - auto p_set = p.rule("set", "set " << ws << var_name << ws << "=" << expression); - expression |= p_set; - - // if, else, endif - auto p_if = p.rule("if", "if " << ws << expression << ws); - auto p_else = p.rule("else", "else " << ws << expression << ws); - auto p_endif = p.rule("endif", p.literal("endif")); - - expression |= p_if; - expression |= p_else; - expression |= p_endif; - - expression = p.space() + expression + p.space(); - - // - // root - // - - // auto strip = p.rule("strip", "-" << expression << "-"); - auto print = p.rule("print", "{{" << (expression) << "}}"); - auto ctrl = p.rule("ctrl", "{%" << (expression) << "%}"); - - root |= print; - root |= ctrl; - root |= p.rule("text", p.negate(root)); - - root = p.one_or_more(root); - root += p.end(); - } -}; - -} // namespace jinja diff --git a/common/jinja/jinja-lexer.h b/common/jinja/jinja-lexer.h index 554f30500a..2011e487b1 100644 --- a/common/jinja/jinja-lexer.h +++ b/common/jinja/jinja-lexer.h @@ -48,6 +48,38 @@ struct token { std::string value; }; +std::string type_to_string(token::type t) { + switch (t) { + case token::undefined: return "undefined"; + case token::text: return "text"; + case token::numeric_literal: return "numeric_literal"; + case token::string_literal: return "string_literal"; + case token::identifier: return "identifier"; + case token::equals: return "equals"; + case token::open_paren: return "open_paren"; + case token::close_paren: return "close_paren"; + case token::open_statement: return "open_statement"; + case token::close_statement: return "close_statement"; + case token::open_expression: return "open_expression"; + case token::close_expression: return "close_expression"; + case token::open_square_bracket: return "open_square_bracket"; + case token::close_square_bracket: return "close_square_bracket"; + case token::open_curly_bracket: return "open_curly_bracket"; + case token::close_curly_bracket: return "close_curly_bracket"; + case token::comma: return "comma"; + case token::dot: return "dot"; + case token::colon: return "colon"; + case token::pipe: return "pipe"; + case token::call_operator: return "call_operator"; + case token::additive_binary_operator: return "additive_binary_operator"; + case token::multiplicative_binary_operator: return "multiplicative_binary_operator"; + case token::comparison_binary_operator: return "comparison_binary_operator"; + case token::unary_operator: return "unary_operator"; + case token::comment: return "comment"; + default: return "unknown"; + } +} + struct lexer { const std::map escape_chars = { {'n', '\n'}, diff --git a/common/jinja/jinja-parser.cpp b/common/jinja/jinja-parser.cpp new file mode 100644 index 0000000000..fa8cd9785a --- /dev/null +++ b/common/jinja/jinja-parser.cpp @@ -0,0 +1,39 @@ +#include "jinja-lexer.h" +#include "jinja-vm.h" + +namespace jinja { + +void parse(const std::vector & tokens) { + auto program = std::make_unique(); + size_t current = 0; + + /** + * Consume the next token if it matches the expected type, otherwise throw an error. + * @param type The expected token type + * @param error The error message to throw if the token does not match the expected type + * @returns The consumed token + */ + auto expect = [&](const token::type & type, const std::string & error) -> token { + const auto & prev = tokens[current++]; + if (prev.t != type) { + throw std::runtime_error("Parser Error: " + error + " (" + type_to_string(prev.t) + " != " + type_to_string(type) + ")"); + } + return prev; + }; + + auto next_token = [&]() -> const token & { + if (current >= tokens.size()) { + return token{token::undefined, ""}; + } + return tokens[current++]; + }; + + auto expect_identifier = [&](const std::string & name) -> void { + if (!is_identifier(name)) { + throw std::runtime_error("Expected " + name); + } + ++current; + }; +} + +}; // namespace jinja diff --git a/common/jinja/jinja-vm.cpp b/common/jinja/jinja-vm.cpp deleted file mode 100644 index 7c8d0cf732..0000000000 --- a/common/jinja/jinja-vm.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -struct vm_context { - std::ostringstream out; -}; - -struct op_base { - virtual ~op_base() = default; - virtual void execute(vm_context & ctx) = 0; -}; - -struct op_print : public op_base { - std::string message; - op_print(const std::string & message) : message(message) {} - void execute(vm_context & ctx) override { - ctx.out << message; - } -}; - -struct op_load : public op_base { - std::string dst; - std::string src; - std::string value; - op_load(const std::string & dst) : dst(dst) {} - void execute(vm_context & ctx) override { - } -};