Created
September 23, 2019 20:36
-
-
Save elfalem/b7befb7a91ddb5ba0f12d8a156b54179 to your computer and use it in GitHub Desktop.
Alternative view engine for ASP.NET Core: Parsing template syntax
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using Superpower; | |
using Superpower.Parsers; | |
using Superpower.Tokenizers; | |
namespace foo.Stache | |
{ | |
public enum Tokens | |
{ | |
String, | |
OpenBraces, | |
CloseBraces | |
} | |
public abstract class ParseNode | |
{ | |
} | |
public class TextNode : ParseNode | |
{ | |
public string Value { get; set; } | |
} | |
public class ExpressionNode : ParseNode | |
{ | |
public string Value { get; set; } | |
} | |
public class DocumentNode : ParseNode | |
{ | |
public List<ParseNode> Nodes { get; set; } | |
} | |
public class StacheParser | |
{ | |
public static Tokenizer<Tokens> Tokenizer = new TokenizerBuilder<Tokens>() | |
.Match(Span.EqualTo("{{"), Tokens.OpenBraces) | |
.Match(Span.EqualTo("}}"), Tokens.CloseBraces) | |
// Note: the following ignores single braces, e.g. it would fail on {{foo{bar}} | |
.Match(Span.MatchedBy(Character.ExceptIn('{','}')).Many(), Tokens.String) | |
.Build(); | |
private readonly static TokenListParser<Tokens, ParseNode> ExpressionParser = | |
from ob in Token.EqualTo(Tokens.OpenBraces) | |
from str in Token.EqualTo(Tokens.String) | |
from cb in Token.EqualTo(Tokens.CloseBraces) | |
select (ParseNode)new ExpressionNode { | |
Value = str.ToStringValue() | |
}; | |
private readonly static TokenListParser<Tokens, ParseNode> LiteralParser = | |
from str in Token.EqualTo(Tokens.String) | |
select (ParseNode)new TextNode { | |
Value = str.ToStringValue() | |
}; | |
public readonly static TokenListParser<Tokens, ParseNode> MainParser = | |
from nodes in ExpressionParser.Or(LiteralParser).Many() | |
select (ParseNode)new DocumentNode { | |
Nodes = nodes.ToList() | |
}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc.Rendering; | |
using Microsoft.AspNetCore.Mvc.ViewEngines; | |
using Superpower; | |
namespace foo.Stache{ | |
public class StacheView : IView | |
{ | |
public StacheView(string path){ | |
Path = path; | |
} | |
public string Path {get; private set;} | |
public Task RenderAsync(ViewContext context) | |
{ | |
var template = File.ReadAllText(Path); | |
var tokens = StacheParser.Tokenizer.Tokenize(template); | |
var parsedResult = StacheParser.MainParser.TryParse(tokens); | |
var processedOutput = new StringBuilder(); | |
if(parsedResult.HasValue){ | |
var document = (DocumentNode)parsedResult.Value; | |
foreach(var node in document.Nodes){ | |
switch(node){ | |
case TextNode textNode: | |
processedOutput.Append(textNode.Value); | |
break; | |
case ExpressionNode expNode: | |
processedOutput.Append(context.ViewData[expNode.Value]?.ToString()); | |
break; | |
} | |
} | |
}else{ | |
throw new Exception(parsedResult.ErrorMessage); | |
} | |
return context.Writer.WriteAsync(processedOutput.ToString()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment