static bool IsOperator(PatternToken token) { if (token.Type != TokenType.Identifier) { return(false); } return(ops.ContainsKey(token.Value)); }
static bool IsFunction(PatternToken token) { if (token.Type != TokenType.Identifier) { return(false); } return(fns.ContainsKey(token.Value)); }
PatternToken ReadToken() { if (lookAhead == null) { throw UnexpectedEnd(); } PatternToken ret = lookAhead.Value; lookAhead = tokenizer.NextToken(); return(ret); }
Exception BadArgCount(PatternToken token, int expected) { throw new InvalidPatternException(string.Format("Invalid argument count for '{0}' at position {1}. Expected {2}", token.Value, token.Position, expected)); }
static bool IsOperator(PatternToken token) { if (token.Type != TokenType.Identifier) return false; return ops.ContainsKey(token.Value); }
static bool IsFunction(PatternToken token) { if (token.Type != TokenType.Identifier) return false; return fns.ContainsKey(token.Value); }
Exception UnknownToken(PatternToken token) { throw new InvalidPatternException(string.Format("Unknown token '{0}' at position {1}.", token.Value, token.Position)); }
Exception UnexpectedToken(PatternToken token, char expect) { throw new InvalidPatternException(string.Format("Unexpected token '{0}' at position {1}. Expected '{2}'.", token.Value, token.Position, expect)); }
PatternExpression ParseExpression(bool readBinOp = false) { PatternExpression ret; PatternToken token = ReadToken(); switch (token.Type) { case TokenType.Literal: ret = new LiteralExpression(token.Value); break; case TokenType.LParens: { ret = ParseExpression(true); PatternToken parens = ReadToken(); if (parens.Type != TokenType.RParens) { throw MismatchParens(token.Position.Value); } } break; case TokenType.Identifier: if (IsOperator(token)) { // unary operator PatternOperator op = ops[token.Value](); if (!op.IsUnary) { throw UnexpectedToken(token); } op.OperandA = ParseExpression(); ret = op; } else if (IsFunction(token)) { // function PatternFunction fn = fns[token.Value](); PatternToken parens = ReadToken(); if (parens.Type != TokenType.LParens) { throw UnexpectedToken(parens, '('); } fn.Arguments = new List <PatternExpression>(fn.ArgumentCount); for (int i = 0; i < fn.ArgumentCount; i++) { if (PeekToken() == null) { throw UnexpectedEnd(); } if (PeekToken().Value.Type == TokenType.RParens) { throw BadArgCount(token, fn.ArgumentCount); } if (i != 0) { PatternToken comma = ReadToken(); if (comma.Type != TokenType.Comma) { throw UnexpectedToken(comma, ','); } } fn.Arguments.Add(ParseExpression()); } parens = ReadToken(); if (parens.Type == TokenType.Comma) { throw BadArgCount(token, fn.ArgumentCount); } if (parens.Type != TokenType.RParens) { throw MismatchParens(parens.Position.Value); } ret = fn; } else { bool boolValue; if (bool.TryParse(token.Value, out boolValue)) { ret = new LiteralExpression(boolValue); } else { throw UnknownToken(token); } } break; default: throw UnexpectedToken(token); } if (!readBinOp) { return(ret); } // binary operator PatternToken?peek = PeekToken(); while (peek != null) { if (peek.Value.Type != TokenType.Identifier) { break; } if (!IsOperator(peek.Value)) { break; } PatternToken binOpToken = ReadToken(); PatternOperator binOp = ops[binOpToken.Value](); if (binOp.IsUnary) { throw UnexpectedToken(binOpToken); } binOp.OperandA = ret; binOp.OperandB = ParseExpression(); ret = binOp; peek = PeekToken(); } return(ret); }