Example #1
0
        public string Markup(string code, out int outdentThis, out int indentNext)
        {
            var sb = new StringBuilder();
            var lexer = new Lexer(code);
            int parenDepth = 0, squareDepth = 0;

            outdentThis = indentNext = 0;
            bool statementStart = true;
            bool ifStatement    = false;
            bool justSawThen    = false;

            while (!lexer.AtEnd)
            {
                int start = lexer.position;

                // grab whitespace (normally skipped by the lexer)
                if (Lexer.IsWhitespace(code[lexer.position]))
                {
                    while (!lexer.AtEnd && Lexer.IsWhitespace(code[lexer.position]))
                    {
                        lexer.position++;
                    }
                    sb.Append(code.Substring(start, lexer.position - start));
                    if (lexer.AtEnd)
                    {
                        break;
                    }
                    start = lexer.position;
                }

                // also check for a comment (which the lexer would also skip over)
                if (lexer.position < code.Length - 2 && code[lexer.position] == '/' && code[lexer.position + 1] == '/')
                {
                    while (!lexer.AtEnd && code[lexer.position] != '\n')
                    {
                        lexer.position++;
                    }
                    sb.Append(comment.startTags);
                    sb.Append(code.Substring(start, lexer.position - start));
                    sb.Append(comment.endTags);
                    if (lexer.AtEnd)
                    {
                        break;
                    }
                    start = lexer.position;
                }

                // now, grab and process the next token (being sure to catch and handle lexer exceptions)
                Token tok = null;
                try {
                    tok = lexer.Dequeue();
                } catch (LexerException exc) {
                    tok            = new Token();
                    lexer.position = code.Length;
                }

                if (tok.text == "self")
                {
                    tok.type = Token.Type.Keyword;                              // (special case)
                }
                if (justSawThen && tok.type != Token.Type.Comment && tok.type != Token.Type.EOL)
                {
                    // If anything (other than a comment) comes after "then", then this
                    // is a single-line if, and should not indent the next line.
                    indentNext = 0;
                }
                justSawThen = false;

                switch (tok.type)
                {
                case Token.Type.Keyword:
                    sb.Append(keyword.startTags);
                    sb.Append(tok.text);
                    sb.Append(keyword.endTags);
                    // Styling's done, but also figure out how this keyword changes indentation.
                    if (statementStart)
                    {
                        if (tok.text == "if")
                        {
                            indentNext++;
                            ifStatement = true;
                        }
                        else
                        {
                            ifStatement = false;
                        }
                        if (tok.text == "while" || tok.text == "for" ||
                            tok.text == "else" || tok.text == "else if")
                        {
                            indentNext++;
                        }
                        if (tok.text.StartsWith("end ") ||
                            tok.text == "else" || tok.text == "else if")
                        {
                            outdentThis++;
                        }
                    }
                    else
                    {
                        if (tok.text == "function")
                        {
                            indentNext++;
                        }
                        if (tok.text == "then")
                        {
                            justSawThen = true;
                        }
                    }

                    break;

                case Token.Type.Colon:
                    sb.Append(colon.startTags);
                    sb.Append(":");
                    sb.Append(colon.endTags);
                    statementStart = true;
                    break;

                case Token.Type.Identifier:
                    sb.Append(identifier.startTags);
                    sb.Append(tok.text);
                    sb.Append(identifier.endTags);
                    break;

                case Token.Type.String:
                    sb.Append(stringLiteral.startTags);
                    sb.Append("\"");                           // (note that lexer strips the surrounding quotes)
                    sb.Append(tok.text.Replace("\"", "\"\"")); // and un-doubles internal quotes
                    sb.Append("\"");
                    sb.Append(stringLiteral.endTags);
                    break;

                case Token.Type.Number:
                    sb.Append(numericLiteral.startTags);
                    sb.Append(tok.text);
                    sb.Append(numericLiteral.endTags);
                    break;

                case Token.Type.LParen:
                case Token.Type.RParen:
                    if (tok.type == Token.Type.LParen)
                    {
                        parenDepth++;
                    }
                    if (rotatingParenColors)
                    {
                        float h, s, v;
                        Color.RGBToHSV(baseParenColor, out h, out s, out v);
                        h = Mathf.Repeat(h + 0.22f * (parenDepth - 1), 1);
                        Color color = Color.HSVToRGB(h, s, v);
                        if (parenDepth < 1)
                        {
                            color = Color.red;
                        }
                        sb.Append("<color=#");
                        sb.Append(ColorUtility.ToHtmlStringRGB(color));
                        sb.Append(tok.type == Token.Type.LParen ? ">(</color>" : ">)</color>");
                    }
                    else
                    {
                        sb.Append(tok.type == Token.Type.LParen ? ">(</color>" : ">)</color>");
                    }
                    if (tok.type == Token.Type.RParen)
                    {
                        parenDepth--;
                    }
                    break;

                case Token.Type.LSquare:
                case Token.Type.RSquare:
                    if (tok.type == Token.Type.LSquare)
                    {
                        squareDepth++;
                    }
                    if (rotatingSquareColors)
                    {
                        float h, s, v;
                        Color.RGBToHSV(baseSquareColor, out h, out s, out v);
                        h = Mathf.Repeat(h + 0.22f * (squareDepth - 1), 1);
                        Color color = Color.HSVToRGB(h, s, v);
                        if (squareDepth < 1)
                        {
                            color = Color.red;
                        }
                        sb.Append("<color=#");
                        sb.Append(ColorUtility.ToHtmlStringRGB(color));
                        sb.Append(tok.type == Token.Type.LSquare ? ">[</color>" : ">]</color>");
                    }
                    else
                    {
                        sb.Append(tok.type == Token.Type.LSquare ? ">[</color>" : ">]</color>");
                    }
                    if (tok.type == Token.Type.RSquare)
                    {
                        squareDepth--;
                    }
                    break;

                case Token.Type.Unknown:
                    if (code[start] == '"')
                    {
                        sb.Append(openString.startTags);
                        sb.Append(code.Substring(start, lexer.position - start));
                        sb.Append(openString.endTags);
                    }
                    else
                    {
                        sb.Append(code.Substring(start, lexer.position - start));
                    }
                    break;

                default:
                    sb.Append(operators.startTags);
                    sb.Append(code.Substring(start, lexer.position - start));
                    sb.Append(operators.endTags);
                    break;
                }
                statementStart = false;
            }
            return(sb.ToString());
        }