-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTemplateParser.cs
134 lines (120 loc) · 5.3 KB
/
TemplateParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Collections.Generic;
public class TemplateParser
{
public List<TemplateToken> toks;
public int tokIdx = -1;
public TemplateToken currentTok;
public List<Node> nodes = new List<Node>(){};
public TemplateParser(List<TemplateToken> tokens)
{
toks = tokens;
this.Advance();
}
public void Advance()
{
tokIdx += 1;
currentTok = tokIdx < toks.Count ? toks[tokIdx] : TemplateToken.EOFToken();
}
public List<Node> Parse()
{
while(currentTok.tokType != TemplateTokenType.EOF)
{
nodes.Add(this.ParseToken());
}
return nodes;
}
private Node ParseToken()
{
if(currentTok.tokType == TemplateTokenType.Render) return this.ParseRenderToken();
else if (currentTok.tokType == TemplateTokenType.Extends) return this.ParseExtends();
else if (currentTok.tokType == TemplateTokenType.ForCue) return this.ParseForLoop();
else if (currentTok.tokType == TemplateTokenType.IfCue) return this.ParseIfChain();
else if (currentTok.tokType == TemplateTokenType.BlockCue) return this.ParseBlock();
throw new InvalidSyntaxError(currentTok.posStart, currentTok.posEnd, string.Format("Expected either an expression or a statement cue got {0}", currentTok.tokType.ToString()));
}
private Node ParseRenderToken()
{
var node = currentTok.GetRenderNode();
this.Advance();
return new RenderNode(node, node.posStart, node.posEnd);
}
private Node ParseExtends()
{
var givenTok = currentTok;
var extension = currentTok.GetExtendsStrng();
this.Advance();
return new ExtendsNode(extension, givenTok.posStart, givenTok.posEnd);
}
private Node ParseBlock()
{
var blockName = currentTok.GetBlockString();
var posStart = currentTok.posStart;
this.Advance();
var currentNodes = new List<Node>();
while(currentTok.tokType != TemplateTokenType.EndBlockCue && currentTok.tokType != TemplateTokenType.EOF)
{
var currentNode = this.ParseToken();
currentNodes.Add(currentNode);
}
if(currentTok.tokType != TemplateTokenType.EndBlockCue) throw new InvalidSyntaxError(posStart, currentTok.posEnd.Copy(), "Expected an endfor cue");
this.Advance();
return new BlockNode(blockName, currentNodes, posStart, currentTok.posEnd);
}
private Node ParseForLoop()
{
var forLoopContent = currentTok.GetForCueContent();
var ident = forLoopContent.Item1;
var iter = forLoopContent.Item2;
var posStart = currentTok.posStart;
this.Advance();
var currentNodes = new List<Node>();
while(currentTok.tokType != TemplateTokenType.EndForCue && currentTok.tokType != TemplateTokenType.EOF)
{
var currentNode = this.ParseToken();
currentNodes.Add(currentNode);
}
if(currentTok.tokType != TemplateTokenType.EndForCue) throw new InvalidSyntaxError(posStart, currentTok.posEnd.Copy(), "Expected an endfor cue");
this.Advance();
return new ForNode(ident, iter, currentNodes, posStart, currentTok.posEnd);
}
private Node ParseIfChain()
{
var firstCond = currentTok.GetIfCueCond();
var nodes = new List<Tuple<Node, List<Node>>>();
var firstNodes = new List<Node>();
var elseCase = new List<Node>();
var posStart = currentTok.posStart;
this.Advance();
while(
currentTok.tokType != TemplateTokenType.ElifCue
&& currentTok.tokType != TemplateTokenType.ElseCue
&& currentTok.tokType != TemplateTokenType.EndIfCue
&& currentTok.tokType != TemplateTokenType.EOF
) firstNodes.Add(this.ParseToken());
if (currentTok.tokType == TemplateTokenType.EOF) throw new InvalidSyntaxError(posStart, currentTok.posEnd.Copy(), "Expected elif or an endif cue");
nodes.Add(Tuple.Create<Node, List<Node>>(firstCond, firstNodes));
while (currentTok.tokType == TemplateTokenType.ElifCue)
{
var currentNodes = new List<Node>();
var cond = currentTok.GetElifCueCond();
this.Advance();
while (
currentTok.tokType != TemplateTokenType.ElifCue
&& currentTok.tokType != TemplateTokenType.EndIfCue
&& currentTok.tokType != TemplateTokenType.EOF
&& currentTok.tokType != TemplateTokenType.ElseCue
) currentNodes.Add(this.ParseToken());
if (currentTok.tokType == TemplateTokenType.EOF) throw new InvalidSyntaxError(posStart, currentTok.posEnd.Copy(), "Expected elif or an endif cue");
nodes.Add(Tuple.Create<Node, List<Node>>(cond, currentNodes));
}
if(currentTok.tokType == TemplateTokenType.ElseCue)
{
this.Advance();
while (currentTok.tokType != TemplateTokenType.EndIfCue && currentTok.tokType != TemplateTokenType.EndIfCue) elseCase.Add(this.ParseToken());
}
if (currentTok.tokType != TemplateTokenType.EndIfCue) throw new InvalidSyntaxError(posStart, currentTok.posEnd.Copy(), "Expected an endif cue");
this.Advance();
return new IfNode(nodes, elseCase, posStart, currentTok.posEnd.Copy());
}
}