Esempio n. 1
0
            private static Token ReadHexLiteral(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int index = cr.Position;

                // Read the prefix ($ or 0x)
                sb.Append(cr.ReadChar());
                if (cr.PeekChar() == 'x')
                {
                    sb.Append(cr.ReadChar());
                }

                // Read the digits
                while (!cr.EOF)
                {
                    char current = cr.PeekChar();
                    if (!IsHexCharacter(current))
                    {
                        break;
                    }
                    sb.Append(current);
                    cr.AdvancePosition();
                }

                return(new Token(Token.TokenKind.Number, sb.ToString(), cr.GetPositionInfo(index)));
            }
Esempio n. 2
0
            private static Token ReadNumberLiteral(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int index = cr.Position;

                // Read the first character, because it's guaranteed
                char first = cr.ReadChar();

                sb.Append(first);
                bool hasUsedDot = (first == '.');

                // Read the digits
                while (!cr.EOF)
                {
                    char current = cr.PeekChar();
                    if (!char.IsDigit(current) && (!hasUsedDot && current != '.'))
                    {
                        break;
                    }
                    sb.Append(current);
                    cr.AdvancePosition();
                }

                return(new Token(Token.TokenKind.Number, sb.ToString(), cr.GetPositionInfo(index)));
            }
Esempio n. 3
0
            private static Token ReadStringLiteralNoEscape(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int index = cr.Position;

                char quoteChar = cr.ReadChar();

                while (!cr.EOF && cr.PeekChar() != quoteChar)
                {
                    sb.Append(cr.ReadChar());
                }

                if (!cr.EOF)
                {
                    cr.AdvancePosition();
                }

                return(new Token(Token.TokenKind.String, sb.ToString(), cr.GetPositionInfo(index)));
            }
Esempio n. 4
0
            private static Token ReadIdentifier(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int index = cr.Position;

                sb.Append(cr.ReadChar());
                char c = cr.PeekChar();

                while (!cr.EOF && (char.IsLetterOrDigit(c) || c == '_'))
                {
                    sb.Append(c);
                    cr.AdvancePosition();
                    c = cr.PeekChar();
                }

                string identifierText = sb.ToString();

                return(identifierText switch
                {
                    "and" => new Token(Token.TokenKind.LogicalAnd, cr.GetPositionInfo(index)),
                    "or" => new Token(Token.TokenKind.LogicalOr, cr.GetPositionInfo(index)),
                    "xor" => new Token(Token.TokenKind.LogicalXor, cr.GetPositionInfo(index)),
                    "while" => new Token(Token.TokenKind.KeywordWhile, cr.GetPositionInfo(index)),
                    "with" => new Token(Token.TokenKind.KeywordWith, cr.GetPositionInfo(index)),
                    "if" => new Token(Token.TokenKind.KeywordIf, cr.GetPositionInfo(index)),
                    "do" => new Token(Token.TokenKind.KeywordDo, cr.GetPositionInfo(index)),
                    "not" => new Token(Token.TokenKind.Not, cr.GetPositionInfo(index)),
                    "enum" => new Token(Token.TokenKind.Enum, cr.GetPositionInfo(index)),
                    "begin" => new Token(Token.TokenKind.OpenBlock, cr.GetPositionInfo(index)),
                    "end" => new Token(Token.TokenKind.CloseBlock, cr.GetPositionInfo(index)),
                    "var" => new Token(Token.TokenKind.KeywordVar, cr.GetPositionInfo(index)),
                    "globalvar" => new Token(Token.TokenKind.KeywordGlobalVar, cr.GetPositionInfo(index)),
                    "return" => new Token(Token.TokenKind.KeywordReturn, cr.GetPositionInfo(index)),
                    "default" => new Token(Token.TokenKind.KeywordDefault, cr.GetPositionInfo(index)),
                    "struct" => new Token(Token.TokenKind.KeywordStruct, cr.GetPositionInfo(index)),
                    "function" when cr.compileContext.Data.GMS2_3 => new Token(Token.TokenKind.KeywordFunction, cr.GetPositionInfo(index)),
                    "for" => new Token(Token.TokenKind.KeywordFor, cr.GetPositionInfo(index)),
                    "case" => new Token(Token.TokenKind.KeywordCase, cr.GetPositionInfo(index)),
                    "switch" => new Token(Token.TokenKind.KeywordSwitch, cr.GetPositionInfo(index)),
                    "until" => new Token(Token.TokenKind.KeywordUntil, cr.GetPositionInfo(index)),
                    "continue" => new Token(Token.TokenKind.KeywordContinue, cr.GetPositionInfo(index)),
                    "break" => new Token(Token.TokenKind.KeywordBreak, cr.GetPositionInfo(index)),
                    "else" => new Token(Token.TokenKind.KeywordElse, cr.GetPositionInfo(index)),
                    "repeat" => new Token(Token.TokenKind.KeywordRepeat, cr.GetPositionInfo(index)),
                    "exit" => new Token(Token.TokenKind.KeywordExit, cr.GetPositionInfo(index)),
                    "then" => new Token(Token.TokenKind.KeywordThen, cr.GetPositionInfo(index)),
                    "mod" => new Token(Token.TokenKind.Mod, cr.GetPositionInfo(index)),
                    "div" => new Token(Token.TokenKind.Div, cr.GetPositionInfo(index)),
                    _ => new Token(Token.TokenKind.Identifier, identifierText, cr.GetPositionInfo(index)),
                });
Esempio n. 5
0
            private static Token ReadToken(CodeReader cr, bool gms2)
            {
                SkipWhitespaceAndComments(cr);
                if (cr.EOF)
                {
                    return(new Token(Token.TokenKind.EOF));
                }

                if (cr.PeekChar() == '#')
                {
                    // Skip preprocessor directive/macro/etc. Maybe support could be added later... but not yet.
                    while (!cr.EOF)
                    {
                        if (cr.PeekChar() == '\n')
                        {
                            break;
                        }
                        cr.AdvancePosition();
                    }
                }

                char c = cr.PeekChar();

                if (!char.IsLetter(c) && c != '_')
                {
                    // Numbers/hex
                    if (c == '$' || (c == '0' && cr.PeekCharAhead() == 'x'))
                    {
                        return(ReadHexLiteral(cr));
                    }
                    if (char.IsDigit(c) || (c == '.' && char.IsDigit(cr.PeekCharAhead())))
                    {
                        return(ReadNumberLiteral(cr));
                    }

                    // Strings
                    if (gms2)
                    {
                        if (c == '@')
                        {
                            char c2 = cr.PeekCharAhead();
                            if (c2 == '"' || c2 == '\'')
                            {
                                cr.AdvancePosition();
                                return(ReadStringLiteralNoEscape(cr));
                            }
                        }
                        else if (c == '"')
                        {
                            return(ReadStringLiteral(cr));
                        }
                    }
                    else
                    {
                        if (c == '"' || c == '\'')
                        {
                            return(ReadStringLiteral(cr));
                        }
                    }

                    // Operators/everything else
                    switch (c)
                    {
                    case '{':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.OpenBlock, cr.GetPositionInfo(cr.Position - 1)));

                    case '}':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.CloseBlock, cr.GetPositionInfo(cr.Position - 1)));

                    case '(':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.OpenParen, cr.GetPositionInfo(cr.Position - 1)));

                    case ')':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.CloseParen, cr.GetPositionInfo(cr.Position - 1)));

                    case '|':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '|':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.LogicalOr, cr.GetPositionInfo(cr.Position - 2)));

                            case '=':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.AssignOr, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.BitwiseOr, cr.GetPositionInfo(cr.Position - 1)));

                    case '^':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '^':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.LogicalXor, cr.GetPositionInfo(cr.Position - 2)));

                            case '=':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.AssignXor, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.BitwiseXor, cr.GetPositionInfo(cr.Position - 1)));

                    case '&':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '&':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.LogicalAnd, cr.GetPositionInfo(cr.Position - 2)));

                            case '=':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.AssignAnd, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.BitwiseAnd, cr.GetPositionInfo(cr.Position - 1)));

                    case '%':
                    {
                        if (cr.PeekCharAhead() == '=')
                        {
                            cr.AdvancePosition(2);
                            return(new Token(Token.TokenKind.AssignMod, cr.GetPositionInfo(cr.Position - 2)));
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.Mod, cr.GetPositionInfo(cr.Position - 1)));

                    case '~':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.BitwiseNegate, cr.GetPositionInfo(cr.Position - 1)));

                    case '!':
                        cr.AdvancePosition();
                        if (cr.PeekChar() == '=')
                        {
                            cr.AdvancePosition();
                            return(new Token(Token.TokenKind.CompareNotEqual, cr.GetPositionInfo(cr.Position - 2)));
                        }
                        return(new Token(Token.TokenKind.Not, cr.GetPositionInfo(cr.Position - 1)));

                    case '[':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '?':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.OpenArrayMap, cr.GetPositionInfo(cr.Position - 2)));

                            case '@':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.OpenArrayBaseArray, cr.GetPositionInfo(cr.Position - 2)));

                            case '#':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.OpenArrayGrid, cr.GetPositionInfo(cr.Position - 2)));

                            case '|':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.OpenArrayList, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.OpenArray, cr.GetPositionInfo(cr.Position - 1)));

                    case ']':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.CloseArray, cr.GetPositionInfo(cr.Position - 1)));

                    case '*':
                        cr.AdvancePosition();
                        if (cr.PeekChar() == '=')
                        {
                            cr.AdvancePosition();
                            return(new Token(Token.TokenKind.AssignTimes, cr.GetPositionInfo(cr.Position - 2)));
                        }
                        return(new Token(Token.TokenKind.Times, cr.GetPositionInfo(cr.Position - 1)));

                    case '/':
                        cr.AdvancePosition();
                        if (cr.PeekChar() == '=')
                        {
                            cr.AdvancePosition();
                            return(new Token(Token.TokenKind.AssignDivide, cr.GetPositionInfo(cr.Position - 2)));
                        }
                        return(new Token(Token.TokenKind.Divide, cr.GetPositionInfo(cr.Position - 1)));

                    case '+':
                        cr.AdvancePosition();
                        {
                            char next = cr.PeekChar();
                            if (next == '=')
                            {
                                cr.AdvancePosition();
                                return(new Token(Token.TokenKind.AssignPlus, cr.GetPositionInfo(cr.Position - 2)));
                            }
                            if (next == '+')
                            {
                                cr.AdvancePosition();
                                return(new Token(Token.TokenKind.Increment, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                        return(new Token(Token.TokenKind.Plus, cr.GetPositionInfo(cr.Position - 1)));

                    case '-':
                        cr.AdvancePosition();
                        {
                            char next = cr.PeekChar();
                            if (next == '=')
                            {
                                cr.AdvancePosition();
                                return(new Token(Token.TokenKind.AssignMinus, cr.GetPositionInfo(cr.Position - 2)));
                            }
                            if (next == '-')
                            {
                                cr.AdvancePosition();
                                return(new Token(Token.TokenKind.Decrement, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                        return(new Token(Token.TokenKind.Minus, cr.GetPositionInfo(cr.Position - 1)));    // converted to negate later if necessary

                    case ',':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.Comma, cr.GetPositionInfo(cr.Position - 1)));

                    case '.':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.Dot, cr.GetPositionInfo(cr.Position - 1)));

                    case ':':
                        cr.AdvancePosition();
                        if (cr.PeekChar() == '=')
                        {
                            cr.AdvancePosition();
                            return(new Token(Token.TokenKind.Assign, ":=", cr.GetPositionInfo(cr.Position - 2)));    // Apparently this exists
                        }
                        return(new Token(Token.TokenKind.Colon, cr.GetPositionInfo(cr.Position - 1)));

                    case ';':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.EndStatement, cr.GetPositionInfo(cr.Position - 1)));

                    case '=':
                        cr.AdvancePosition();
                        if (cr.PeekChar() == '=')
                        {
                            cr.AdvancePosition();
                            return(new Token(Token.TokenKind.CompareEqual, cr.GetPositionInfo(cr.Position - 2)));
                        }
                        return(new Token(Token.TokenKind.Assign, "=", cr.GetPositionInfo(cr.Position - 1)));

                    case '<':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '<':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.BitwiseShiftLeft, cr.GetPositionInfo(cr.Position - 2)));

                            case '=':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.CompareLessEqual, cr.GetPositionInfo(cr.Position - 2)));

                            case '>':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.CompareNotEqual, cr.GetPositionInfo(cr.Position - 2)));            // <> exists, it's just legacy
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.CompareLess, cr.GetPositionInfo(cr.Position - 1)));

                    case '>':
                    {
                        char ahead = cr.PeekCharAhead();
                        if (ahead != '\0')
                        {
                            switch (ahead)
                            {
                            case '>':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.BitwiseShiftRight, cr.GetPositionInfo(cr.Position - 2)));

                            case '=':
                                cr.AdvancePosition(2);
                                return(new Token(Token.TokenKind.CompareGreaterEqual, cr.GetPositionInfo(cr.Position - 2)));
                            }
                        }
                    }
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.CompareGreater, cr.GetPositionInfo(cr.Position - 1)));

                    case '?':
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.Conditional, cr.GetPositionInfo(cr.Position - 1)));

                    default:
                        cr.AdvancePosition();
                        return(new Token(Token.TokenKind.Error, c.ToString(), cr.GetPositionInfo(cr.Position - 1)));
                    }
                }
                else
                {
                    // Identifier
                    return(ReadIdentifier(cr));
                }
            }
Esempio n. 6
0
            private static Token ReadStringLiteral(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int  index = cr.Position;
                char type  = cr.PeekChar();

                cr.AdvancePosition();

                char c  = cr.PeekChar();
                char c2 = cr.PeekCharAhead();

                while (!cr.EOF)
                {
                    switch (c)
                    {
                    // Escape character
                    case '\\':
                        if (cr.compileContext.Data?.IsGameMaker2() == false)
                        {
                            sb.Append(c);
                            cr.AdvancePosition();
                            c  = cr.PeekChar();
                            c2 = cr.PeekCharAhead();
                            continue;
                        }
                        cr.AdvancePosition();
                        c  = cr.PeekChar();
                        c2 = cr.PeekCharAhead();
                        switch (c)
                        {
                        case 'a':
                            sb.Append('\a');
                            break;

                        case 'n':
                            sb.Append('\n');
                            break;

                        case 'r':
                            sb.Append('\r');
                            break;

                        case 't':
                            sb.Append('\t');
                            break;

                        case 'v':
                            sb.Append('\v');
                            break;

                        case 'f':
                            sb.Append('\f');
                            break;

                        case 'b':
                            sb.Append('\b');
                            break;

                        case '\n':
                            break;

                        case 'u':
                        {
                            int calc = 0;
                            for (int i = 0; i < 4 && (IsHexCharacter(c2)); i++)
                            {
                                calc *= 16;
                                calc  = (!char.IsDigit(c2)) ? (calc + char.ToLower(c2) - 87) : (calc + c2 - 48);
                                cr.AdvancePosition();
                                c  = cr.PeekChar();
                                c2 = cr.PeekCharAhead();
                            }
                            sb.Append((char)(ushort)calc);
                        }
                        break;

                        case 'x':
                            cr.AdvancePosition();
                            c  = cr.PeekChar();
                            c2 = cr.PeekCharAhead();
                            if (IsHexCharacter(c))
                            {
                                char[] arr = new char[2] {
                                    c, ' '
                                };
                                for (int i = 1; i < 2; i++)
                                {
                                    if (!IsHexCharacter(c2))
                                    {
                                        break;
                                    }
                                    c      = cr.PeekChar();
                                    c2     = cr.PeekCharAhead();
                                    arr[i] = c;
                                }
                                char value = (char)Convert.ToInt32(new string(arr), 16);
                                sb.Append(value);
                            }
                            break;

                        default:
                            if (c >= '0' && c <= '7')
                            {
                                // Octal
                                StringBuilder sb2 = new StringBuilder();
                                sb2.Append(c);
                                for (int i = 1; i < 3; i++)
                                {
                                    if (c2 < '0' || c > '7')
                                    {
                                        break;
                                    }
                                    cr.AdvancePosition();
                                    c = cr.PeekChar();
                                    if (c == '\0')
                                    {
                                        c = ' ';
                                    }
                                    c2 = cr.PeekCharAhead();
                                    if (c2 == '\0')
                                    {
                                        c2 = ' ';
                                    }

                                    sb2.Append(c);
                                }
                                sb.Append(Convert.ToInt32(sb2.ToString(), 8));
                            }
                            else
                            {
                                sb.Append(c);
                            }
                            break;
                        }
                        cr.AdvancePosition();
                        c  = cr.PeekChar();
                        c2 = cr.PeekCharAhead();
                        continue;

                    default:
                        if (c == type)
                        {
                            break;
                        }
                        sb.Append(c);
                        cr.AdvancePosition();
                        c  = cr.PeekChar();
                        c2 = cr.PeekCharAhead();
                        continue;
                    }
                    break;
                }

                cr.AdvancePosition();

                return(new Token(Token.TokenKind.String, sb.ToString(), cr.GetPositionInfo(index)));
            }
Esempio n. 7
0
            private static Token ReadIdentifier(CodeReader cr)
            {
                StringBuilder sb = new StringBuilder();

                int index = cr.Position;

                sb.Append(cr.ReadChar());
                char c = cr.PeekChar();

                while (!cr.EOF && (char.IsLetterOrDigit(c) || c == '_'))
                {
                    sb.Append(c);
                    cr.AdvancePosition();
                    c = cr.PeekChar();
                }

                string identifierText = sb.ToString();

                switch (identifierText)
                {
                default:
                    return(new Token(Token.TokenKind.Identifier, identifierText, cr.GetPositionInfo(index)));

                case "and":
                    return(new Token(Token.TokenKind.LogicalAnd, cr.GetPositionInfo(index)));

                case "or":
                    return(new Token(Token.TokenKind.LogicalOr, cr.GetPositionInfo(index)));

                case "xor":
                    return(new Token(Token.TokenKind.LogicalXor, cr.GetPositionInfo(index)));

                case "while":
                    return(new Token(Token.TokenKind.KeywordWhile, cr.GetPositionInfo(index)));

                case "with":
                    return(new Token(Token.TokenKind.KeywordWith, cr.GetPositionInfo(index)));

                case "if":
                    return(new Token(Token.TokenKind.KeywordIf, cr.GetPositionInfo(index)));

                case "do":
                    return(new Token(Token.TokenKind.KeywordDo, cr.GetPositionInfo(index)));

                case "not":
                    return(new Token(Token.TokenKind.Not, cr.GetPositionInfo(index)));

                case "enum":
                    return(new Token(Token.TokenKind.Enum, cr.GetPositionInfo(index)));

                case "begin":
                    return(new Token(Token.TokenKind.OpenBlock, cr.GetPositionInfo(index)));

                case "end":
                    return(new Token(Token.TokenKind.CloseBlock, cr.GetPositionInfo(index)));

                case "var":
                    return(new Token(Token.TokenKind.KeywordVar, cr.GetPositionInfo(index)));

                case "globalvar":
                    return(new Token(Token.TokenKind.KeywordGlobalVar, cr.GetPositionInfo(index)));

                case "return":
                    return(new Token(Token.TokenKind.KeywordReturn, cr.GetPositionInfo(index)));

                case "default":
                    return(new Token(Token.TokenKind.KeywordDefault, cr.GetPositionInfo(index)));

                case "struct":
                    return(new Token(Token.TokenKind.KeywordStruct, cr.GetPositionInfo(index)));

                case "for":
                    return(new Token(Token.TokenKind.KeywordFor, cr.GetPositionInfo(index)));

                case "case":
                    return(new Token(Token.TokenKind.KeywordCase, cr.GetPositionInfo(index)));

                case "switch":
                    return(new Token(Token.TokenKind.KeywordSwitch, cr.GetPositionInfo(index)));

                case "until":
                    return(new Token(Token.TokenKind.KeywordUntil, cr.GetPositionInfo(index)));

                case "continue":
                    return(new Token(Token.TokenKind.KeywordContinue, cr.GetPositionInfo(index)));

                case "break":
                    return(new Token(Token.TokenKind.KeywordBreak, cr.GetPositionInfo(index)));

                case "else":
                    return(new Token(Token.TokenKind.KeywordElse, cr.GetPositionInfo(index)));

                case "repeat":
                    return(new Token(Token.TokenKind.KeywordRepeat, cr.GetPositionInfo(index)));

                case "exit":
                    return(new Token(Token.TokenKind.KeywordExit, cr.GetPositionInfo(index)));

                case "then":
                    return(new Token(Token.TokenKind.KeywordThen, cr.GetPositionInfo(index)));

                case "mod":
                    return(new Token(Token.TokenKind.Mod, cr.GetPositionInfo(index)));

                case "div":
                    return(new Token(Token.TokenKind.Div, cr.GetPositionInfo(index)));
                }
            }