예제 #1
0
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            if (functionToken.ParameterCount == 0)
            {
                throw new XPressionException(functionToken.Source, "format requires at least one argument", functionToken.Position);
            }
            var args = new List <Expression>();

            for (var i = 0; i < functionToken.ParameterCount; i++)
            {
                args.Add(treeBuilder.PopExpression(stack, p));
            }

            args.Reverse(); // reverse stack order

            output =
                Expression.Call(
                    MemberTokens.String.FormatWithProvider,
                    Expression.Constant(CultureInfo.InvariantCulture),
                    args[0],
                    Expression.NewArrayInit(
                        typeof(object),
                        args.Skip(1).Select(e => e.Type == typeof(object) ? e : Expression.Convert(e, typeof(object)))
                        )
                    );
            return(true);
        }
예제 #2
0
        public object Execute(KarinEngine engine, FunctionToken token, object pipedObj)
        {
            var args = token.Arguments;

            if (!(2 <= args.Length || args.Length <= 3))
            {
                throw new KarinException($"{Name}関数の引数の数が不正です。");
            }

            //条件を演算
            var sw = engine.Ride(args[0]);

            if (!(sw is bool))
            {
                throw new KarinException($"{Name}関数の条件を評価できません。");
            }

            //どちらかを実行
            if ((bool)sw)
            {
                return(engine.Ride(args[1]));
            }
            else
            {
                return(args.Length == 3 ? engine.Ride(args[2]) : null);
            }
        }
예제 #3
0
        public object Execute(KarinEngine engine, FunctionToken token, object pipedObj)
        {
            var args = token.Arguments;

            if (args.Length != 2)
            {
                throw new KarinException($"{Name}関数の引数の数が不正です。");
            }

            //回数条件
            var co = engine.Ride(args[0]);

            //繰り返し実行
            object ret = null;

            for (var c = 0; c < (int)co; c++)
            {
                ret = engine.Ride(args[1]);
                if (ret is ReturnedObject)
                {
                    break;
                }
            }
            return(ret);
        }
예제 #4
0
        public object Execute(KarinEngine engine, FunctionToken token, object pipedObj)
        {
            if (!((token.IsPipe && token.Arguments.Length == 0) ||
                  (!token.IsPipe && token.Arguments.Length == 1)))
            {
                throw new KarinException($"{Name}関数の引数の数が不正です。");
            }

            var arg = token.IsPipe ? pipedObj : engine.Ride(token.Arguments[0]);

            if (!(arg is string))
            {
                throw new KarinException($"{Name}関数の引数が文字列ではありません。");
            }

            var s   = (string)arg;
            var sb  = new StringBuilder(s.Length);
            int pre = 0;
            var ptn = new Regex(@"{\s*(\$\$?[^\s\$\{\}]+)\s*}");

            foreach (Match m in ptn.Matches(s))
            {
                var val = engine.Eval(m.Value);
                sb.Append(s.Substring(pre, m.Index - pre));
                sb.Append(val);
                pre = m.Index + m.Length;
            }
            sb.Append(s.Substring(pre, s.Length - pre));
            return(sb.ToString());
        }
예제 #5
0
        private bool TryCompileAliasedFunction(MessageScriptParser.TokenContext context, string tagId, out FunctionToken functionToken)
        {
            LogContextInfo(context);

            functionToken = new FunctionToken();
            var functionWasFound = false;

            foreach (var library in Library.MessageScriptLibraries)
            {
                var function = library.Functions.SingleOrDefault(x => x.Name == tagId);
                if (function == null)
                {
                    continue;
                }

                var arguments = new List <short>();
                for (var i = 0; i < function.Parameters.Count; i++)
                {
                    if (!TryParseShortIntLiteral(context, "Expected function argument", () => context.IntLiteral(i), out var argument))
                    {
                        return(false);
                    }

                    arguments.Add(argument);
                }

                functionToken    = new FunctionToken(library.Index, function.Index, arguments);
                functionWasFound = true;
                break;
            }

            return(functionWasFound);
        }
예제 #6
0
        public object Execute(KarinEngine engine, FunctionToken token, object pipedObj)
        {
            var args = token.Arguments;

            if (args.Length != 2)
            {
                throw new KarinException($"{Name}関数の引数の数が不正です。");
            }

            object ret = null;

            while (true)
            {
                object loop = engine.Ride(args[0]);
                if (!(loop is bool))
                {
                    throw new KarinException($"{Name}関数の条件を評価できません。");
                }
                if ((bool)loop == false)
                {
                    break;
                }

                ret = engine.Ride(args[1]);
                if (ret is ReturnedObject)
                {
                    break;
                }
            }
            return(ret);
        }
예제 #7
0
        private static OnStatement readOn(TokenCollection stream)
        {
            OnFunctionPrimitive token = stream.GetNextToken() as OnFunctionPrimitive;

            if (token == null)
            {
                throw new HspLogicalLineException("on条件分岐行:条件分岐プリミティブ以外からスタート");
            }
            //式がないこともあるかもしれない(実行時エラー)
            if (stream.NextIsEndOfLine)
            {
                return(new OnStatement(token, null, null));
            }
            //式を読む。goto/gosubがないこともあるかもしれない(実行時エラー)
            ExpressionToken exp = CodeTokenFactory.ReadExpression(stream);

            if (stream.NextIsEndOfLine)
            {
                return(new OnStatement(token, exp, null));
            }
            //goto/gosub関数を読む。goto/gosub以外でもコンパイルは通る(実行時エラー)
            //この関数には()がつかない。
            FunctionToken func = CodeTokenFactory.ReadFunction(stream, false);

            if (stream.NextIsEndOfLine)
            {
                return(new OnStatement(token, exp, func));
            }
            //まだあまってたらエラーね。
            throw new HspLogicalLineException("on条件分岐行:余分なトークンがある");
        }
예제 #8
0
        public void EqualsDiffTypeTest()
        {
            var token = new FunctionToken(Functions.Sine, 1);

            Assert.False(token.Equals(1));
            Assert.NotEqual((object)1, token);
        }
예제 #9
0
 /// <summary>
 /// Make a function node from a parsed function token.
 /// </summary>
 /// <param name="tok"></param>
 public FunctionNode(FunctionToken tok)
 {
     Name            = tok.Name;
     TopArguments    = tok.TopArguments;
     BottomArguments = tok.BottomArguments;
     Tiebreaker      = tok.Range.Max;
 }
예제 #10
0
        public void EqualsNullTest()
        {
            var token = new FunctionToken(Functions.Sine, 1);

            Assert.False(token.Equals(null));
            Assert.NotNull(token);
        }
예제 #11
0
        public static double Log10(FunctionToken func, Evaluator evaluator)
        {
            var args = func.Arguments;
            var num  = args[0].Evaluate(evaluator);

            return(Math.Log10(num));
        }
예제 #12
0
 public RawFunctionNode(FunctionToken functionName, ArgListNode args, Type returnType, bool doNotCache)
 {
     _functionName = functionName;
     Args          = args;
     ReturnType    = returnType;
     DoNotCache    = doNotCache;
 }
예제 #13
0
        public void EqualsSameObjectTest()
        {
            var token = new FunctionToken(Functions.Sine, 1);

            Assert.True(token.Equals(token));
            Assert.Equal(token, token);
        }
예제 #14
0
        public static double Atan(FunctionToken func, Evaluator evaluator)
        {
            var args = func.Arguments;
            var num  = args[0].Evaluate(evaluator);

            return(Math.Atan(num.ToRadians(evaluator.Settings.Mode)));
        }
예제 #15
0
        public static double GradToRad(FunctionToken func, Evaluator evaluator)
        {
            var args = func.Arguments;
            var num  = args[0].Evaluate(evaluator);

            return(num.ToRadians(Mode.Grad));
        }
예제 #16
0
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            var rightToken = stack.Pop(); // must be a constant string
            var target     = treeBuilder.PopExpression(stack, p);

            if (target.IsNullConstant())
            {
                output = Expression.Convert(Expression.Constant(null), typeof(bool?));
                return(true);
            }
            Type type;

            try
            {
                type = treeBuilder.Grammar.GetType(rightToken.Lexeme);
            }
            catch (Exception ex)
            {
                throw new XPressionException(functionToken.Source, "Invalid type: " + rightToken.Lexeme, rightToken.Position, ex);
            }
            if ((!target.Type.IsValueType || target.Type.IsNullable()) && type.IsValueType && !type.IsNullable())
            {
                type = typeof(Nullable <>).MakeGenericType(type);
            }
            output = Expression.TypeEqual(target, type);
            return(true);
        }
예제 #17
0
    public void TestTokenProperties()
    {
        IdentifierToken functionName = new IdentifierToken("function");
        FunctionToken   result       = new FunctionToken(0, functionName);

        Assert.AreEqual(functionName, result.FunctionName);
    }
예제 #18
0
 public FunctionBlock(IBlock parent, BlockType type, TrackingToken start, ITextSnapshot textSnapshot, FunctionToken name)
     : base(parent, type, start, textSnapshot)
 {
     Name       = name;
     Parameters = new List <IDefinitionToken>();
     parent.AddToken(name);
     name.FunctionBlock = this;
 }
예제 #19
0
        public void EqualsDiffFuncTest()
        {
            var token1 = new FunctionToken(Functions.Sine, 1);
            var token2 = new FunctionToken(Functions.Cosine, 1);

            Assert.False(token1.Equals(token2));
            Assert.NotEqual(token1, token2);
        }
예제 #20
0
        private void CheckDefinition(FunctionToken def)
        {
            if (def.Name != "Def")
            {
                throw new ParseException("Function definitions must start with a call named Def, like this: " + example)
                      {
                          FunctionToken = def
                      }
            }
            ;

            if (def.TopArguments.Length == 0)
            {
                throw new ParseException("Function definitions must have at leat one argument- the name: " + example)
                      {
                          FunctionToken = def
                      }
            }
            ;

            foreach (Argument arg in def.TopArguments.Concat(def.BottomArguments))
            {
                if (!(arg is FunctionArg))
                {
                    throw new ParseException("Incorrect formal parameter declaration {0}. All parameters must have alphabetic names and no quotes.", arg)
                          {
                              FunctionToken = def
                          }
                }
                ;
            }

            TopArguments    = def.TopArguments.Skip(1).Cast <FunctionArg>().ToArray();
            BottomArguments = def.BottomArguments.Cast <FunctionArg>().ToArray();

            string functionName = def.TopArguments[0].GetAs <string>();

            if (functionName == "...")
            {
                throw new ParseException("... cannot be the name of a function. Function names consist of letters only.")
                      {
                          FunctionToken = def
                      };
            }
            else
            {
                Name = functionName;
            }

            // if Main doesn't have any arguments
            if (Name == "Main" && TopArguments.Length == 0)
            {
                TopArguments = new FunctionArg[] { FunctionArg.TryParseArg("...") };
            }
        }
    }
}
예제 #21
0
        public override Token getToken()
        {
            FunctionToken token = new FunctionToken();

            token.setValue(sbCode.ToString());
            token.setType(TokenType.Function);

            return(token);
        }
예제 #22
0
        // C# equivalents:
        // if(test,body) => return test ? body() : true;
        // if(test,trueBody,falseBody) => return test ? trueBody() : falseBody();
        // if parametercount==2 (falseBody is omitted), then the falseBody always
        // returns true (so then the trueBody MUST return a boolean value as well)
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            var ifFalse = functionToken.ParameterCount >= 3 ? treeBuilder.PopExpression(stack, p) : Expression.Constant(true);
            var ifTrue  = treeBuilder.PopExpression(stack, p);
            var test    = treeBuilder.PopExpression(stack, p);

            output = Expression.Condition(test.Convert <bool>(), ifTrue, ifFalse);
            return(true);
        }
예제 #23
0
 public AccessMethodNode(FunctionToken fToken, ArgsListNode args, ArgsListNode extraAggregateArguments,
                         MethodInfo method = (MethodInfo)null, string alias = "")
 {
     FToken    = fToken;
     Arguments = args;
     ExtraAggregateArguments = extraAggregateArguments;
     Method = method;
     Alias  = alias;
     Id     = $"{nameof(AccessMethodNode)}{alias}{fToken.Value}{args.Id}";
 }
예제 #24
0
        public void FunctionParsingWorks(string test, string name, int argCount)
        {
            foreach (string teststr in new[] { test, @"\." + test, test + "./", @"\." + test + "./" })
            {
                FunctionToken f = new FunctionToken(teststr, 0, teststr.Length);

                Assert.AreEqual(name, f.Name);
                Assert.AreEqual(argCount, f.TopArguments.Length);
            }
        }
예제 #25
0
        private Expression BuildArrayAccessExpression(FunctionToken token, Expression array, Stack <Token> stack, ParameterExpression p)
        {
            var args = new List <Expression>();

            for (var i = 0; i < token.ParameterCount; i++)
            {
                args.Add(PopExpression(stack, p));
            }
            args.Reverse();

            return(Expression.ArrayAccess(array, args));
        }
예제 #26
0
        /// <summary>
        /// 命令行
        /// </summary>
        /// <param defaultName="primitives"></param>
        /// <returns></returns>
        private static Command readCommand(TokenCollection stream)
        {
            //実態はCodeTokenFactoryに任せる
            //命令には(関数と違って)括弧はいらない
            FunctionToken func = CodeTokenFactory.ReadFunction(stream, false);

            if (stream.NextIsEndOfLine)
            {
                return(new Command(func));
            }
            throw new HspLogicalLineException("命令行:余分なトークンがある");
        }
예제 #27
0
        public object Execute(KarinEngine engine, FunctionToken token, object pipedObj)
        {
            if (token.Arguments.Length != 1)
            {
                throw new KarinException($"{Name}関数の引数の数が不正です。");
            }

            var ptn = new System.Text.RegularExpressions.Regex($@"{token.Name}\s*\[([\s\S]*)\]");
            var mc  = ptn.Match(token.Text);

            return(mc.Groups[1].Value);
        }
예제 #28
0
 private bool TryParseFunction(string expression, int i, out FunctionToken functionToken)
 {
     functionToken = default(FunctionToken);
     foreach (var function in Functions)
     {
         if (function.TryParse(expression, i))
         {
             functionToken = function;
             return(true);
         }
     }
     return(false);
 }
예제 #29
0
        public static double Log(FunctionToken func, Evaluator evaluator)
        {
            var args = func.Arguments;
            var a    = args[0].Evaluate(evaluator);

            if (args.Length == 1)
            {
                return(Math.Log(a));
            }
            var @base = args[1].Evaluate(evaluator);

            return(Math.Log(a, @base));
        }
예제 #30
0
        public void Decompile(FunctionToken token)
        {
            if (Library != null)
            {
                var library = Library.MessageScriptLibraries.FirstOrDefault(x => x.Index == token.FunctionTableIndex);
                if (library != null)
                {
                    var function = library.Functions.FirstOrDefault(x => x.Index == token.FunctionIndex);
                    if (function != null)
                    {
                        if (function.Semantic == MessageScriptLibraryFunctionSemantic.Unused && OmitUnusedFunctions)
                        {
                            return;
                        }

                        if (!string.IsNullOrWhiteSpace(function.Name))
                        {
                            WriteOpenTag(FormatIdentifier(function.Name));

                            for (var i = 0; i < function.Parameters.Count; i++)
                            {
                                var argument = function.Parameters[i];
                                WriteTagArgument(token.Arguments[i].ToString());
                            }

                            WriteCloseTag();
                            return;
                        }
                    }
                }
            }

            if (token.Arguments.Count == 0)
            {
                WriteTag("f", token.FunctionTableIndex.ToString(), token.FunctionIndex.ToString());
            }
            else
            {
                WriteOpenTag("f");
                WriteTagArgument(token.FunctionTableIndex.ToString());
                WriteTagArgument(token.FunctionIndex.ToString());

                foreach (var tokenArgument in token.Arguments)
                {
                    WriteTagArgument(tokenArgument.ToString());
                }

                WriteCloseTag();
            }
        }
예제 #31
0
		private static QueryExpression ParseFunction(QueryExpression subQuery, List<Token> tokens, int startToken, int numTokens, FunctionToken functionToken)
		{
			if (!(tokens[startToken] is VariableToken))
				throw new CSExpressionException("Function call " + functionToken.Function + " called with incorrect parameters");

            QueryExpression newQuery = (QueryExpression) EvalVariable(((VariableToken) tokens[startToken]).Variable, subQuery);

			string fieldExpression;

			switch (functionToken.Function)
			{
				case "HAS": fieldExpression = "*"; break;
				case "COUNT": fieldExpression = "count(*)"; break;
				case "COUNTDISTINCT": fieldExpression = "count(distinct " + newQuery.FieldName + ")"; break;

				default: fieldExpression = functionToken.Function + "(" + newQuery.FieldName + ")"; break;
			}

		    if (numTokens > 1)
		    {
                if (!(tokens[startToken + 1] is OperatorToken))
                    throw new CSExpressionException("Expected WHERE");

                OperatorToken whereToken = (OperatorToken) tokens[startToken + 1];
		        
		        if (whereToken.Operator.ToUpper() != "WHERE")
                    throw new CSExpressionException("Expected WHERE");

		        if (numTokens < 3)
                    throw new CSExpressionException("Expected expression after WHERE");

                newQuery.Expression += " AND ";
		        
                newQuery = Parse(newQuery, tokens, startToken + 2, numTokens - 2);
            }
		    
            string selectSql = newQuery.Table.Schema.DB.BuildSelectSQL(newQuery.Table.TableName, newQuery.Table.TableAlias, new[] { fieldExpression }, null, newQuery.Joins.BuildJoinExpressions(), newQuery.Expression, null, 1, 0, false, false);

		    if (functionToken.Function == "HAS")
                subQuery.Expression += "EXISTS ";
		    
            subQuery.Expression += "(" + selectSql + ")";
	    
			return subQuery;
		}
예제 #32
0
                private static Token[] GetInfixTokens(string term)
                {
                    //Leerzeichen entfernen und in Kleinbuchstaben konvertieren
                    term = term.Replace(" ", string.Empty).ToLowerInvariant();

                    var tokens = new List<Token>();

                    //mit RegEx alle Zahlen aussortieren
                    var numbers = parserRegEx.Matches(term);
                    term = parserRegEx.Replace(term, "1");

                    var sb = new StringBuilder(term);

                    //Term in Tokens teilen
                    var numberIndex = 0;
                    while (sb.Length > 0)
                    {
                        var validToken = false;

                        //Zahlen prüfen
                        if (sb.StartsWith("1"))
                        {
                            var t = new NumberToken();
                            t.ParseFromString(numbers[numberIndex].Groups["number"].Value);
                            tokens.Add(t);

                            numberIndex++;

                            //term = ReduceString(term, 1);
                            sb.Remove(0, 1);

                            validToken = true;
                        }

                        //Operatoren prüfen
                        if (!validToken)
                            for (int i = 0; i < operators.Length; i++)
                            {
                                var token = operators[i];
                                if (sb.StartsWith(token))
                                {
                                    var t = new OperatorToken();

                                    if ((token == '+' || token == '-') && (tokens.Count == 0 || tokens.Last().GetName() == "(")) //Vorzeichen
                                    {
                                        if (token == '-')
                                            t.ParseFromString("!");
                                    }
                                    else
                                        t.ParseFromString(token.ToString());

                                    tokens.Add(t);

                                    //term = ReduceString(term, 1);
                                    sb.Remove(0, 1);

                                    validToken = true;
                                    break;
                                }
                            }

                        //Funktionen prüfen
                        if (!validToken)
                            for (int i = 0; i < functions.Length; i++)
                            {
                                var token = functions[i];
                                if (sb.StartsWith(token))
                                {
                                    var t = new FunctionToken();
                                    t.ParseFromString(token);
                                    tokens.Add(t);

                                    //term = ReduceString(term, token.Length);
                                    sb.Remove(0, token.Length);

                                    validToken = true;
                                    break;
                                }
                            }

                        //Rest prüfen
                        if (!validToken)
                        {
                            if (sb.StartsWith("pi")) //Pi
                            {
                                var t = new NumberToken();
                                t.ParseFromString(System.Math.PI.ToString());
                                tokens.Add(t);

                                //term = ReduceString(term, 2);
                                sb.Remove(0, 2);
                            }

                            else if (sb.StartsWith("e")) //e
                            {
                                var t = new NumberToken();
                                t.ParseFromString(System.Math.E.ToString());
                                tokens.Add(t);

                                //term = ReduceString(term, 1);
                                sb.Remove(0, 1);
                            }

                            else if (sb.StartsWith("(")) //öffnende Klammer
                            {
                                var t = new SpecialToken();
                                t.ParseFromString("(");
                                tokens.Add(t);

                                //term = ReduceString(term, 1);
                                sb.Remove(0, 1);
                            }

                            else if (sb.StartsWith(")")) //schließende Klammer
                            {
                                var t = new SpecialToken();
                                t.ParseFromString(")");
                                tokens.Add(t);

                                //term = ReduceString(term, 1);
                                sb.Remove(0, 1);
                            }

                            else if (sb.StartsWith(";")) //Argumenttrennzeichen
                            {
                                var t = new SpecialToken();
                                t.ParseFromString(";");
                                tokens.Add(t);

                                //term = ReduceString(term, 1);
                                sb.Remove(0, 1);
                            }

                            else //Token nicht bekannt
                                throw new ArgumentException("Dieser Term enthält einen ungültigen Token.");
                        }
                    }

                    return tokens.ToArray();
                }