/// <summary> /// Genera un nuevo token y avanza. /// </summary> public Token Emit(TokenType t) { var token = new Token(t, this.Start, this.Input.Substring(this.Start, this.Pos - this.Start)); this.Tokens.Add(token); this.Start = this.Pos; if(Template.Debug) { Console.WriteLine("{0}. {1} -> {2}", this.Tokens.IndexOf(token), token.Type, token.Value); } return token; }
static IRenderizable ParseIf (Token currentToken, List<Token> tokens, ref int index, Template mainTemplate) { var ifCondition = new IfCondition(); if(tokens.Count <= index) { throw new TemplateException(string.Format("Invalid if condition at: {0}", currentToken.Position)); } var condition = tokens[index]; if(condition.Type == TokenType.Parameter) { ifCondition.ModelKey = condition.Value; } else { var function = ParseFunction(condition, tokens, ref index, null) as Function; if(function == null) { throw new TemplateException(string.Format("Invalid if condition at: {0}", currentToken.Position)); } ifCondition.Expression = function; } index++; ifCondition.Body = Parse(mainTemplate, tokens, ref index); // Parsear el else si existe if(tokens.Count >= index && tokens[index].Value == "else") { index++; ifCondition.ElseBody = Parse(mainTemplate, tokens, ref index); } return ifCondition; }
/// <summary> /// Parses the foreach. El formato es {{ foreach .posts -> post[, i] }} /// Donde .posts es el IEnumerable que se itera, post es cada elemento en la iteración y i es el índice opcional. /// </summary> static IRenderizable ParseForeach (Token currentToken, List<Token> tokens, ref int index, Template mainTemplate) { var item = new Foreach (); if (tokens.Count <= index) { throw new TemplateException(string.Format("Invalid foreach at: {0}", currentToken.Position)); } // Parsear el nombre del elemento de la iteración var nextToken = tokens [index]; if (nextToken.Type != TokenType.Parameter) { throw new TemplateException(string.Format("Invalid if foreach at: {0}. Iterate name not found", currentToken.Position)); } item.IterateKey = nextToken.Value.Trim(argumentSeparators); index++; // si hay una coma para separar, ignorarla nextToken = tokens [index]; if (nextToken.Type == TokenType.Parameter && nextToken.Value.Trim() == ",") { index++; nextToken = tokens [index]; } // Parsear el indice de la iteración (es opcional) if (nextToken.Type == TokenType.Parameter && nextToken.Value.Trim() != "in") { item.IndexKey = nextToken.Value.Trim(argumentSeparators); index++; } // Parsear el separador "in" nextToken = tokens [index]; if (nextToken.Type != TokenType.Parameter && nextToken.Value.Trim() != "in") { throw new TemplateException(string.Format("Invalid if foreach at: {0}. Iterate separator 'in' not found", currentToken.Position)); } index++; nextToken = tokens [index]; if (nextToken.Type != TokenType.Parameter) { throw new TemplateException(string.Format("Invalid foreach at: {0}. Model not found", currentToken.Position)); } item.ModelKey = nextToken.Value.Trim (); index++; item.Body = Parse(mainTemplate, tokens, ref index); return item; }
static IRenderizable ParseBlock(Token currentToken, List<Token> tokens, ref int index, Template mainTemplate) { var item = new TemplateBlock(); var nextToken = tokens [index]; if (nextToken.Type != TokenType.Parameter) { throw new TemplateException(string.Format("Invalid include at: {0}. Name not specified", currentToken.Position)); } item.Path = nextToken.Value.Trim(); item.MainTemplate = mainTemplate; item.Body = Parse(mainTemplate, tokens, ref index); return item; }
static IRenderizable ParseInclude(Token currentToken, List<Token> tokens, ref int index, Template mainTemplate) { var item = new Include(); if (tokens.Count <= index) { throw new TemplateException(string.Format("Invalid include at: {0}", currentToken.Position)); } var nextToken = tokens [index]; if (nextToken.Type != TokenType.Parameter) { throw new TemplateException(string.Format("Invalid include at: {0}. Name not specified", currentToken.Position)); } item.Path = nextToken.Value.Trim(); item.MainTemplate = mainTemplate; // añadir la clave como referenciada. mainTemplate.Templates[item.Path] = null; return item; }
static IRenderizable ParseFunction(Token currentToken, IList<Token> tokens, ref int index, Template mainTemplate) { var function = new Function(); function.Name = currentToken.Value.Trim(); function.Arguments = new List<string>(); while(tokens.Count > index + 1) { var nextToken = tokens [index + 1]; if(nextToken.Type != TokenType.Parameter) { break; } index++; var tokenValue = nextToken.Value; // si hay una coma para separar, ignorarla if (nextToken.Type == TokenType.Parameter && tokenValue.Trim() == ",") { index++; nextToken = tokens[index]; tokenValue = nextToken.Value; } tokenValue = tokenValue.Trim(argumentSeparators).Trim('"'); // añadir el argumento. Como pueden ir separados por comas, eliminarla. function.Arguments.Add(tokenValue); // En caso de que extienda a otra, el argumento es la ruta. if(function.Name == "extends") { mainTemplate.BaseTemplate = tokenValue; // añadir la clave como referenciada. mainTemplate.Templates[tokenValue] = null; } } return function; }