Beispiel #1
0
        private MatchResult CheckExpressionMatches(CompilerPlugin plugin, List<TokenMatch> matches, Dictionary<string, object> args, int peekCount, int matchCount)
        {
            var isMatch = true;
            var token = peekCount == 0 ? this.TokenIt.NextToken : this.TokenIt.Peek(peekCount);
            var totalMatched = matchCount;
            
            foreach (var match in matches)
            {
                var continueCheck = false;
                var trackNamedArgs = true;
                var valueMatched = false;

                // Termninators
                if (match.TokenType == "@exprTerminators" 
                    && ( Terminators.ExpFlexibleEnd.ContainsKey(token.Token) || Terminators.ExpThenEnd.ContainsKey(token.Token) ) 
                    )
                {
                    // Don't increment the peekcount
                    isMatch = totalMatched >= plugin.TotalRequiredMatches;
                    break;
                }
                // Check for ";" and EOF ( end of file/text )
                if (token.Token == Tokens.Semicolon || token.Token == Tokens.EndToken)
                {
                    isMatch = totalMatched >= plugin.TotalRequiredMatches;
                    break;
                }

                // Check 1: Group tokens ?
                if(match.IsGroup)
                {
                    var submatches = ((TokenGroup) match).Matches;
                    var result = CheckExpressionMatches(plugin, submatches, args, peekCount, totalMatched);
                    if(match.IsRequired && !result.Success)
                    {
                        isMatch = false;
                        break;
                    }
                    if(result.Success)
                    {
                        peekCount = result.TokenCount;
                        if(match.IsRequired)
                            totalMatched += result.TotalMatched;
                    }
                }
                // Check 2: starttoken?
                else if (match.TokenType == "@starttoken")
                {
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 2a: tokenmap1
                else if (match.TokenType == "@tokenmap1")
                {
                    if (plugin.TokenMap1 == null || !plugin.TokenMap1.ContainsKey(token.Token.Text))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    totalMatched++;
                }
                else if (match.TokenType == "@tokenmap2")
                {
                    if (plugin.TokenMap2 == null || !plugin.TokenMap2.ContainsKey(token.Token.Text))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 2c: "identSymbol" must exist
                else if (match.TokenType == "@identsymbol")
                {
                    var symbolExists = this.Symbols.Contains(token.Token.Text);
                    continueCheck = symbolExists;
                    if (!continueCheck)
                    {
                        isMatch = false;
                        break;
                    }
                    totalMatched++;
                }
                // Check 2c: "identSymbol" must exist
                else if (match.TokenType == "@singularsymbol")
                {
                    var plural = token.Token.Text + "s";
                    var symbolExists = this.Symbols.Contains(plural);
                    continueCheck = symbolExists;
                    if (!continueCheck)
                    {
                        isMatch = false;
                        break;
                    }
                    totalMatched++;
                }
                // Check 2d: paramlist = @word ( , @word )* parameter names
                else if(match.TokenType == "@paramnames")
                {
                    var isvalidParamList = true;
                    var maxParams = 10;
                    var totalParams = 0;
                    var paramList = new List<object>();

                    while(totalParams <= maxParams)
                    {
                        var token2 = this.TokenIt.Peek(peekCount, false);
                        if(token2.Token == Tokens.Comma)
                        {
                            peekCount++;
                        }
                        else if(token2.Token.Kind == TokenKind.Ident)
                        {
                            paramList.Add(token2.Token.Text);
                            peekCount++;
                        }
                        else
                        {
                            peekCount--;
                            break;
                        }
                        totalParams++;
                    }
                    isMatch = isvalidParamList;
                    continueCheck = isMatch;
                    if (continueCheck)
                    {
                        trackNamedArgs = false;
                        if(!string.IsNullOrEmpty(match.Name))
                        {
                            args[match.Name] = token;
                            args[match.Name + "Value"] = new LArray(paramList);
                        }
                        totalMatched++;
                    }
                    else
                    {
                        break;
                    }
                }
                // Check 3a: Optional words with text
                else if (!match.IsRequired && match.Text != null && match.Text != token.Token.Text)
                {
                    continueCheck = false;
                }
                // Check 3b: Optional words matched
                else if (!match.IsRequired && match.IsMatchingValue(token.Token))
                {
                    continueCheck = true;
                }
                // Check 4: Optional word not matched
                else if (!match.IsRequired && !match.IsMatchingValue(token.Token))
                {
                    continueCheck = false;
                }
                // Check 5a: Expected word
                else if (match.IsRequired && match.TokenType == null && match.Text == token.Token.Text)
                {
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 5b: Expected word in list
                else if (match.IsRequired && match.TokenType == null && match.Values != null)
                {
                    if (!match.IsMatchingValue(token.Token))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    valueMatched = true;
                    totalMatched++;
                }
                // Check 6: check the type of n1
                else if (match.IsMatchingType(token.Token))
                {
                    continueCheck = true;
                    totalMatched++;
                }
                else
                {
                    isMatch = false;
                    break;
                }
                if (continueCheck)
                {
                    if (!string.IsNullOrEmpty(match.Name) && trackNamedArgs)
                    {
                        args[match.Name] = token; 
                        if(match.TokenPropEnabled)
                        {
                            // 1. figure out which token map to use.
                            var lookupmap = plugin.StartTokenMap;

                            if (match.TokenType == "@tokenmap1")
                                lookupmap = plugin.TokenMap1;
                            else if (match.TokenType == "@tokenmap2")
                                lookupmap = plugin.TokenMap2;

                            // Case 1: Start token replacement value
                            if (match.TokenPropValue == "value")
                            {
                                var startToken = token.Token.Text;
                                args[match.Name + "Value"] = lookupmap[startToken];
                            }
                            // Case 2: Token value
                            else if (match.TokenPropValue == "tvalue")
                            {
                                LObject val = LObjects.Null;
                                if (match.TokenType == "@number")
                                    val = new LNumber((double)token.Token.Value);
                                else if (match.TokenType == "@time")
                                    val = new LTime((TimeSpan)token.Token.Value);
                                else if (match.TokenType == "@word")
                                    val = new LString((string)token.Token.Value);
                                else if (match.TokenType == "@starttoken")
                                    val = new LString(token.Token.Text);
                                args[match.Name + "Value"] = val;
                            }
                            // Case 2: Token value
                            else if (match.TokenPropValue == "tvaluestring")
                            {
                                LObject val = LObjects.Null;
                                if (match.TokenType == "@number")
                                    val = new LString(((double)token.Token.Value).ToString(CultureInfo.InvariantCulture));
                                else if (match.TokenType == "@time")
                                    val = new LString(((TimeSpan)token.Token.Value).ToString());
                                else if (match.TokenType == "@starttoken")
                                    val = new LString(token.Token.Text);
                                else if (match.TokenType == "@word")
                                    val = new LString(token.Token.Text);
                                else if (match.TokenType == "@singularsymbol")
                                    val = new LString(token.Token.Text);
                                args[match.Name + "Value"] = val;
                            }
                        }
                        // matching values
                        else if(valueMatched)
                        {
                            args[match.Name + "Value"] = token.Token.Text;
                        }
                    }
                    // Matched: increment.
                    peekCount++;
                    token = this.TokenIt.Peek(peekCount, false);
                }
            }
            var res = new MatchResult(isMatch, null, args);
            res.TotalMatched = totalMatched;
            res.TokenCount = peekCount;
            return res;
        }
Beispiel #2
0
        public static LString IncrementString(UnaryExpr expr, LString sourceVal, IAstVisitor visitor)
        {
            // Check 1: Can only do += on strings.
            if (expr.Op != Operator.PlusEqual)
                throw new LangException("Syntax Error", "string operation with " + expr.Op.ToString() + " not supported", expr.Ref.ScriptName, expr.Ref.Line, expr.Ref.CharPos);

            //expr.DataType = typeof(string);
            var val = expr.Expression.Evaluate(visitor) as LObject;

            // Check 2: Check for null
            if (val == LObjects.Null)
                return sourceVal;

            // Check 3: Limit size if string
            Ctx.Limits.CheckStringLength(expr, sourceVal.Value, val.GetValue().ToString());

            // Finally do the appending.
            var appended = sourceVal.Value + val.GetValue().ToString();
            sourceVal.Value = appended;
            expr.Ctx.Memory.SetValue(expr.Name, sourceVal);
            return sourceVal;
        }
Beispiel #3
0
        /// <summary>
        /// Evaluate * / + - % 
        /// </summary>
        /// <returns></returns>
        public object VisitBinary(BinaryExpr expr)
        {
            // Validate
            object result = 0;
            var node = expr;
            var op = expr.Op;
            var left = (LObject) expr.Left.Evaluate(this);
            var right = (LObject) expr.Right.Evaluate(this);

            // Case 1: Both numbers
            if (IsTypeMatch(LTypes.Number, left, right))
            {
                result = EvalHelper.CalcNumbers(node, (LNumber)left, (LNumber)right, op);
            }
            // Case 2: Both times
            else if (IsTypeMatch(LTypes.Time, left, right))
            {
                result = EvalHelper.CalcTimes(node, (LTime)left, (LTime)right, op);
            }
            // Case 3: Both dates
            else if (IsTypeMatch(LTypes.Date, left, right))
            {
                result = EvalHelper.CalcDates(node, (LDate)left, (LDate)right, op);
            }
            // Case 4: Both strings.
            else if (IsTypeMatch(LTypes.String, left, right))
            {
                var strleft = ((LString)left).Value;
                var strright = ((LString)right).Value;

                // Check string limit.
                this.Ctx.Limits.CheckStringLength(node, strleft, strright);
                result = new LString(strleft + strright);
            }

            // MIXED TYPES
            // TODO: Needs to be improved with new code for types.
            // Case 5 : Double and Bool
            else if (left.Type == LTypes.Number && right.Type == LTypes.Bool)
            {
                var r = ((LBool)right).Value;
                var rval = r ? 1 : 0;
                result = EvalHelper.CalcNumbers(node, (LNumber)left, new LNumber(rval), op);
            }
            // Bool Double
            else if (left.Type == LTypes.Bool && right.Type == LTypes.Number)
            {
                var l = ((LBool)left).Value;
                var lval = l ? 1 : 0;
                result = EvalHelper.CalcNumbers(node, new LNumber(lval), (LNumber)right, op);
            }
            // Append as strings.
            else if (left.Type == LTypes.String && right.Type == LTypes.Bool)
            {
                var st1 = ((LString)left).Value + ((LBool)right).Value.ToString().ToLower();
                result = new LString(st1);
            }
            // Append as strings.
            else if (left.Type == LTypes.Bool && right.Type == LTypes.String)
            {
                var st2 = ((LBool)left).Value.ToString().ToLower() + ((LString)right).Value;
                result = new LString(st2);
            }
            // TODO: Need to handle LUnit and LVersion better
            //else if (left.Type == LTypes.Unit && right.Type == LTypes.Unit)
            else if (left.Type.TypeVal == TypeConstants.Unit && right.Type.TypeVal == TypeConstants.Unit)
            {
                result = EvalHelper.CalcUnits(node, (LUnit)((LClass)left).Value, (LUnit)((LClass)right).Value, op, this.Ctx.Units);
            }
            else
            {
                // Check for null
                var lStringVal = "";
                var rStringVal = "";
                if (left != LObjects.Null)
                    lStringVal = left.GetValue().ToString();
                if (right != LObjects.Null)
                    rStringVal = right.GetValue().ToString();

                var st3 = lStringVal + rStringVal;
                result = new LString(st3);
            }
            return result;
        }
Beispiel #4
0
        /// <summary>
        /// Evaluates a math expression of 2 time spans.
        /// </summary>
        /// <param name="node">The AST node the evaluation is a part of.</param>
        /// <param name="lhs">The time on the left hand side</param>
        /// <param name="rhs">The time on the right hand side</param>
        /// <param name="op">The math operator.</param>
        /// <returns></returns>
        public static LBool CompareStrings(AstNode node, LString lhs, LString rhs, Operator op)
        {
            var left = lhs.Value;
            var right = rhs.Value;
            var result = false;
            if (op == Operator.EqualEqual)
            {
                result = left == right;
                return new LBool(result);
            }
            else if (op == Operator.NotEqual)
            {
                result = left != right;
                return new LBool(result);
            }

            int compareResult = string.Compare(left, right, StringComparison.InvariantCultureIgnoreCase);
            if (op == Operator.LessThan) result = compareResult == -1;
            else if (op == Operator.LessThanEqual) result = compareResult != 1;
            else if (op == Operator.MoreThan) result = compareResult == 1;
            else if (op == Operator.MoreThanEqual) result = compareResult != -1;
            return new LBool(result);
        }