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 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 DoSubCall(Token <TokenType> first, Interpreter interpreter, SourceReader reader, State state) { var name = reader.ReadToken(); if (!Util.ValidateName(name.Value)) { throw new RantException(reader.Source, name, "Invalid subroutine 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 subroutine name."); } none = true; } IEnumerable <Token <TokenType> >[] args = null; Subroutine sub = null; if (none) { if ((sub = interpreter.Engine.Subroutines.Get(name.Value, 0)) == null) { throw new RantException(reader.Source, name, "No subroutine was found with the name '" + name.Value + "' and 0 parameters."); } } else { args = reader.ReadItemsToClosureTrimmed(TokenType.LeftSquare, TokenType.RightSquare, TokenType.Semicolon, BracketPairs.All).ToArray(); if ((sub = interpreter.Engine.Subroutines.Get(name.Value, args.Length)) == null) { throw new RantException(reader.Source, name, "No subroutine was found with the name '" + name.Value + "' and " + args.Length + " parameter" + (args.Length != 1 ? "s" : "") + "."); } } state.AddPreBlueprint(new SubCallBlueprint(interpreter, reader.Source, sub, args)); return(true); }