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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }