Пример #1
0
        public FunctionNode HandleFunction()
        {
            //get the function name
            SkipWhiteSpace();
            Lexeme       functionNameLexeme = Pop(LexemeType.WORD);
            FunctionNode functionNode       = new FunctionNode(functionNameLexeme);
            string       functionName       = functionNameLexeme.text;

            //If the function only takes one argument, stop here
            if (!subroutineDatabase.TryGetValue(functionName, out SubroutineInformation subroutineInformation))
            {
                throw GetParsingException($"Function {functionName} not in function database");
            }

            //If have reached the end of line/nothing left to parse, just return no arguments
            if (!HasCurrent())
            {
                return(functionNode);
            }

            //If there is a comma after the function name, just ignore it
            if (Peek().type == LexemeType.COMMA)
            {
                Pop();
            }
            SkipWhiteSpace();

            //Console.WriteLine($"Parsing function {functionName} which has {subroutineInformation.hasArguments} arguments");
            if (subroutineInformation.hasArguments)
            {
                //parse the first argument if it has more than one argument
                //TODO: should proabably group tokens here rather than doing later? not sure....

                functionNode.AddArgument(HandleExpression());

                while (HasCurrent())
                {
                    //Just assume there is one argument after each comma
                    //If anything else is found besides a comma, assume function arguments have ended.
                    //TODO: (the engine will actually accept spaces instead of commas)
                    //TODO: perhaps should use colon ':' to determine function end if more than one function after each other?
                    SkipWhiteSpace();
                    if (Peek().type != LexemeType.COMMA)
                    {
                        break;
                    }
                    else
                    {
                        Pop();
                    }

                    SkipWhiteSpace();
                    functionNode.AddArgument(HandleExpression());
                }
            }

            return(functionNode);
        }
Пример #2
0
        public void LexSection(bool sectionAllowsText)
        {
            bool mustBeExpression = false;
            bool firstIteration   = true;

            while (HasCurrent())
            {
                bool nextMustBeExpression = false;
                TryPopRegex(Regexes.whitespace, LexemeType.WHITESPACE);
                if (!HasCurrent())
                {
                    break;
                }

                if (!mustBeExpression &&
                    sectionAllowsText &&
                    (Peek() == '^' || Regexes.exclamationTextCommand.IsMatch(this.line, this.pos) || Peek() > 127))
                {
                    //only allow entering text mode if:
                    // - not followed by a comma, as that would imply the next lexeme is a function argument which cannot be text mode
                    //   EXAMPLE: dwave_eng 0, ev2_3e816 ^  Chiester Sisters!!^@:

                    // - not followed by an operator, as that would imply the next lexeme is a expression
                    //   Example: dwave_eng 0, ev2_3e816 + ^  Chiester Sisters!!^@:

                    // - not followed by a function name which takes arguments, as that would imply it's meant to be
                    // Example where it is allowed: langen ^She jumped and jumped and leapt and even flipped in midair, increasing that distance.^\
                    // Example where it NOT allowed: takesOneArgument ^She jumped and jumped and leapt and even flipped in midair, increasing that distance.^

                    PopDialogue();
                }
                else if ((mustBeExpression || firstIteration) && TryPopRegex(Regexes.label, LexemeType.LABEL))
                {
                    //label must either be:
                    // - the first lexeme on the line, or
                    // - an expression (function argument)
                }
                else if (TryEach(nextMustBeExpressionList))
                {
                    nextMustBeExpression = true;
                }
                else if (TryEach(operators))
                {
                    nextMustBeExpression = true;
                }
                else if (TryPopRegex(Regexes.comma, LexemeType.COMMA))
                {
                    nextMustBeExpression = true;
                }
                else if (TryEach(pairs))
                {
                }
                else if (TryPopRegex(Regexes.word, LexemeType.WORD, out Lexeme lexeme))
                {
                    if (!mustBeExpression)
                    {
                        string word = lexeme.text;
                        if (word == "to" || word == "step")
                        {
                            //In For loops, after "to" or "step" an expression is expected.
                            nextMustBeExpression = true;
                        }
                        else if (word == "if" || word == "notif" || word == "for")
                        {
                            //do nothing?
                        }
                        else if (subroutineDatabase.TryGetValue(word, out SubroutineInformation subroutineInformation))
                        {
                            if (subroutineInformation.hasArguments)
                            {
                                nextMustBeExpression = true;
                            }
                        }
                        else
                        {
                            throw GetLexingException($"Unrecognized keyword or function \"{word}\"");
                        }
                    }
                }
                else if (sectionAllowsText && (Peek() == '`'))
                {
                    //For '`': Pretend single-byte text mode is just normal text mode for now...
                    PopDialogue();
                }
                else if (sectionAllowsText && TryPopRegex(Regexes.hexColor, LexemeType.HEX_COLOR))
                {
                    //For '#': If you encounter a color tag at top level, most likely it's for colored text.
                    //Should this enter text mode?
                    break;
                }
                else if (sectionAllowsText && (Peek() == '\''))
                {
                    PrintLexingWarning($"WARNING: Text-mode possibly entered unintentionally from character '{Peek()}' (ascii: {(int)Peek()})!");
                    PopDialogue();
                }
                else if (Peek() <= 8)
                {
                    PrintLexingWarning($"WARNING: Got control character '{Peek()}' (ascii: {(int)Peek()}), which will be ignored!");
                    lexemes.Add(new Lexeme(LexemeType.UNHANDLED_CONTROL_CHAR, Pop().ToString()));
                }
                else
                {
                    //error
                    throw GetLexingException($"Unexpected character(s)? at top level starting from: [{this.line.Substring(this.pos)}]");
                }

                mustBeExpression = nextMustBeExpression;
                firstIteration   = false;
            }
        }