Skip to content

Commit bb4ba40

Browse files
committed
[llvm] address more comments
1 parent b58fbcb commit bb4ba40

File tree

2 files changed

+95
-73
lines changed

2 files changed

+95
-73
lines changed

llvm/include/llvm/Support/Mustache.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class ASTNode {
130130
InvertSection,
131131
};
132132

133-
ASTNode() : T(Type::Root), ParentContext(nullptr), LocalContext(nullptr) {};
133+
ASTNode() : T(Type::Root), ParentContext(nullptr) {};
134134

135135
ASTNode(StringRef Body, ASTNode *Parent)
136136
: T(Type::Text), Body(Body), Parent(Parent), ParentContext(nullptr),
@@ -151,12 +151,12 @@ class ASTNode {
151151

152152
void render(const llvm::json::Value &Data, SmallString<0> &Output);
153153

154-
void setUpNode(StringMap<ASTNode *> &Partials, StringMap<Lambda> &Lambdas,
154+
void setUpNode(llvm::BumpPtrAllocator &Alloc,
155+
StringMap<ASTNode *> &Partials,
156+
StringMap<Lambda> &Lambdas,
155157
StringMap<SectionLambda> &SectionLambdas,
156158
DenseMap<char, StringRef> &Escapes);
157-
158-
void setUpContext(llvm::BumpPtrAllocator *Alloc);
159-
159+
160160
private:
161161

162162
void renderLambdas(const llvm::json::Value &Contexts, SmallString<0> &Output,
@@ -212,9 +212,12 @@ class Template {
212212
StringMap<Lambda> Lambdas;
213213
StringMap<SectionLambda> SectionLambdas;
214214
DenseMap<char, StringRef> Escapes;
215+
// The allocator for the ASTNode Tree
215216
llvm::BumpPtrAllocator Allocator;
217+
// Allocator for each render call resets after each render
218+
llvm::BumpPtrAllocator LocalAllocator;
216219
ASTNode *Tree;
217220
};
218221
} // namespace mustache
219222
} // end namespace llvm
220-
#endif // LLVM_SUPPORT_MUSTACHE
223+
#endif // LLVM_SUPPORT_MUSTACHE

llvm/lib/Support/Mustache.cpp

Lines changed: 86 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ using namespace llvm::mustache;
1616

1717
SmallString<0> escapeString(StringRef Input,
1818
DenseMap<char, StringRef> &Escape) {
19-
2019
SmallString<0> Output;
20+
Output.reserve(Input.size());
2121
for (char C : Input) {
2222
auto It = Escape.find(C);
2323
if (It != Escape.end())
@@ -91,24 +91,33 @@ Token::Type Token::getTokenType(char Identifier) {
9191

9292
// Function to check if there's no meaningful text behind
9393
bool noTextBehind(size_t Idx, const SmallVector<Token, 0> &Tokens) {
94-
if (Idx == 0 || Tokens[Idx - 1].getType() != Token::Type::Text)
94+
if(Idx == 0)
95+
return false;
96+
97+
int PrevIdx = Idx - 1;
98+
if (Tokens[PrevIdx].getType() != Token::Type::Text)
9599
return false;
100+
96101
const Token &PrevToken = Tokens[Idx - 1];
97102
StringRef TokenBody = PrevToken.getRawBody().rtrim(" \t\v\t");
98-
// We make a special exception for when previous token is empty
103+
// We make an exception for when previous token is empty
99104
// and the current token is the second token
100105
// ex.
101106
// " {{#section}}A{{/section}}"
102-
// that's why we check if the token body is empty and the index is 1
107+
// the output of this is
108+
// "A"
103109
return TokenBody.ends_with("\n") || (TokenBody.empty() && Idx == 1);
104110
}
105111

106112
// Function to check if there's no meaningful text ahead
107113
bool noTextAhead(size_t Idx, const SmallVector<Token, 0> &Tokens) {
108-
if (Idx >= Tokens.size() - 1 ||
109-
Tokens[Idx + 1].getType() != Token::Type::Text)
114+
if (Idx >= Tokens.size() - 1)
110115
return false;
111-
116+
117+
int PrevIdx = Idx + 1;
118+
if (Tokens[Idx + 1].getType() != Token::Type::Text)
119+
return false;
120+
112121
const Token &NextToken = Tokens[Idx + 1];
113122
StringRef TokenBody = NextToken.getRawBody().ltrim(" ");
114123
return TokenBody.starts_with("\r\n") || TokenBody.starts_with("\n");
@@ -121,10 +130,47 @@ bool requiresCleanUp(Token::Type T) {
121130
T == Token::Type::Partial;
122131
}
123132

124-
// Simple tokenizer that splits the template into tokens
125-
// the mustache spec allows {{{ }}} to unescape variables
126-
// but we don't support that here unescape variable
127-
// is represented only by {{& variable}}
133+
// Adjust next token body if there is no text ahead
134+
// eg.
135+
// The template string
136+
// "{{! Comment }} \nLine 2"
137+
// would be considered as no text ahead and should be render as
138+
// " Line 2"
139+
void stripTokenAhead(SmallVector<Token, 0>& Tokens, size_t Idx) {
140+
Token &NextToken = Tokens[Idx + 1];
141+
StringRef NextTokenBody = NextToken.getTokenBody();
142+
// cut off the leading newline which could be \n or \r\n
143+
if (NextTokenBody.starts_with("\r\n"))
144+
NextToken.setTokenBody(NextTokenBody.substr(2));
145+
else if (NextTokenBody.starts_with("\n"))
146+
NextToken.setTokenBody(NextTokenBody.substr(1));
147+
}
148+
149+
// Adjust previous token body if there no text behind
150+
// eg.
151+
// The template string
152+
// " \t{{#section}}A{{/section}}"
153+
// would be considered as no text ahead and should be render as
154+
// "A"
155+
// The exception for this is partial tag which requires us to
156+
// keep track of the indentation once it's rendered
157+
void stripTokenBefore(SmallVector<Token, 0>& Tokens,
158+
size_t Idx,
159+
Token& CurrentToken,
160+
Token::Type CurrentType) {
161+
Token &PrevToken = Tokens[Idx - 1];
162+
StringRef PrevTokenBody = PrevToken.getTokenBody();
163+
StringRef Unindented = PrevTokenBody.rtrim(" \t\v");
164+
size_t Indentation = PrevTokenBody.size() - Unindented.size();
165+
if (CurrentType != Token::Type::Partial)
166+
PrevToken.setTokenBody(Unindented);
167+
CurrentToken.setIndentation(Indentation);
168+
}
169+
170+
// Simple tokenizer that splits the template into tokens.
171+
// The mustache spec allows {{{ }}} to unescape variables
172+
// but we don't support that here. An unescape variable
173+
// is represented only by {{& variable}}.
128174
SmallVector<Token, 0> tokenize(StringRef Template) {
129175
SmallVector<Token, 0> Tokens;
130176
StringRef Open("{{");
@@ -160,7 +206,11 @@ SmallVector<Token, 0> tokenize(StringRef Template) {
160206
Tokens.emplace_back(Template.substr(Start));
161207

162208
// Fix up white spaces for:
163-
// open sections/inverted sections/close section/comment
209+
// - open sections
210+
// - inverted sections
211+
// - close sections
212+
// - comments
213+
//
164214
// This loop attempts to find standalone tokens and tries to trim out
165215
// the surrounding whitespace.
166216
// For example:
@@ -178,47 +228,22 @@ SmallVector<Token, 0> tokenize(StringRef Template) {
178228
if (!RequiresCleanUp)
179229
continue;
180230

181-
// We adjust the token body if there's no text behind or ahead a token is
182-
// considered surrounded by no text if the right of the previous token
183-
// is a newline followed by spaces or if the left of the next token
184-
// is spaces followed by a newline
231+
// We adjust the token body if there's no text behind or ahead.
232+
// A token is considered to have no text ahead if the right of the previous
233+
// token is a newline followed by spaces.
234+
// A token is considered to have no text behind if the left of the next
235+
// token is spaces followed by a newline.
185236
// eg.
186237
// "Line 1\n {{#section}} \n Line 2 \n {{/section}} \n Line 3"
187-
188238
bool NoTextBehind = noTextBehind(Idx, Tokens);
189239
bool NoTextAhead = noTextAhead(Idx, Tokens);
190-
191-
// Adjust next token body if there is no text ahead
192-
// eg.
193-
// The template string
194-
// "{{! Comment }} \nLine 2"
195-
// would be considered as no text ahead and should be render as
196-
// " Line 2"
240+
197241
if ((NoTextBehind && NoTextAhead) || (NoTextAhead && Idx == 0)) {
198-
Token &NextToken = Tokens[Idx + 1];
199-
StringRef NextTokenBody = NextToken.getTokenBody();
200-
// cut off the leading newline which could be \n or \r\n
201-
if (NextTokenBody.starts_with("\r\n"))
202-
NextToken.setTokenBody(NextTokenBody.substr(2));
203-
else if (NextTokenBody.starts_with("\n"))
204-
NextToken.setTokenBody(NextTokenBody.substr(1));
242+
stripTokenAhead(Tokens, Idx);
205243
}
206-
// Adjust previous token body if there no text behind
207-
// eg.
208-
// The template string
209-
// " \t{{#section}}A{{/section}}"
210-
// would be considered as no text ahead and should be render as
211-
// "A"
212-
// The exception for this is partial tag which requires us to
213-
// keep track of the indentation once it's rendered
244+
214245
if (((NoTextBehind && NoTextAhead) || (NoTextBehind && Idx == LastIdx))) {
215-
Token &PrevToken = Tokens[Idx - 1];
216-
StringRef PrevTokenBody = PrevToken.getTokenBody();
217-
StringRef Unindented = PrevTokenBody.rtrim(" \t\v");
218-
size_t Indentation = PrevTokenBody.size() - Unindented.size();
219-
if (CurrentType != Token::Type::Partial)
220-
PrevToken.setTokenBody(Unindented);
221-
CurrentToken.setIndentation(Indentation);
246+
stripTokenBefore(Tokens, Idx, CurrentToken, CurrentType);
222247
}
223248
}
224249
return Tokens;
@@ -304,25 +329,25 @@ void Parser::parseMustache(ASTNode *Parent) {
304329
Parent->addChild(CurrentNode);
305330
break;
306331
}
332+
case Token::Type::Comment:
333+
break;
307334
case Token::Type::SectionClose:
308335
return;
309-
default:
310-
break;
311336
}
312337
}
313338
}
314339

315340
StringRef Template::render(Value &Data) {
316-
BumpPtrAllocator LocalAllocator;
317-
Tree->setUpContext(&LocalAllocator);
318341
Tree->render(Data, Output);
342+
LocalAllocator.Reset();
319343
return Output.str();
320344
}
321345

322346
void Template::registerPartial(StringRef Name, StringRef Partial) {
323347
Parser P = Parser(Partial, Allocator);
324348
ASTNode *PartialTree = P.parse();
325-
PartialTree->setUpNode(Partials, Lambdas, SectionLambdas, Escapes);
349+
PartialTree->setUpNode(LocalAllocator, Partials, Lambdas, SectionLambdas,
350+
Escapes);
326351
Partials.insert(std::make_pair(Name, PartialTree));
327352
}
328353

@@ -344,7 +369,8 @@ Template::Template(StringRef TemplateStr) {
344369
{'"', "&quot;"},
345370
{'\'', "&#39;"}};
346371
registerEscape(HtmlEntities);
347-
Tree->setUpNode(Partials, Lambdas, SectionLambdas, Escapes);
372+
Tree->setUpNode(LocalAllocator,
373+
Partials, Lambdas, SectionLambdas, Escapes);
348374
}
349375

350376
void toJsonString(const Value &Data, SmallString<0> &Output) {
@@ -494,7 +520,6 @@ void ASTNode::renderChild(const Value &Contexts, SmallString<0> &Output) {
494520

495521
void ASTNode::renderPartial(const Value &Contexts, SmallString<0> &Output,
496522
ASTNode *Partial) {
497-
Partial->setUpContext(Allocator);
498523
Partial->render(Contexts, Output);
499524
addIndentation(Output, Indentation);
500525
}
@@ -506,8 +531,8 @@ void ASTNode::renderLambdas(const Value &Contexts, SmallString<0> &Output,
506531
toJsonString(LambdaResult, LambdaStr);
507532
Parser P = Parser(LambdaStr, *Allocator);
508533
ASTNode *LambdaNode = P.parse();
509-
LambdaNode->setUpNode(*Partials, *Lambdas, *SectionLambdas, *Escapes);
510-
LambdaNode->setUpContext(Allocator);
534+
LambdaNode->setUpNode(*Allocator, *Partials, *Lambdas, *SectionLambdas,
535+
*Escapes);
511536
LambdaNode->render(Contexts, Output);
512537
if (T == Variable)
513538
Output = escapeString(Output, *Escapes);
@@ -523,30 +548,24 @@ void ASTNode::renderSectionLambdas(const Value &Contexts,
523548
toJsonString(Return, LambdaStr);
524549
Parser P = Parser(LambdaStr, *Allocator);
525550
ASTNode *LambdaNode = P.parse();
526-
LambdaNode->setUpNode(*Partials, *Lambdas, *SectionLambdas, *Escapes);
527-
LambdaNode->setUpContext(Allocator);
551+
LambdaNode->setUpNode(*Allocator, *Partials, *Lambdas, *SectionLambdas,
552+
*Escapes);
528553
LambdaNode->render(Contexts, Output);
529554
return;
530555
}
531556

532-
void ASTNode::setUpNode(StringMap<ASTNode *> &Par, StringMap<Lambda> &L,
557+
void ASTNode::setUpNode(llvm::BumpPtrAllocator &Alloc,
558+
StringMap<ASTNode *> &Par, StringMap<Lambda> &L,
533559
StringMap<SectionLambda> &SC,
534560
DenseMap<char, StringRef> &E) {
535561
// Passed down datastructures needed for rendering to
536562
// the children nodes. This must be called before rendering
563+
Allocator = &Alloc;
537564
Partials = &Par;
538565
Lambdas = &L;
539566
SectionLambdas = &SC;
540567
Escapes = &E;
541568
for (ASTNode *Child : Children)
542-
Child->setUpNode(Par, L, SC, E);
569+
Child->setUpNode(Alloc, Par, L, SC, E);
543570
}
544571

545-
void ASTNode::setUpContext(llvm::BumpPtrAllocator *Alloc) {
546-
// Passed down the allocator to the children nodes.
547-
// Each render call requires a allocator for generating
548-
// Partial/Section nodes
549-
Allocator = Alloc;
550-
for (ASTNode *Child : Children)
551-
Child->setUpContext(Alloc);
552-
}

0 commit comments

Comments
 (0)