public static TemplateExpression Parse(ExpressionWalker ew) { ew.IsCurrentOrThrow(ExpressionToken.Template); ew.NextOrThrow(); // ReSharper disable once UseObjectOrCollectionInitializer var ret = new TemplateExpression(); ew.IsCurrentOrThrow(ExpressionToken.StringLiteral); ret._matchPath = new RegexResult[] { ew.Current.Match.AsResult() }; ret.Path = ew.Current.Match.Value.StartsWith("\"") ? ew.Current.Match.Value.Substring(1, ew.Current.Match.Length - 2) : ew.Current.Match.Value; ret._matchForEvery = ew.Next(ExpressionToken.ForEvery, true).Match.AsResult(); ew.NextOrThrow(); ret.Arguments = ArgumentsExpression.Parse(ew, token => token.Token == ExpressionToken.NewLine || token.Token == ExpressionToken.Mod, false, typeof(ForeachExpression)); return(ret); }
public static ArgumentsExpression Parse(ExpressionWalker ew, ExpressionToken left, ExpressionToken right, bool argsOptional, Type caller = null) { var args = new ArgumentsExpression(); ew.IsCurrentOrThrow(left); ew.NextOrThrow(); var exprs = new List <Expression>(); while (ew.Current.Token != right && ew.HasNext) { if (ew.Current.Token == ExpressionToken.Comma) { if (ew.HasBack && ew.PeakBack.Token == ExpressionToken.Comma) { exprs.Add(NullIdentity.Instance); } ew.NextOrThrow(); continue; } var expression = ParseExpression(ew, caller); if (ew.IsCurrent(ExpressionToken.Colon)) { //handle keyvalue item exprs.Add(KeyValueExpression.Parse(ew, expression, caller)); } else { exprs.Add(expression); } } if (exprs.Count == 0 && !argsOptional) { throw new UnexpectedTokenException($"Was expecting an expression between {left} and {right}"); } ew.Next(); args.Arguments = exprs.ToArray(); return(args); }
public static GroupExpression Parse(ExpressionWalker ew, ExpressionToken left, ExpressionToken right) { var grp = new GroupExpression() { _matchLeft = AttributeExtensions.GetAttribute <ExpressionTokenAttribute>(left).Emit.AsResult(), _matchRight = AttributeExtensions.GetAttribute <ExpressionTokenAttribute>(right).Emit.AsResult() }; ew.IsCurrentOrThrow(left); ew.NextOrThrow(); if (ew.Current.Token == right) { throw new UnexpectedTokenException($"Expected an expression, found end of group of type {right}"); } grp.InnerExpression = ParseExpression(ew); ew.IsCurrentOrThrow(right); ew.Next(); return(grp); }
public static ArgumentsExpression Parse(ExpressionWalker ew, Func <TokenMatch, bool> parseTill, bool argsOptional, Type caller = null) { var args = new ArgumentsExpression(); var exprs = new List <Expression>(); while (!parseTill(ew.Current) && ew.HasNext) { if (ew.Current.Token == ExpressionToken.Comma) { if (ew.HasBack && ew.PeakBack.Token == ExpressionToken.Comma) { exprs.Add(NullIdentity.Instance); } ew.NextOrThrow(); continue; } var expression = ParseExpression(ew, caller); if (ew.IsCurrent(ExpressionToken.Colon)) { //handle keyvalue item exprs.Add(KeyValueExpression.Parse(ew, expression)); } else { exprs.Add(expression); } } if (exprs.Count == 0 && !argsOptional) { throw new UnexpectedTokenException($"Was expecting arguments but found none while argsOptional is false"); } ew.Next(); args.Arguments = exprs.ToArray(); return(args); }
public static ParserAction Parse(ExpressionWalker ew, string code, LineBuilder output) { // multiline: // %foreach expr% // code #1 // % // singleline: // %foreach expr // code #1 ew.IsCurrentOrThrow(ExpressionToken.Foreach); ew.NextOrThrow(); //parse the arguments for the foreach var args = ArgumentsExpression.Parse(ew, token => token.Token == ExpressionToken.NewLine || token.Token == ExpressionToken.Mod, false, typeof(ForeachExpression)); //ew.Back(); //agrumentsExpression skips the closer token and we need it to identify if this is a singleline or multiline if (output == null) { output = new LineBuilder(code); } string content; var relatedLines = new List <Line>(); relatedLines.AddRange(output.GetLinesRelated(args.Matches())); if (ew.PeakBack.Token == ExpressionToken.Mod) { //the content is % to % block var leftBorder = ew.Current.Match; var nextMod = ForeachExpression.FindCloser(leftBorder.Index, code); //handle implicit end block (when % is not existing) if (nextMod == -1) { nextMod = code.Length - 1; } ew.SkipForwardWhile(token => token.Match.Index < nextMod); ew.Next(); //skip % itself var l1 = output.GetLineAt(leftBorder.Index) ?? output.Lines.First(); relatedLines.AddRange(new Range(l1.LineNumber, output.GetLineAt(nextMod).LineNumber).EnumerateIndexes().Select(output.GetLineByLineNumber)); content = null; } else { //the content is only next line var leftMod = ew.Current.Match; var nextMod = code.IndexOf('\n', leftMod.Index); relatedLines.Add(output.GetLineByLineNumber(relatedLines.Last().LineNumber + 1)); //next line. content = code.Substring(leftMod.Index, nextMod == -1 ? (code.Length - leftMod.Index) : nextMod - leftMod.Index); } relatedLines = relatedLines.Distinct().OrderBy(l => l.StartIndex).ToList(); if (relatedLines.Count(l => l.Content.Contains("%foreach")) <= relatedLines.Count(l => l.CleanContent() == "%") && relatedLines.Last().CleanContent() == "%") { relatedLines[relatedLines.Count - 1].MarkedForDeletion = true; relatedLines.RemoveAt(relatedLines.Count - 1); } //make sure to clean out % at the end if (content == null) { content = relatedLines.Select(l => l.Content).StringJoin(); } //all lines of the foreach are destined to deletion foreach (var line in relatedLines) { line.MarkedForDeletion = true; } return(new ParserAction(ParserToken.ForeachLoop, relatedLines, new ForeachExpression() { Content = content, Arguments = args })); }
public static IdentityExpression Parse(ExpressionWalker ew, Type caller = null, Expression left = null) { var ret = new IdentityExpression(); //types: //justname //justname.accessor //justname.accessor[5].second //justname.method().someval //justname.method().someval[3].thatsfar if (left == null) { ew.IsCurrentOrThrow(ExpressionToken.Literal); } if (ew.HasNext && ew.PeakNext.WhitespacesAfterMatch == 0 && ew.PeakNext.Token == ExpressionToken.Period && caller != typeof(IdentityExpression) || left != null) { var first = left ?? ParseExpression(ew, typeof(IdentityExpression)); ew.NextOrThrow(); //skip the predicted period. var next = ew.PeakNext; switch (next.Token) { //currently we are at Literal case ExpressionToken.Period: ret.Identity = new PropertyIdentity(first, Parse(ew)); return(ret); case ExpressionToken.LeftBracet: ret.Identity = new PropertyIdentity(first, IndexerCallExpression.Parse(ew)); return(ret); case ExpressionToken.LeftParen: ret.Identity = new PropertyIdentity(first, CallExpression.Parse(ew)); return(ret); default: if (left != null) { return(new IdentityExpression(new PropertyIdentity(left, Parse(ew, typeof(IdentityExpression), null)))); } if (first != null) { //just a plain single word! var right = new IdentityExpression(); if (ew.IsCurrent(ExpressionToken.Null)) { right.Identity = NullIdentity.Instance; } else { ew.IsCurrentOrThrow(ExpressionToken.Literal); right.Identity = StringIdentity.Create(ew.Current.Match); } ew.Next(); return(new IdentityExpression(new PropertyIdentity(first, right))); } goto _plain_identity; } } _plain_identity: //just a plain single word! if (ew.IsCurrent(ExpressionToken.Null)) { ret.Identity = NullIdentity.Instance; } else { ew.IsCurrentOrThrow(ExpressionToken.Literal); ret.Identity = StringIdentity.Create(ew.Current.Match); } ew.Next(); return(ret); }
public static Expression Parse(ExpressionWalker ew) { ew.IsCurrentOrThrow(ExpressionToken.Null); ew.Next(); return(new IdentityExpression(Instance)); }