/// <summary> /// Invoked when a block is entered to create a new statements context /// which will received all subsequent statements. /// </summary> public void EnterBlock(ParseTreeNode tag) { _blocks.Push(CurrentBlock); CurrentBlock = new BlockContext(tag); }
/// <summary> /// Invoked when the end of a block has been reached. /// It resets the current statements context to the outer block. /// </summary> public void ExitBlock() { CurrentBlock = _blocks.Pop(); }
protected bool _isRaw; // true when the current block is raw public bool TryParse(StringSegment template, out IList <Statement> result, out IEnumerable <string> errors) { errors = Array.Empty <string>(); Parser parser = null; _currentContext = new BlockContext(null); _contexts = new Stack <BlockContext>(); result = _currentContext.Statements; try { int previous = 0, index = 0; Statement s; while (true) { previous = index; if (!MatchTag(template, index, out var start, out var end)) { index = template.Length; if (index != previous) { // Consume last Text statement ConsumeTextStatement(template, previous, index); } break; } else { if (parser == null) { parser = new Parser(_language); } if (start != previous) { // Consume current Text statement ConsumeTextStatement(template, previous, start); } var tag = template.Substring(start, end - start + 1); var tree = parser.Parse(tag); if (tree.HasErrors()) { errors = tree .ParserMessages .Select(x => $"{x.Message} at line:{x.Location.Line}, col:{x.Location.Column}") .ToArray(); return(false); } switch (tree.Root.Term.Name) { case "output": s = BuildOutputStatement(tree.Root); break; case "tag": s = BuildTagStatement(tree.Root); break; default: s = null; break; } if (s != null) { _currentContext.Statements.Add(s); } index = end + 1; } }