public Expression ParseExpression(int precedence = 0) { var token = Take(); IPrefixParselet prefix; IInfixParselet infix; if (!PrefixParselets.TryGetValue(token.ID, out prefix)) { throw new RantException(_src, token, "Invalid expression '\{token.Value}'."); } var left = prefix.Parse(this, token); // Break when the next token's precedence is less than or equal to the current precedence // This will assure that higher precedence operations like multiplication are parsed before lower operations. while (GetPrecedence() > precedence) { token = Take(); if (!InfixParselets.TryGetValue(token.ID, out infix)) { throw new RantException(_src, token, "Invalid operator '\{token.Value}'."); } // Replace the left expression with the next parsed expression. left = infix.Parse(this, left, token); } return(left); }
/// <summary> /// Registers a token type to a new BinaryOperatorParselet /// </summary> /// <param name="opToken">Token type to register</param> /// <param name="precedence">Precedence of operator</param> /// <param name="rightAssociative">If the operator is right-associative or not</param> public static void RegisterBinaryOperator(TokenType opToken, Precedence precedence, bool rightAssociative = false) { Logger.Log(LogLevel.Debug, Logger.REGISTRY, "Registering binary operator parselet for token " + opToken.ToString()); InfixParselets.Add(opToken, new BinaryOperatorParselet(precedence, rightAssociative)); }
/// <summary> /// Gets the infix parselet registered to the token type /// </summary> /// <param name="tokenClass">Token type to check</param> /// <returns>Parselet the token type is registered to</returns> public static IInfixParselet GetInfix(TokenType tokenClass) { if (InfixParselets.ContainsKey(tokenClass)) { return(InfixParselets[tokenClass]); } return(null); }
/// <summary> /// Returns the precedence of the next infix operator, or 0 if there is none. /// </summary> /// <returns></returns> private int GetPrecedence() { if (_pos == _tokens.Length) { return(0); } IInfixParselet infix; InfixParselets.TryGetValue(Peek().ID, out infix); return(infix?.Precedence ?? 0); }
/// <summary> /// Registers a token type to a new PostfixOperatorParselet /// </summary> /// <param name="opToken">Token type to register</param> public static void RegisterPostfixOperator(TokenType opToken) { Logger.Log(LogLevel.Debug, Logger.REGISTRY, "Registering postfix operator parselet for token " + opToken.ToString()); InfixParselets.Add(opToken, new PostfixOperatorParselet(Precedence.POSTFIX)); }
/// <summary> /// Registers a token type to an infix parselet /// </summary> /// <param name="token">Token type to register</param> /// <param name="parselet">Parselet to register to</param> public static void RegisterInfix(TokenType token, IInfixParselet parselet) { Logger.Log(LogLevel.Debug, Logger.REGISTRY, "Registering infix/postfix operator parselet for token " + token.ToString()); InfixParselets.Add(token, parselet); }