Пример #1
0
 public State(Interpreter ii, RantPattern source, ChannelStack output)
 {
     _interpreter  = ii;
     _output       = output;
     _reader       = new PatternReader(source);
     _sharesOutput = (output == _interpreter._output && _interpreter.PrevState != null) || (_interpreter._stateStack.Any() && output == _interpreter._stateStack.Peek().Output);
 }
Пример #2
0
 private State(Interpreter ii, RantPattern derivedSource, IEnumerable <Token <R> > tokens,
               ChannelStack output)
 {
     _interpreter  = ii;
     _output       = output;
     _reader       = new PatternReader(new RantPattern(derivedSource, tokens));
     _sharesOutput = (output == _interpreter._output && _interpreter.PrevState != null) || (_interpreter._stateStack.Any() && output == _interpreter._stateStack.Peek().Output);
 }
Пример #3
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);
        }
Пример #4
0
        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;
                }