Пример #1
0
        private static bool Nth(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
        {
            int offset, interval;

            if (!Int32.TryParse(args[0].GetString(), out interval))
            {
                throw new RantException(source, tagname, "Invalid interval value.");
            }

            if (interval <= 0)
            {
                throw new RantException(source, tagname, "Interval must be greater than zero.");
            }

            if (!Int32.TryParse(args[1].GetString(), out offset))
            {
                throw new RantException(source, tagname, "Invalid offset value.");
            }

            if (interpreter.CurrentRepeater == null || !interpreter.CurrentRepeater.Nth(offset, interval))
            {
                return(false);
            }
            interpreter.PushState(State.CreateDerivedDistinct(source, args[2].GetTokens(), interpreter, interpreter.CurrentState.Output));
            return(true);
        }
Пример #2
0
        private static bool Arg(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
        {
            if (!interpreter.SubArgStack.Any())
            {
                throw new RantException(source, tagname, "Tried to access arguments outside of a subroutine body.");
            }

            Argument arg;
            var      argName = args[0].GetString().Trim();

            if (!interpreter.SubArgStack.Peek().TryGetValue(argName, out arg))
            {
                throw new RantException(source, tagname, "Could not find argument '" + argName + "'.");
            }

            // Argument is string
            if (arg.Flags == ParamFlags.None)
            {
                interpreter.Print(arg.GetString());
                return(false);
            }

            // Argument is tokens
            interpreter.PushState(State.CreateDerivedShared(source, arg.GetTokens(), interpreter));
            return(true);
        }
Пример #3
0
        private static bool Alt(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
        {
            var testState = State.CreateDerivedDistinct(source, args[0].GetTokens(), interpreter,
                                                        interpreter.CurrentState.Output);

            testState.AddPostBlueprint(new AltBlueprint(interpreter, testState, args[1].GetTokens()));
            interpreter.PushState(testState);
            return(true);
        }
Пример #4
0
 private static bool Else(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
 {
     if (!interpreter.UseElse())
     {
         return(false);
     }
     interpreter.PushState(State.CreateDerivedShared(source, args[0].GetTokens(), interpreter));
     return(true);
 }
Пример #5
0
 private static bool Else(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args)
 {
     if (!interpreter.UseElse())
     {
         return(false);
     }
     interpreter.PushState(Interpreter.State.CreateSub(source, args[0].GetTokens(), interpreter, interpreter.CurrentState.Output));
     return(true);
 }
Пример #6
0
 private static bool First(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
 {
     if (interpreter.CurrentRepeater == null || !interpreter.CurrentRepeater.IsFirst)
     {
         return(false);
     }
     interpreter.PushState(State.CreateDerivedDistinct(source, args[0].GetTokens(), interpreter, interpreter.CurrentState.Output));
     return(true);
 }
Пример #7
0
 private static bool IfDef(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args)
 {
     if (interpreter.Engine.Flags.Contains(args[0]))
     {
         interpreter.PushState(Interpreter.State.CreateSub(source, args[1].GetTokens(), interpreter, interpreter.CurrentState.Output));
         return(true);
     }
     interpreter.SetElse();
     return(false);
 }
Пример #8
0
 private static bool IfDef(Interpreter interpreter, Source source, Stringe tagname, Argument[] args)
 {
     if (interpreter.Engine.Flags.Contains(args[0]))
     {
         interpreter.PushState(State.CreateDerivedShared(source, args[1].GetTokens(), interpreter));
         return(true);
     }
     interpreter.SetElse();
     return(false);
 }
Пример #9
0
        private static bool DoSubDefinition(Token <TokenType> first, Interpreter interpreter, SourceReader reader, State state)
        {
            bool meta = reader.Take(TokenType.Question);

            reader.Read(TokenType.LeftSquare);

            var parameters = new List <Tuple <string, ParamFlags> >();
            var tName      = reader.Read(TokenType.Text, "subroutine name");

            if (!Util.ValidateName(tName.Value))
            {
                throw new RantException(reader.Source, tName, "Invalid subroutine name: '" + tName.Value + "'");
            }

            if (!reader.Take(TokenType.Colon))
            {
                reader.Read(TokenType.RightSquare);
            }
            else
            {
                while (true)
                {
                    bool isTokens = reader.Take(TokenType.At);
                    parameters.Add(Tuple.Create(reader.Read(TokenType.Text, "parameter name").Value, isTokens ? ParamFlags.Code : ParamFlags.None));
                    if (reader.Take(TokenType.RightSquare, false))
                    {
                        break;
                    }
                    reader.Read(TokenType.Semicolon);
                }
            }

            reader.SkipSpace();
            reader.Read(TokenType.Colon);

            var body = reader.ReadToScopeClose(TokenType.LeftSquare, TokenType.RightSquare, BracketPairs.All).ToArray();

            if (meta)
            {
                interpreter.PushState(State.CreateDerivedDistinct(reader.Source, body, interpreter));
                state.AddPreBlueprint(new FunctionBlueprint(interpreter, _ =>
                {
                    _.Engine.Subroutines.Define(tName.Value, Subroutine.FromString(tName.Value, _.PopResultString(), parameters.ToArray()));
                    return(false);
                }));
            }
            else
            {
                interpreter.Engine.Subroutines.Define(tName.Value, Subroutine.FromTokens(tName.Value, reader.Source, body, parameters.ToArray()));
            }

            return(meta);
        }
Пример #10
0
        private static bool DoTag(Interpreter interpreter, SourceReader reader, State state)
        {
            reader.Read(TokenType.LeftSquare);
            var name = reader.ReadToken();

            // Check if metapattern
            if (name.Identifier == TokenType.Question)
            {
                state.AddPreBlueprint(new MetapatternBlueprint(interpreter));
                interpreter.PushState(State.CreateDerivedDistinct(reader.Source, reader.ReadToScopeClose(TokenType.LeftSquare, TokenType.RightSquare, BracketPairs.All), interpreter));
                return(true);
            }

            // Check if replacer
            if (name.Identifier == TokenType.Regex)
            {
                return(DoReplacer(name, interpreter, reader, state));
            }

            if (name.Identifier == TokenType.Dollar)
            {
                return(reader.IsNext(TokenType.Text) ? DoSubCall(name, interpreter, reader, state) : DoSubDefinition(name, interpreter, reader, state));
            }

            if (!Util.ValidateName(name.Value.Trim()))
            {
                throw new RantException(reader.Source, name, "Invalid tag name '" + name.Value + "'");
            }

            bool none = false;

            if (!reader.Take(TokenType.Colon))
            {
                if (!reader.Take(TokenType.RightSquare))
                {
                    throw new RantException(reader.Source, name, "Expected ':' or ']' after tag name.");
                }
                none = true;
            }

            if (none)
            {
                state.AddPreBlueprint(new TagBlueprint(interpreter, reader.Source, name));
            }
            else
            {
                var items = reader.ReadItemsToClosureTrimmed(TokenType.LeftSquare, TokenType.RightSquare,
                                                             TokenType.Semicolon, BracketPairs.All).ToArray();

                state.AddPreBlueprint(new TagBlueprint(interpreter, reader.Source, name, items));
            }
            return(true);
        }
Пример #11
0
        private static bool BranchScope(Interpreter interpreter, RantPattern source, Stringe tagName, Argument[] args)
        {
            interpreter.RNG.Branch(args[0].GetString().Hash());
            var state = Interpreter.State.CreateSub(source, args[1].GetTokens(), interpreter, interpreter.CurrentState.Output);

            state.AddPostBlueprint(new DelegateBlueprint(interpreter, _ =>
            {
                interpreter.RNG.Merge();
                return(false);
            }));
            interpreter.PushState(state);
            return(true);
        }
Пример #12
0
        private static bool DoReplacer(Token <TokenType> name, Interpreter interpreter, SourceReader reader, State state)
        {
            reader.Read(TokenType.Colon);

            var args = reader.ReadItemsToClosureTrimmed(TokenType.LeftSquare, TokenType.RightSquare, TokenType.Semicolon, BracketPairs.All).ToArray();

            if (args.Length != 2)
            {
                throw new RantException(reader.Source, name, "Replacer expected 2 arguments, but got " + args.Length + ".");
            }

            state.AddPreBlueprint(new ReplacerBlueprint(interpreter, Util.ParseRegex(name.Value), args[1]));

            interpreter.PushState(State.CreateDerivedDistinct(reader.Source, args[0], interpreter));
            return(true);
        }
Пример #13
0
        private static bool DoMath(Interpreter interpreter, Token <R> firstToken, PatternReader reader, State state)
        {
            bool isStatement = reader.Take(R.At);
            var  tokens      = reader.ReadToScopeClose(R.LeftParen, R.RightParen, Brackets.All);

            interpreter.PushState(State.CreateSub(reader.Source, tokens, interpreter));
            state.AddPreBlueprint(new DelegateBlueprint(interpreter, _ =>
            {
                var v = Parser.Calculate(_, _.PopResultString());
                if (!isStatement)
                {
                    _.Print(_.FormatNumber(v));
                }
                return(false);
            }));
            return(true);
        }
Пример #14
0
        private static bool Compare(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args)
        {
            var cmp = new Comparison(args[0].GetString(), args[1].GetString());

            interpreter.Comparisons.Push(cmp);

            var state = Interpreter.State.CreateSub(source, args[2].GetTokens(), interpreter, interpreter.CurrentState.Output);

            state.AddPostBlueprint(new DelegateBlueprint(interpreter, I =>
            {
                I.Comparisons.Pop();
                return(false);
            }));

            interpreter.PushState(state);

            return(true);
        }
Пример #15
0
        private static bool DoMath(Interpreter interpreter, SourceReader reader, State state)
        {
            reader.Read(TokenType.LeftParen);
            bool isStatement = reader.Take(TokenType.At);
            var  tokens      = reader.ReadToScopeClose(TokenType.LeftParen, TokenType.RightParen, BracketPairs.All);

            interpreter.PushState(State.CreateDerivedDistinct(reader.Source, tokens, interpreter));
            state.AddPreBlueprint(new FunctionBlueprint(interpreter, _ =>
            {
                var v = Parser.Calculate(_, _.PopResultString());
                if (!isStatement)
                {
                    _.Print(_.FormatNumber(v));
                }
                return(false);
            }));
            return(true);
        }
Пример #16
0
        private static bool CmpIs(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args)
        {
            var cmp        = interpreter.Comparisons.Peek();
            var conStrings = args[0].GetString()
                             .Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            ComparisonResult e;

            foreach (var conString in conStrings)
            {
                if (!Enum.TryParse(NameToCamel(conString), true, out e))
                {
                    continue;
                }
                if (!cmp.Result.HasFlag(e))
                {
                    continue;
                }
                interpreter.PushState(Interpreter.State.CreateSub(source, args[1].GetTokens(), interpreter, interpreter.CurrentState.Output));
                return(true);
            }

            return(false);
        }
Пример #17
0
        public bool Iterate(Interpreter ii, RepeaterBlueprint bp)
        {
            if (Finished)
            {
                ii.PopRepeater();
                return(false);
            }

            // Queue the next iteration on the current state
            ii.CurrentState.AddPreBlueprint(bp);

            // Push separator if applicable
            if (!IsLast && _attribs.Separator != null && _attribs.Separator.Any())
            {
                var sepState = Interpreter.State.CreateDerivedDistinct(
                    ii.CurrentState.Reader.Source,
                    _attribs.Separator,
                    ii,
                    ii.CurrentState.Output);

                // Make sure that the repeater is not available to the separator pattern
                sepState.AddPreBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Pop));
                sepState.AddPostBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Push));

                ii.PushState(sepState);
            }

            // Push postfix if applicable
            if (_attribs.After != null && _attribs.After.Any())
            {
                ii.PushState(Interpreter.State.CreateDerivedDistinct(
                                 ii.CurrentState.Reader.Source,
                                 _attribs.After,
                                 ii,
                                 ii.CurrentState.Output));
            }

            // Push next item
            var itemState = Interpreter.State.CreateDerivedDistinct(ii.CurrentState.Reader.Source,
                                                                    _items[_attribs.Sync != null ? _attribs.Sync.NextItem(_items.Length) : ii.RNG.Next(_items.Length)],
                                                                    ii,
                                                                    ii.CurrentState.Output);

            // Add a blueprint that iterates the repeater just before reading the item. This makes sure that tags like [first] can run before this happens.
            itemState.AddPostBlueprint(new FunctionBlueprint(ii, _ =>
            {
                Next();
                return(false);
            }));

            ii.PushState(itemState);

            // Push prefix if applicable
            if (_attribs.Before != null && _attribs.Before.Any())
            {
                ii.PushState(Interpreter.State.CreateDerivedDistinct(
                                 ii.CurrentState.Reader.Source,
                                 _attribs.Before,
                                 ii,
                                 ii.CurrentState.Output));
            }

            return(true);
        }
Пример #18
0
        public bool Iterate(Interpreter ii, RepeaterBlueprint bp)
        {
            while (ii.CurrentRepeater != null && ii.CurrentRepeater.Finished)
            {
                ii.PopRepeater();
            }

            if (Finished)
            {
                return(false);
            }

            // Queue the next iteration on the current state
            ii.CurrentState.AddPreBlueprint(bp);

            // Push separator if applicable
            if (!IsLast && _attribs.Separator != null && _attribs.Separator.Any())
            {
                var sepState = Interpreter.State.CreateSub(
                    ii.CurrentState.Reader.Source,
                    _attribs.Separator,
                    ii,
                    ii.CurrentState.Output);

                // Make sure that the repeater is not available to the separator pattern
                sepState.AddPreBlueprint(new DelegateBlueprint(ii, _ =>
                {
                    _allowStats = false;
                    return(false);
                }));
                sepState.AddPostBlueprint(new DelegateBlueprint(ii, _ =>
                {
                    _allowStats = true;
                    return(false);
                }));

                ii.PushState(sepState);
            }

            Interpreter.State afterState = null;

            // Push postfix if applicable
            if (_attribs.After != null && _attribs.After.Any())
            {
                ii.PushState(afterState = Interpreter.State.CreateSub(
                                 ii.CurrentState.Reader.Source,
                                 _attribs.After,
                                 ii,
                                 ii.CurrentState.Output));
            }

            // Push next item
            var itemState = Interpreter.State.CreateSub(ii.CurrentState.Reader.Source,
                                                        _attribs.Sync != null
                ? _block.Items[_attribs.Sync.NextItem(_block.Items.Length)].Item2
                : _block.Items.PickWeighted(ii.RNG, _block.WeightTotal, item => item.Item1).Item2,
                                                        ii,
                                                        ii.CurrentState.Output);

            // Apply the Next() call to the last state in the repeater iteration
            (afterState ?? itemState).AddPostBlueprint(new DelegateBlueprint(ii, _ =>
            {
                Next();
                return(false);
            }));

            ii.PushState(itemState);

            // Push prefix if applicable
            if (_attribs.Before != null && _attribs.Before.Any())
            {
                ii.PushState(Interpreter.State.CreateSub(
                                 ii.CurrentState.Reader.Source,
                                 _attribs.Before,
                                 ii,
                                 ii.CurrentState.Output));
            }

            return(true);
        }