/// <summary> /// Recursive exp /// </summary> /// <param name="expressions">Expressions</param> /// <param name="lastToken">Last token</param> /// <param name="pLevel">Parenthesis level</param> /// <param name="actualBlock">Actual block</param> /// <returns>New expressions</returns> List<IExpression> RecursiveExp(List<IExpression> expressions, Token lastToken, int pLevel, Block actualBlock) { if (pLevel < 0 || !HasNextToken()) return expressions; Token actualToken = Peek(); bool restart = true; switch (lastToken.Type) { case TokenType.IDENTIFIER: switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: case TokenType.DOT: case TokenType.CLOSEPAREN: actualToken = Pop(); expressions.Add(new VariableExpression(lastToken.Value, actualBlock)); break; case TokenType.OPENPAREN: actualToken = Pop(); List<List<IExpression>> exps = new List<List<IExpression>>(); while (!Match(TokenType.CLOSEPAREN)) { exps.Add(Exp(actualBlock)); if (Match(TokenType.CLOSEPAREN)) break; else if (!Match(TokenType.COMMA)) Logger.Error("Parameter need to be separated with a comma"); Pop(); // Pop the comma } expressions.Add(new MethodCallExpression(lastToken.Value, actualBlock, exps)); break; default: expressions.Add(new VariableExpression(lastToken.Value, actualBlock)); restart = false; break; } break; case TokenType.NEW: switch (actualToken.Type) { case TokenType.IDENTIFIER: Token customTypeToken = Pop(); List<List<IExpression>> exps = new List<List<IExpression>>(); if (Match(TokenType.OPENPAREN)) { Pop(); // Pop the parenthesis while (!Match(TokenType.CLOSEPAREN)) { exps.Add(Exp(actualBlock)); if (Match(TokenType.COMMA)) { Pop(); // Pop the comma continue; } else break; } } else Logger.Error("You need to open parenthesis after object instantation."); if (!Match(TokenType.CLOSEPAREN)) Logger.Error("You need to close parenthesis after put parameters"); actualToken = Pop(); // Pop the parenthesis expressions.Add(new ConstructorExpression(customTypeToken.Value, actualBlock, exps)); break; default: restart = false; break; } break; case TokenType.DOT: switch (actualToken.Type) { case TokenType.IDENTIFIER: case TokenType.CLOSEPAREN: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.COMMA: restart = false; break; case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: switch (actualToken.Type) { case TokenType.IDENTIFIER: case TokenType.PLUS: case TokenType.MINUS: case TokenType.INTLITERAL: case TokenType.FLOATLITERAL: case TokenType.STRINGLITERAL: case TokenType.EXMARK: case TokenType.OPENPAREN: actualToken = Pop(); expressions.Add(new OperatorExpression(lastToken.Type)); break; default: restart = false; break; } break; case TokenType.STRINGLITERAL: expressions.Add(new Value(VariableType.STRING, lastToken.Value)); switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.BOOLLITERAL: expressions.Add(new Value(VariableType.BOOL, lastToken.Value == Language.Keywords["true"] ? true : false)); switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.INTLITERAL: expressions.Add(new Value(VariableType.INT, Convert.ToInt32(lastToken.Value))); switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: case TokenType.CLOSEPAREN: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.FLOATLITERAL: expressions.Add(new Value(VariableType.FLOAT, Conv.StringToFloat(lastToken.Value))); switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: case TokenType.CLOSEPAREN: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.EXMARK: switch (actualToken.Type) { case TokenType.IDENTIFIER: case TokenType.BOOLLITERAL: case TokenType.OPENPAREN: actualToken = Pop(); expressions.Add(new OperatorExpression(lastToken.Type)); break; default: restart = false; break; } break; case TokenType.OPENPAREN: pLevel++; expressions.Add(new OperatorExpression(lastToken.Type)); switch (actualToken.Type) { case TokenType.IDENTIFIER: case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: case TokenType.EXMARK: case TokenType.BOOLLITERAL: case TokenType.STRINGLITERAL: case TokenType.INTLITERAL: case TokenType.FLOATLITERAL: case TokenType.OPENPAREN: case TokenType.CLOSEPAREN: actualToken = Pop(); break; default: restart = false; break; } break; case TokenType.CLOSEPAREN: if (pLevel > 0) { pLevel--; expressions.Add(new OperatorExpression(lastToken.Type)); switch (actualToken.Type) { case TokenType.PLUS: case TokenType.MINUS: case TokenType.MULTIPLY: case TokenType.DIVIDE: case TokenType.CLOSEPAREN: actualToken = Pop(); break; default: restart = false; break; } } else { Push(lastToken); restart = false; } break; default: restart = false; break; } if (restart) return RecursiveExp(expressions, actualToken, pLevel, actualBlock); else return expressions; }
/// <summary> /// Push a token /// </summary> /// <param name="token">Token to push</param> void Push(Token token) { Tokens.Push(token); }