/// <summary>
 /// Adds an operand to the expression. 
 /// </summary>
 /// <param name="token">Token to add as an operand</param>
 /// <param name="addToFirst">Whether to add operand as first operand</param>
 public void AddOperand(Token token, bool addToFirst)
 {
     if ( addToFirst )
     {
         FirstOperand = token;
     }
     else
     {
         SecondOperand = token;
     }
 }
 /// <summary>
 /// Adds a new semantic error
 /// </summary>
 /// <param name="token">Token</param>
 /// <param name="message">Message</param>
 public static void AddSemanticError(Token token, string message)
 {
     if ( token != null )
     {
         SemanticErrors.Add(
             new Error(Lines[token.Line - 1], token.Line, token.StartColumn, message));
     }
     else
     {
         SemanticErrors.Add(
             new Error(Lines[Lines.Count - 1], Lines.Count, Lines[Lines.Count - 1].Length, message));
     }
 }
예제 #3
0
        /// <summary>
        /// Adds a syntax error to the list of errors
        /// </summary>
        /// <param name="token">Current token</param>
        /// <param name="expectedLexeme">Expected lexeme</param>
        /// <param name="useDefault">Use default message: "Was expecting {expectedLexeme}."</param>
        private void AddSyntaxError(Token token, string expectedLexeme, bool useDefault = true)
        {
            if (token == null)
            {
                _syntaxErrors.Add(
                    new Error(Scanner.Lines[Scanner.Lines.Count - 1], Scanner.Lines.Count - 1, Scanner.Lines[Scanner.Lines.Count - 1].Length, String.Format("Unexpected end of file, was expecting {0}.", expectedLexeme)));
                return;
            }
            if (useDefault)
            {
                _syntaxErrors.Add(
                    new Error(Scanner.Lines[token.Line - 1], token.Line, token.StartColumn, String.Format("Was expecting {0}.", expectedLexeme)));
            }
            else
            {
                _syntaxErrors.Add(
                    new Error(Scanner.Lines[token.Line - 1], token.Line, token.StartColumn, expectedLexeme));

            }
        }
예제 #4
0
 /// <summary>
 /// Checks the token for null reference and correct lexeme
 /// </summary>
 /// <param name="token">Current token</param>
 /// <param name="lexeme">Lexeme expected</param>
 /// <returns>True if ok</returns>
 public static bool CheckToken(Token token, string lexeme)
 {
     return token != null && token.Lexeme == lexeme;
 }
 /// <summary>
 /// Extracts string value from a terminal token or variable. 
 /// Basicly this is ToString() for tokenterminal and variables of type t
 /// </summary>
 /// <param name="token">Terminal or variable token</param>
 /// <returns>Value</returns>
 private static string ExtractString(Token token)
 {
     var tokenTerminal = token as TokenTerminal<string>;
     if ( tokenTerminal != null )
     {
         return tokenTerminal.Value;
     }
     var tokenIdentifier = token as TokenIdentifier;
     if ( tokenIdentifier != null )
     {
         var s = Statement.GetVariable(tokenIdentifier.Identifier) as VariableType<string>;
         if ( s != null )
         {
             return s.Value;
         }
         var i = Statement.GetVariable(tokenIdentifier.Identifier) as VariableType<int>;
         if ( i != null )
         {
             return i.Value.ToString();
         }
         var b = Statement.GetVariable(tokenIdentifier.Identifier) as VariableType<bool>;
         if ( b != null )
         {
             return b.Value.ToString().ToLower();
         }
     }
     try
     {
         return ExtractInt(token).ToString();
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     try
     {
         return ExtractBool(token).ToString().ToLower();
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     Statements.AddSemanticError(token, "Was expecting a string value.");
     throw new AbstractSyntaxTreeException("");
 }
 /// <summary>
 /// Extracts integer value from terminal token or from variable token
 /// </summary>
 /// <param name="token">Terminal or variable token</param>
 /// <returns>Value</returns>
 private static int ExtractInt(Token token)
 {
     var tokenTerminal = token as TokenTerminal<int>;
     if ( tokenTerminal != null )
     {
         return tokenTerminal.Value;
     }
     var tokenIdentifier = token as TokenIdentifier;
     if ( tokenIdentifier != null )
     {
         var variable = Statement.GetVariable(tokenIdentifier.Identifier) as VariableType<int>;
         if ( variable != null )
         {
             return variable.Value;
         }
     }
     Statements.AddSemanticError(token, "Was expecting an int value.");
     throw new AbstractSyntaxTreeException("");
 }
 /// <summary>
 /// Compares two string values
 /// </summary>
 /// <param name="token"> </param>
 /// <param name="firstValue">First value</param>
 /// <param name="op">Operator</param>
 /// <param name="secondValue">Second value</param>
 /// <returns>Comparison</returns>
 private static bool Compare(Token token, string firstValue, string op, string secondValue)
 {
     switch ( op )
     {
         case Operators.Equal:
             return firstValue == secondValue;
         case Operators.NotEqual:
             return firstValue != secondValue;
     }
     Statements.AddSemanticError(token, "Can't compare values string and string with operator " + op);
     throw new AbstractSyntaxTreeCalculateException("");
 }
 /// <summary>
 /// Compares two integer values
 /// </summary>
 /// <param name="token"> </param>
 /// <param name="firstValue">First value</param>
 /// <param name="op">Operator</param>
 /// <param name="secondValue">Second value</param>
 /// <returns>Comparison</returns>
 private static bool Compare(Token token, int firstValue, string op, int secondValue)
 {
     switch (op)
     {
         case Operators.Equal:
             return firstValue == secondValue;
         case Operators.NotEqual:
             return firstValue != secondValue;
         case Operators.GreaterThan:
             return firstValue > secondValue;
         case Operators.GreaterOrEqualThan:
             return firstValue >= secondValue;
         case Operators.LesserThan:
             return firstValue < secondValue;
         case Operators.LesserOrEqualThan:
             return firstValue <= secondValue;
     }
     Statements.AddSemanticError(token, "Can't compare values int and int with operator " + op);
     throw new AbstractSyntaxTreeCalculateException("");
 }
 /// <summary>
 /// Calculates boolean value from expression and operand
 /// </summary>
 /// <param name="first">First expression</param>
 /// <param name="op">Operator</param>
 /// <param name="second">Second operand</param>
 /// <returns>Result</returns>
 private static bool CalculateBool(Expression first, string op, Token second)
 {
     try
     {
         var b1 = first.EvaluateBool();
         var b2 = ExtractBool(second);
         return Calculate(first.GetFirstNotNullToken(), b1, op, b2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     try
     {
         var i1 = first.EvaluateInt();
         var i2 = ExtractInt(second);
         return Compare(first.GetFirstNotNullToken(), i1, op, i2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     try
     {
         var s1 = first.EvaluateString();
         var s2 = ExtractString(second);
         return Compare(first.GetFirstNotNullToken(), s1, op, s2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     Statements.AddSemanticError(first.GetFirstNotNullToken(), "Could not evaluate value.");
     throw new AbstractSyntaxTreeCalculateException("Couldn't evaluate.");
 }
예제 #10
0
 /// <summary>
 /// Calculates boolean value from two operands
 /// </summary>
 /// <param name="first">First operand</param>
 /// <param name="op">Operator</param>
 /// <param name="second">Second operand</param>
 /// <returns>Result</returns>
 private static bool CalculateBool(Token first, string op, Token second)
 {
     try
     {
         var b1 = ExtractBool(first);
         var b2 = ExtractBool(second);
         return Calculate(first, b1, op, b2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     try
     {
         var i1 = ExtractInt(first);
         var i2 = ExtractInt(second);
         return Compare(first, i1, op, i2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     try
     {
         var s1 = ExtractString(first);
         var s2 = ExtractString(second);
         return Compare(first, s1, op, s2);
     }
     catch ( AbstractSyntaxTreeException )
     {
         Statements.DeleteLastAddedError();
     }
     Statements.AddSemanticError(first, "Could not evaluate value.");
     throw new AbstractSyntaxTreeCalculateException("");
 }
예제 #11
0
 /// <summary>
 /// Calculates string value from two operands
 /// </summary>
 /// <param name="token"> </param>
 /// <param name="firstValue">First value</param>
 /// <param name="op">Operator</param>
 /// <param name="secondValue">Second value</param>
 /// <returns>Result</returns>
 private static string Calculate(Token token, string firstValue, string op, string secondValue)
 {
     if (op == Operators.Plus)
     {
         return firstValue + secondValue;
     }
     Statements.AddSemanticError(token, String.Format("Can't apply operator '{0}' to a string operation.", op));
     throw new AbstractSyntaxTreeCalculateException("");
 }
예제 #12
0
 /// <summary>
 /// Calculates integer value from two operands
 /// </summary>
 /// <param name="token"> </param>
 /// <param name="firstValue">First value</param>
 /// <param name="op">Operator</param>
 /// <param name="secondValue">Second value</param>
 /// <returns>Result</returns>
 private static int Calculate(Token token, int firstValue, string op, int secondValue)
 {
     switch ( op )
     {
         case Operators.Plus:
             return firstValue + secondValue;
         case Operators.Minus:
             return firstValue - secondValue;
         case Operators.Multiply:
             return firstValue * secondValue;
         case Operators.Divide:
             return firstValue / secondValue;
     }
     Statements.AddSemanticError(token, String.Format("Can't apply operator '{0}' to operands 'int' and int'.", op));
     throw new AbstractSyntaxTreeCalculateException("");
 }
예제 #13
0
 /// <summary>
 /// Calculates boolean value from two operands
 /// </summary>
 /// <param name="token"> </param>
 /// <param name="firstValue">First value</param>
 /// <param name="op">Operator</param>
 /// <param name="secondValue">Second value</param>
 /// <returns>Result</returns>
 private static bool Calculate(Token token, bool firstValue, string op, bool secondValue)
 {
     switch (op)
     {
         case Operators.Equal:
             return firstValue == secondValue;
         case Operators.NotEqual:
             return firstValue != secondValue;
         case Operators.And:
             return firstValue != secondValue;
     }
     Statements.AddSemanticError(token, String.Format("Can't apply operator '{0}' to operands 'bool' and 'bool'.", op));
     throw new AbstractSyntaxTreeCalculateException("");
 }
예제 #14
0
        /// <summary>
        /// Produces tokens for the parser.
        /// </summary>
        /// <param name="lines">Source code</param>
        /// <returns>Tokens</returns>
        public List<Token> Tokenize(List<string> lines)
        {
            if ( lines == null )
            {
                throw new ScannerException("Lines were null");
            }
            Lines = lines;
            var tokens = new List<Token>();
            for (_row = 0; _row < lines.Count; _row++)
            {
                _column = 0;
                var line = lines[_row];
                while (_column < line.Length)
                {
                    var stop = SkipWhiteSpace(line);
                    if (stop)
                    {
                        break;
                    }
                    if ( _column < line.Length - 1 && line[_column] == '/' && line[_column + 1] == '*' ) // Multiline comment
                    {
                        SkipMultilineComment(lines);
                        continue;
                    }
                    if (_column < line.Length - 1 && line[_column] == '/' && line[_column + 1] == '/') // line comment
                    {
                        break;
                    }

                    Token token;

                    if ( (token = CreateTypeToken(line)) != null )
                    {
                        tokens.Add(token);
                        _previousToken = token;
                        continue;
                    }
                    if ( (token = CreateReservedKeywordToken(line)) != null )
                    {
                        tokens.Add(token);
                        _previousToken = token;
                        continue;
                    }

                    if ( (token = CreateOperatorToken(line)) != null )
                    {
                        tokens.Add(token);
                        _previousToken = token;
                        continue;
                    }

                    if ( (token = CreateTerminalToken(line)) != null )
                    {
                        tokens.Add(token);
                        _previousToken = token;
                        continue;
                    }
                    if ( (token = CreateIdentifierToken(line)) != null )
                    {
                        tokens.Add(token);
                        _previousToken = token;
                        continue;
                    }
                    if ( (token = CreateErrorToken(line)) != null)
                    {
                        tokens.Add(token);
                        _previousToken = token;
                    }
                }
            }

            return tokens;
        }
예제 #15
0
 /// <summary>
 /// Creates a token if it matches the given symbol
 /// </summary>
 /// <param name="line">Current line</param>
 /// <param name="symbol">Symbol to match</param>
 /// <returns>Created token or null</returns>
 private Token CreateToken(string line, string symbol)
 {
     // One can make this to work a lot faster, but this is nicer
     try
     {
         if ( line.Substring(_column, symbol.Length) == symbol )
         {
             var token = new Token(_row, _column, symbol);
             _column += symbol.Length;
             return token;
         }
     }
     catch (ArgumentOutOfRangeException)
     {
     }
     return null;
 }