Ejemplo n.º 1
0
        private IEnumerable <Parselet> BlockWeight(Token <R> token)
        {
            Token <R> funcToken = null;
            var       actions   = new List <RantAction>();

            while (!reader.End)
            {
                funcToken = reader.ReadToken();

                if (funcToken.ID == R.RightParen)
                {
                    reader.SkipSpace();

                    if (!actions.Any())
                    {
                        compiler.SyntaxError(funcToken, "Expected weight value");
                    }

                    RantAction weightAction;
                    // probably a number
                    if (actions[0] is RAText)
                    {
                        if (actions.Count > 1)
                        {
                            if (!(actions[1] is RAText) || ((RAText)actions[1]).Text != "." || actions.Count != 3)
                            {
                                compiler.SyntaxError(actions[1].Range, "Invalid block weight value.");
                            }
                            weightAction = new RAText(actions[0].Range,
                                                      (actions[0] as RAText).Text +
                                                      (actions[1] as RAText).Text +
                                                      (actions[2] as RAText).Text);
                        }
                        else
                        {
                            weightAction = actions[0];
                        }
                    }
                    else
                    {
                        weightAction = new RASequence(actions, funcToken);
                    }

                    AddToOutput(weightAction);
                    yield break;
                }

                yield return(Parselet.GetParselet(funcToken, actions.Add));
            }

            // TODO: this token is "our" (the one that result is us being yielded) token. maybe have the 'fromToken' passed?
            compiler.SyntaxError(token, "Unterminated function: unexpected end of file");
        }
        private IEnumerable <Parselet> FunctionSubroutine(Token <R> token)
        {
            var    call         = false;
            var    nextToken    = reader.ReadToken();
            var    inModule     = false;
            string functionName = null;

            // if the first token isn't a square, it's the name of the subroutine call
            if (nextToken.ID != R.LeftSquare)
            {
                call = true;

                // probably an in-module subroutine call
                if (reader.PeekType() == R.Subtype)
                {
                    reader.ReadToken();
                    var name = reader.Read(R.Text, "subroutine name");
                    functionName = name.Value;
                    inModule     = true;
                }
            }
            else
            {
                if (reader.PeekType() == R.Subtype)
                {
                    compiler.HasModule = true;
                    inModule           = true;
                    reader.ReadToken();
                }
                nextToken = reader.Read(R.Text, "subroutine name");
            }

            // if there's a colon here, there's args
            var hasArgs = reader.Take(R.Colon);

            if (call)
            {
                foreach (var parselet in SubroutineArgs(token, nextToken, functionName))
                {
                    yield return(parselet);
                }
                yield break;
            }

            var subroutine = new RADefineSubroutine(nextToken);

            subroutine.Parameters = new Dictionary <string, SubroutineParameterType>();

            // read ALL THE ARGS!!
            // right now we're at [$[name: or [$[name
            while (hasArgs && !reader.End)
            {
                var nameToken = reader.ReadLooseToken();

                if (nameToken.ID == R.Text)
                {
                    subroutine.Parameters.Add(nameToken.Value, SubroutineParameterType.Greedy);
                }
                else if (nameToken.ID == R.At)
                {
                    nameToken = reader.ReadLoose(R.Text);
                    subroutine.Parameters.Add(nameToken.Value, SubroutineParameterType.Loose);
                }
                else
                {
                    compiler.SyntaxError(nameToken, "Expected subroutine parameter");
                }

                nextToken = reader.ReadLooseToken();

                if (nextToken.ID == R.Semicolon)
                {
                    continue;
                }

                if (nextToken.ID == R.RightSquare)
                {
                    break;
                }

                compiler.SyntaxError(nextToken, "Unexpected token in subroutine parameter definition");
            }

            // if there's no args, we need to get rid of the right square before the body
            if (!hasArgs)
            {
                reader.ReadLoose(R.RightSquare);
            }

            // start reading the body
            reader.ReadLoose(R.Colon);

            RASequence body = null;

            foreach (var parselet in SubroutineBody(token, a => body = a))
            {
                yield return(parselet);
            }

            subroutine.Body = body;
            if (inModule)
            {
                compiler.Module.AddActionFunction(subroutine.Name, subroutine);
            }
            AddToOutput(subroutine);
        }