#ifndef __JetParser_h__ #define __JetParser_h__ #include "JetAST.h" #include #include #include namespace jetc { // Standalone parser for a subset of the JET template grammar. Mirrors the // character-level grammar implemented by JetCore's Tag::parseContainer / // Tag::Tag (attribute scanning, same-tag-name nesting depth, the // split) closely enough for well-formed templates, but is a fresh // implementation - it does not reuse JetCore's Tag classes, since those // fuse parsing and execution together (a real parse/execute split there // is a separate, larger refactor). Anything outside the modeled subset // (set/if/for/while/$[...]/literal text) is captured as an exact raw // source span and left for the existing interpreter (Tag::interpretSpan) // to run at compiled-program runtime, so unsupported constructs degrade // gracefully instead of failing to compile. class Parser { public: explicit Parser(const std::string &src) : s(src), pos(0) {} std::vector parseNodes(); private: std::string s; size_t pos; size_t nextId = 0; bool eof() const { return pos >= s.size(); } bool starts(const std::string &lit) const; static bool isNameChar(char c); void skipWs(); std::string readName(); std::string peekTagName(size_t at) const; bool matchTagOpen(const std::string &name, size_t at) const; bool matchTagClose(const std::string &name, size_t at) const; // p points at '<' of some tag's opening; advances p past its '>' or // "/>", skipping quoted attribute values. Returns true if self-closing. bool skipOpenTag(size_t &p) const; std::map parseAttrs(bool &hasContainer); // Scans forward from bodyStart (just after the opening tag's '>') for // tagName's matching close, tracking same-tag-name nesting depth and // (if lookForElse) a depth==1 "" split point. // Returns {closePos, elsePos} (elsePos == npos if not found/not sought). std::pair scanBody(size_t bodyStart, const std::string &tagName, bool lookForElse); std::vector parseSub(size_t start, size_t end); NodePtr parseVar(); NodePtr parseSet(); NodePtr parseIf(); NodePtr parseFor(); NodePtr parseWhile(); NodePtr parseFallback(); std::string newId(const std::string &prefix) { return prefix + std::to_string(nextId++) + "_"; } }; } #endif