[clang-tools-extra] [llvm] [llvm] add support for mustache templating language (PR #105893)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 13 13:41:29 PDT 2024


================
@@ -0,0 +1,276 @@
+//===-- Mustache.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Mustache.h"
+#include "llvm/Support/Error.h"
+#include <iostream>
+#include <regex>
+#include <sstream>
+
+using namespace llvm;
+using namespace llvm::json;
+using namespace llvm::mustache;
+
+std::string escapeHtml(const std::string &Input) {
+  DenseMap<char, std::string> HtmlEntities = {{'&', "&"},
+                                              {'<', "<"},
+                                              {'>', ">"},
+                                              {'"', """},
+                                              {'"', "'"}};
+  std::string EscapedString;
+  EscapedString.reserve(Input.size());
+
+  for (char C : Input) {
+    if (HtmlEntities.find(C) != HtmlEntities.end()) {
+      EscapedString += HtmlEntities[C];
+    } else {
+      EscapedString += C;
+    }
+  }
+
+  return EscapedString;
+}
+
+std::vector<std::string> split(const std::string &Str, char Delimiter) {
+  std::vector<std::string> Tokens;
+  std::string Token;
+  std::stringstream SS(Str);
+  if (Str == ".") {
+    Tokens.push_back(Str);
+    return Tokens;
+  }
+  while (std::getline(SS, Token, Delimiter)) {
+    Tokens.push_back(Token);
+  }
+  return Tokens;
+}
+
+Token::Token(std::string Str, char Identifier) {
+  switch (Identifier) {
+  case '#':
+    TokenType = Type::SectionOpen;
+    break;
+  case '/':
+    TokenType = Type::SectionClose;
+    break;
+  case '^':
+    TokenType = Type::InvertSectionOpen;
+    break;
+  case '!':
+    TokenType = Type::Comment;
+    break;
+  case '>':
+    TokenType = Type::Partial;
+    break;
+  case '&':
+    TokenType = Type::UnescapeVariable;
+    break;
+  default:
+    TokenType = Type::Variable;
+  }
+  if (TokenType == Type::Comment)
+    return;
+
+  TokenBody = Str;
+  std::string AccessorStr = Str;
+  if (TokenType != Type::Variable) {
+    AccessorStr = Str.substr(1);
+  }
+  Accessor = split(StringRef(AccessorStr).trim().str(), '.');
+}
+
+Token::Token(std::string Str)
+    : TokenType(Type::Text), TokenBody(Str), Accessor({}) {}
+
+std::vector<Token> tokenize(std::string Template) {
+  std::vector<Token> Tokens;
+  std::regex Re(R"(\{\{(.*?)\}\})");
+  std::sregex_token_iterator Iter(Template.begin(), Template.end(), Re,
+                                  {-1, 0});
+  std::sregex_token_iterator End;
+
+  for (; Iter != End; ++Iter) {
+    if (!Iter->str().empty()) {
+      std::string Token = *Iter;
+      std::smatch Match;
+      if (std::regex_match(Token, Match, Re)) {
+        std::string Group = Match[1];
+        Tokens.emplace_back(Group, Group[0]);
+      } else {
+        Tokens.emplace_back(Token);
+      }
+    }
+  }
+
+  return Tokens;
+}
+
+class Parser {
+public:
+  Parser(std::string TemplateStr) : TemplateStr(TemplateStr) {}
+
+  std::shared_ptr<ASTNode> parse();
+
+private:
+  void parseMustache(std::shared_ptr<ASTNode> Parent);
+
+  std::vector<Token> Tokens;
+  std::size_t CurrentPtr;
+  std::string TemplateStr;
+};
+
+std::shared_ptr<ASTNode> Parser::parse() {
+  Tokens = tokenize(TemplateStr);
+  CurrentPtr = 0;
+  std::shared_ptr<ASTNode> Root = std::make_shared<ASTNode>();
----------------
PeterChou1 wrote:

I've refactored it to use an arena

https://github.com/llvm/llvm-project/pull/105893


More information about the cfe-commits mailing list