public ParserIssue[] TryParse(string text, out IContentExpression result) { if (text == null) { throw new ArgumentNullException(nameof(text)); } result = null; var tokens = _tokenizer.Tokenize(text); try { var q = new Queue <DslToken>(tokens); result = ParseExpression(q, t => false); return(new ParserIssue[] { }); } catch (ParserException ex) { return(new ParserIssue[] { new ParserIssue { CodeOrMessage = ex.Message, Index = ex.Token?.Match.StartIndex ?? (text.Length - 1), Value = ex.Token?.Value } }); } }
void Test(string text, IContentExpression expected) { var parser = new ContentExpressionParser(new Tokenizer()); var issues = parser.TryParse(text, out IContentExpression actual); Assert.AreEqual(expected, actual); }
public RegexFilter(IContentExpression value, string regex) { if (regex == null) { throw new ArgumentNullException(nameof(regex)); } Value = value ?? throw new ArgumentNullException(nameof(value)); Regex = new Regex(regex, RegexOptions.Compiled); }
public EqualToFilter(IContentExpression left, IContentExpression right) { Left = left ?? throw new ArgumentNullException(nameof(left)); Right = right ?? throw new ArgumentNullException(nameof(right)); }
public OfTypeFilter(IContentExpression value, ContentType contentType) { Value = value ?? throw new ArgumentNullException(nameof(value)); ContentType = contentType; }
IContentExpression ParseExpression(Queue <DslToken> q, Func <DslToken, bool> terminate) { IContentExpression exp = null; while (q.Count > 0) { var lookAhead = q.Peek(); if (terminate(lookAhead)) { break; } else if (lookAhead.IsConstant()) { if (exp != null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(Utils.ConstantTokens); exp = CreateConstant(token); } else if (lookAhead.TokenType == TokenType.Equals) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.Equals); exp = new EqualToFilter(exp, ParseExpression(q, t => t.TokenType == TokenType.And || t.TokenType == TokenType.Or || terminate(t))); } else if (lookAhead.TokenType == TokenType.Contains) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.Contains); exp = new ContainsFilter(exp, ParseExpression(q, t => t.TokenType == TokenType.And || t.TokenType == TokenType.Or || terminate(t))); } else if (lookAhead.TokenType == TokenType.MatchRegex) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.MatchRegex); var pattern = q.DequeueAndValidate(TokenType.String); exp = new RegexFilter(exp, pattern.Value); } else if (lookAhead.TokenType == TokenType.And) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.And); if (exp is IContentFilter leftBool) { var right = ParseExpression(q, terminate); if (right is IContentFilter rightBool) { exp = new AndFilter(leftBool, rightBool); } else { throw new ParserException("AND cannot have a right operand that does not yield boolean", token); } } else { throw new ParserException("AND cannot have a left operand that does not yield boolean", token); } } else if (lookAhead.TokenType == TokenType.Or) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.Or); if (exp is IContentFilter leftBool) { var right = ParseExpression(q, terminate); if (right is IContentFilter rightBool) { exp = new OrFilter(leftBool, rightBool); } else { throw new ParserException("OR cannot have a right operand that does not yield boolean", token); } } else { throw new ParserException("OR cannot have a left operand that does not yield boolean", token); } } else if (lookAhead.TokenType == TokenType.Path) { if (exp == null) { throw new ParserException($"Unexpected token", lookAhead); } var token = q.DequeueAndValidate(TokenType.Path); exp = new PathExpression(exp, ContentPath.Parse($"$.{token.Value.TrimStart('.')}")); } else if (lookAhead.TokenType == TokenType.DollarSign) { if (exp != null) { throw new ParserException($"Unexpected token", lookAhead); } q.DequeueAndValidate(TokenType.DollarSign); exp = new ScopeRootExpression(); } else if (lookAhead.TokenType == TokenType.OpenCurly) { if (exp != null) { throw new ParserException($"Unexpected token", lookAhead); } exp = CreateObjectExpression(q); } else if (lookAhead.TokenType == TokenType.OpenSquareBracket) { if (exp != null) { throw new ParserException($"Unexpected token", lookAhead); } exp = CreateListExpression(q); } else if (lookAhead.TokenType == TokenType.OpenBracket) { if (exp != null) { throw new ParserException($"Unexpected token", lookAhead); } q.DequeueAndValidate(TokenType.OpenBracket); // open bracket ( exp = ParseExpression(q, t => t.TokenType == TokenType.CloseBracket); q.DequeueAndValidate(TokenType.CloseBracket); // close bracket ) } else { throw new ParserException($"Unexpected token", lookAhead); } } if (exp == null) { throw new ParserException($"Unexpected end", null); } return(exp); }
public ContainsWhereFilter(IContentExpression list, IContentFilter item) { List = list ?? throw new ArgumentNullException(nameof(list)); ItemFilter = item ?? throw new ArgumentNullException(nameof(item)); }