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 RepNum(Interpreter interpreter, Source source, Stringe tagname, Argument[] args) { if (interpreter.CurrentRepeater == null) { throw new RantException(source, tagname, "No active repeaters."); } interpreter.Print(interpreter.FormatNumber(interpreter.CurrentRepeater.Index + 1)); return(false); }
private static bool Number(Interpreter interpreter, Source source, Stringe tagName, Argument[] args) { int a, b; if (!Int32.TryParse(args[0].GetString(), out a) || !Int32.TryParse(args[1].GetString(), out b)) { throw new RantException(source, tagName, "Range values could not be parsed. They must be numbers."); } interpreter.Print(interpreter.FormatNumber(interpreter.RNG.Next(a, b + 1))); return(false); }
private static bool Extern(Interpreter interpreter, Source source, Stringe tagname, Argument[] args) { var name = args[0].GetString(); var result = interpreter.Engine.Hooks.Call(name); if (result == null) { throw new RantException(source, tagname, "A hook with the name '" + name + "' does not exist."); } interpreter.Print(result); return(false); }
private static bool CharacterMulti(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args) { int count; if (!ParseInt(args[1], out count) || count < 0) { throw Error(source, tagname, "Invalid character count specified. Must be a non-negative number greater than zero."); } for (int i = 0; i < count; i++) { interpreter.Print(SelectFromRanges(args[0], interpreter.RNG)); } return(false); }
private static bool CharacterMulti(Interpreter interpreter, Source source, Stringe tagname, Argument[] args) { int count; if (!Int32.TryParse(args[1], out count) || count < 0) { throw new RantException(source, tagname, "Invalid character count specified. Must be a non-negative number greater than zero."); } for (int i = 0; i < count; i++) { interpreter.Print(Util.SelectFromRanges(args[0], interpreter.RNG)); } return(false); }
private static bool Character(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args) { interpreter.Print(SelectFromRanges(args[0], interpreter.RNG)); return(false); }
private static bool Src(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args) { interpreter.Print(source.Code); return(false); }
private static bool Generation(Interpreter interpreter, RantPattern source, Stringe tagName, Argument[] args) { interpreter.Print(interpreter.RNG.Generation); return(false); }
private static bool NumberDec(Interpreter interpreter, RantPattern source, Stringe tagName, Argument[] args) { interpreter.Print(interpreter.RNG.NextDouble()); return(false); }
private static bool DoText(Interpreter interpreter, SourceReader reader, State state) { interpreter.Print(reader.ReadToken().Value); return(false); }
private static bool ReplaceMatch(Interpreter interpreter, Source source, Stringe tagname, Argument[] args) { interpreter.Print(interpreter.GetMatchString()); return(false); }
private static bool DoQuery(Interpreter interpreter, SourceReader reader, State state) { var first = reader.ReadToken(); reader.SkipSpace(); var namesub = reader.Read(TokenType.Text, "list name").Split(new[] { '.' }, 2).ToArray(); var q = new Query(namesub[0].Value.Trim(), namesub.Length == 2 ? namesub[1].Value : "", "", reader.Take(TokenType.Dollar), null, null); Token <TokenType> token = null; // Class filter list. Not initialized unless class filters actually exist. List <Tuple <bool, string> > cfList = null; while (true) { if (reader.Take(TokenType.Hyphen)) { // Initialize the filter list. (cfList ?? (cfList = new List <Tuple <bool, string> >())).Clear(); do { bool notin = reader.Take(TokenType.Exclamation); if (notin && q.Exclusive) { throw new RantException(reader.Source, reader.PrevToken, "Cannot use the '!' modifier on exclusive class filters."); } cfList.Add(Tuple.Create(!notin, reader.Read(TokenType.Text, "class identifier").Value.Trim())); } while (reader.Take(TokenType.Pipe)); q.ClassFilters.Add(cfList.ToArray()); } else if (reader.Take(TokenType.Question)) { token = reader.Read(TokenType.Regex, "regex"); q.RegexFilters.Add(Tuple.Create(true, Util.ParseRegex(token.Value))); } else if (reader.Take(TokenType.Without)) { token = reader.Read(TokenType.Regex, "regex"); q.RegexFilters.Add(Tuple.Create(false, Util.ParseRegex(token.Value))); } else if (reader.Take(TokenType.DoubleColon)) { token = reader.Read(TokenType.Text, "carrier name"); q.Carrier = token.Value.Trim(); if (!reader.Take(TokenType.RightAngle)) { throw new RantException(reader.Source, token, "Expected '>' after carrier. (The carrier should be your last query argument!)"); } break; } else if (reader.Take(TokenType.RightAngle)) { break; } else if (!reader.SkipSpace()) { var t = !reader.End ? reader.ReadToken() : null; throw new RantException(reader.Source, t, t == null ? "Unexpected end-of-file in query." : "Unexpected token '" + t.Value + "' in query."); } } interpreter.Print(interpreter.Engine.Vocabulary.Query(interpreter.RNG, q)); return(false); }
private static bool DoEscape(Interpreter interpreter, SourceReader reader, State state) { interpreter.Print(Util.Unescape(reader.ReadToken().Value, interpreter.RNG)); return(false); }
private static bool DoConstant(Interpreter interpreter, SourceReader reader, State state) { interpreter.Print(Util.UnescapeConstantLiteral(reader.ReadToken().Value)); return(false); }
private static bool Length(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args) { interpreter.Print(args[0].GetString().Length); return(false); }
private static bool Dist(Interpreter interpreter, RantPattern source, Stringe tagname, Argument[] args) { interpreter.Print(interpreter.GetMarkerDistance(args[0], args[1])); return(false); }
private static bool DoQuery(Interpreter interpreter, Token <R> firstToken, PatternReader reader, State state) { reader.SkipSpace(); bool storeMacro = false; bool macroIsGlobal = false; string macroName = null; // Check if this is a macro if (reader.Take(R.At)) { reader.SkipSpace(); var macroNameToken = reader.Read(R.Text, "query macro name"); if (!ValidateName(macroNameToken.Value)) { throw new RantException(reader.Source, macroNameToken, "Invalid macro name."); } macroName = macroNameToken.Value; reader.SkipSpace(); // Check if the macro is a definition or a call. // A definition will start with a colon ':' or equals '=' after the name. A call will only consist of the name. switch (reader.ReadToken().ID) { case R.Colon: // Local definition { storeMacro = true; } break; case R.Equal: // Global definition { storeMacro = true; macroIsGlobal = true; } break; case R.RightAngle: // Call { Query q; if (!interpreter.LocalQueryMacros.TryGetValue(macroName, out q) && !interpreter.Engine.GlobalQueryMacros.TryGetValue(macroName, out q)) { throw new RantException(reader.Source, macroNameToken, "Nonexistent query macro '\{macroName}'"); } interpreter.Print(interpreter.Engine.Vocabulary?.Query(interpreter.RNG, q, interpreter.CarrierSyncState)); return(false); } } } reader.SkipSpace(); var namesub = reader.Read(R.Text, "dictionary name").Split(new[] { '.' }, 2).ToArray(); reader.SkipSpace(); bool exclusive = reader.Take(R.Dollar); List <Tuple <bool, string> > cfList = null; List <Tuple <bool, string>[]> classFilterList = null; List <Tuple <bool, Regex> > regList = null; Carrier carrier = null; Token <R> queryToken = null; // Read query arguments while (true) { reader.SkipSpace(); if (reader.Take(R.Hyphen)) { reader.SkipSpace(); // Initialize the filter list. (cfList ?? (cfList = new List <Tuple <bool, string> >())).Clear(); do { bool notin = reader.Take(R.Exclamation); reader.SkipSpace(); if (notin && exclusive) { throw new RantException(reader.Source, reader.PrevToken, "Cannot use the '!' modifier on exclusive class filters."); } cfList.Add(Tuple.Create(!notin, reader.Read(R.Text, "class identifier").Value.Trim())); reader.SkipSpace(); } while (reader.Take(R.Pipe)); (classFilterList ?? (classFilterList = new List <Tuple <bool, string>[]>())).Add(cfList.ToArray()); } else if (reader.Take(R.Question)) { reader.SkipSpace(); queryToken = reader.Read(R.Regex, "regex"); (regList ?? (regList = new List <Tuple <bool, Regex> >())).Add(Tuple.Create(true, ParseRegex(queryToken.Value))); } else if (reader.Take(R.Without)) { reader.SkipSpace(); queryToken = reader.Read(R.Regex, "regex"); (regList ?? (regList = new List <Tuple <bool, Regex> >())).Add(Tuple.Create(false, ParseRegex(queryToken.Value))); } else if (reader.Take(R.DoubleColon)) // Start of carrier { reader.SkipSpace(); CarrierSyncType type; Token <R> typeToken; switch ((typeToken = reader.ReadToken()).ID) { case R.Exclamation: type = CarrierSyncType.Unique; break; case R.Equal: type = CarrierSyncType.Match; break; case R.Ampersand: type = CarrierSyncType.Rhyme; break; default: throw new RantException(reader.Source, typeToken, "Unrecognized token '\{typeToken.Value}' in carrier."); } reader.SkipSpace(); carrier = new Carrier(type, reader.Read(R.Text, "carrier sync ID").Value, 0, 0); reader.SkipSpace(); if (!reader.Take(R.RightAngle)) { throw new RantException(reader.Source, queryToken, "Expected '>' after carrier. (The carrier should be your last query argument!)"); } break; }