private IArmString ParseFullExpression(ref ArmExpressionTokenizer tokenizer) { Expect(ref tokenizer, ArmExpressionTokenType.OpenBracket); IArmString wholeExpression = ParseInnerExpression(ref tokenizer, noLiteral: true); Expect(ref tokenizer, ArmExpressionTokenType.CloseBracket); Expect(ref tokenizer, ArmExpressionTokenType.EOF); return(wholeExpression); }
private ArmExpressionToken Expect(ref ArmExpressionTokenizer tokenizer, ArmExpressionTokenType expectedTokenType) { ArmExpressionToken token = tokenizer.NextToken(); if (token.Type != expectedTokenType) { throw Error($"Expected token of type '{expectedTokenType}' but instead got '{token}' at index {tokenizer.PreviousIndex} in input '{tokenizer.Input}'"); } return(token); }
private ArmOperation ParseIdentifierExpression(ref ArmExpressionTokenizer tokenizer, ArmExpressionIdentifierToken identifier) { ArmExpressionToken token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.OpenParen: ArmOperation expression = ParseCallExpression(ref tokenizer, identifier); return(ParseDotExpression(ref tokenizer, expression)); default: throw Error($"Expected a token of type '{ArmExpressionTokenType.OpenParen}' but instead got '{token}' in '{tokenizer.Input}' at index '{tokenizer.PreviousIndex}'"); } }
private IArmString ParseInnerExpression(ref ArmExpressionTokenizer tokenizer, bool noLiteral = false) { ArmExpressionToken token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.String: if (noLiteral) { throw Error($"Expected a literal token but found a string in '{tokenizer.Input}' at index {tokenizer.PreviousIndex}"); } return(new ArmStringLiteral(token.CoerceToString())); case ArmExpressionTokenType.Identifier: return(ParseIdentifierExpression(ref tokenizer, (ArmExpressionIdentifierToken)token)); default: throw Error($"Expected an expression token but found '{token}' in '{tokenizer.Input}' at index {tokenizer.PreviousIndex}"); } }
private ArmOperation ParseDotExpression(ref ArmExpressionTokenizer tokenizer, ArmOperation lhs) { ArmExpressionToken token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.Dot: token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.Identifier: return(ParseDotExpression(ref tokenizer, new ArmMemberAccessExpression(lhs, new ArmStringLiteral(((ArmExpressionIdentifierToken)token).Identifier)))); default: throw Error($"Expected token of type '{ArmExpressionTokenType.Identifier}' after '.' but instead got '{token}' at index {tokenizer.PreviousIndex} in input '{tokenizer.Input}'"); } default: tokenizer.UngetToken(token); return(lhs); } }
private ArmOperation ParseCallExpression(ref ArmExpressionTokenizer tokenizer, ArmExpressionIdentifierToken identifier) { var arguments = new List <ArmExpression>(); ArmExpressionToken token; bool sawCloseParen = false; while (!sawCloseParen) { token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.Identifier: arguments.Add(ParseIdentifierExpression(ref tokenizer, (ArmExpressionIdentifierToken)token)); break; case ArmExpressionTokenType.String: arguments.Add(new ArmStringLiteral(token.CoerceToString())); break; case ArmExpressionTokenType.Integer: arguments.Add(new ArmIntegerLiteral(token.CoerceToLong())); break; case ArmExpressionTokenType.Boolean: arguments.Add(ArmBooleanLiteral.FromBool(token.CoerceToBool())); break; case ArmExpressionTokenType.CloseParen: if (arguments.Count == 0) { sawCloseParen = true; continue; } goto default; default: throw Error($"Expected an expression but instead got '{token}' in input '{tokenizer.Input}' at index {tokenizer.PreviousIndex}"); } token = tokenizer.NextToken(); switch (token.Type) { case ArmExpressionTokenType.Comma: break; case ArmExpressionTokenType.CloseParen: sawCloseParen = true; break; default: throw Error($"Expected an expression delimiter but instead got '{token}' in input '{tokenizer.Input}' at index {tokenizer.PreviousIndex}"); } } if (identifier.Identifier.Is(ParametersFunction)) { return(new ArmParameterReferenceExpression((IArmString)arguments[0])); } if (identifier.Identifier.Is(VariablesFunction)) { return(new ArmVariableReferenceExpression((IArmString)arguments[0])); } return(new ArmFunctionCallExpression(new ArmStringLiteral(identifier.Identifier), arguments.ToArray())); }
private IArmString ParseWithTokenizer(string s) { var tokenizer = new ArmExpressionTokenizer(s); return(ParseFullExpression(ref tokenizer)); }