Exemplo n.º 1
0
        public static bool IsReservedWord(string str)
        {
            if (str == null)
            {
                return(false);
            }

            if (InstructionSet.IsConditionFlag(str) ||
                InstructionSet.IsValidInstructionName(str) ||
                InstructionSet.IsValidRegister(str))
            {
                return(true);
            }

            switch (str.ToUpperInvariant())
            {
            case "ORG":
            case "SEEK":
            case "END":
            case "INCLUDE":
            case "INCBIN":
            case "EQU":
            case "DB":
            case "DEFB":
            case "DEFM":
            case "DW":
            case "DEFW":
            case "DS":
            case "DEFS":
            case "IF":
            case "ENDIF":
            case "ELSE":
            case "ELSEIF":
            case "PROC":
            case "ENDP":
            case "MACRO":
            case "ENDM":
            case "DEFBITS":
            case "BITMAP":
            case "ENDB":
            case "ERROR":
            case "WARNING":
            case "RADIX":
            case "STRUCT":
            case "ENDS":
            case "BYTE":
            case "WORD":
                return(true);
            }

            return(false);
        }
Exemplo n.º 2
0
        ExprNode ParseLeaf()
        {
            var pos = _tokenizer.TokenPosition;

            // Number literal?
            if (_tokenizer.Token == Token.Number)
            {
                var node = new ExprNodeNumberLiteral(pos, _tokenizer.TokenNumber);
                _tokenizer.Next();
                return(node);
            }

            // String literal?
            if (_tokenizer.Token == Token.String)
            {
                var str = _tokenizer.TokenString;
                _tokenizer.Next();
                return(new ExprNodeStringLiteral(pos, str));
            }

            // Defined operator?
            if (_tokenizer.TrySkipIdentifier("defined"))
            {
                _tokenizer.SkipToken(Token.OpenRound);
                _tokenizer.CheckToken(Token.Identifier);
                var node = new ExprNodeIsDefined(pos, _tokenizer.TokenString);
                _tokenizer.Next();
                _tokenizer.SkipToken(Token.CloseRound);
                return(node);
            }

            // Sizeof operator?
            if (_tokenizer.TrySkipIdentifier("sizeof"))
            {
                _tokenizer.SkipToken(Token.OpenRound);
                var node = new ExprNodeSizeOf(pos, ParseExpression());
                _tokenizer.SkipToken(Token.CloseRound);
                return(node);
            }

            // Identifier
            if (_tokenizer.Token == Token.Identifier)
            {
                // Special identifier
                if (InstructionSet.IsConditionFlag(_tokenizer.TokenString) ||
                    InstructionSet.IsValidRegister(_tokenizer.TokenString))
                {
                    var node = new ExprNodeRegisterOrFlag(pos, _tokenizer.TokenString);
                    _tokenizer.Next();
                    return(node);
                }
                else
                {
                    var node = new ExprNodeIdentifier(pos, _tokenizer.TokenString);
                    _tokenizer.Next();

                    if (_tokenizer.Token == Token.Period)
                    {
                        ExprNode retNode = node;
                        while (_tokenizer.TrySkipToken(Token.Period))
                        {
                            _tokenizer.CheckToken(Token.Identifier);
                            retNode = new ExprNodeMember(_tokenizer.TokenPosition, _tokenizer.TokenString, retNode);
                            _tokenizer.Next();
                        }
                        return(retNode);
                    }

                    if (_tokenizer.Token == Token.OpenRound)
                    {
                        node.Arguments = ParseArgumentList();
                    }

                    return(node);
                }
            }

            // Parens?
            if (_tokenizer.TrySkipToken(Token.OpenRound))
            {
                var node = ParseExpressionList();
                _tokenizer.SkipToken(Token.CloseRound);
                return(node);
            }

            // Array?
            if (_tokenizer.Token == Token.OpenSquare)
            {
                return(ParseOrderedStructData());
            }

            // Map?
            if (_tokenizer.Token == Token.OpenBrace)
            {
                return(ParseNamedStructData());
            }

            throw new CodeException($"syntax error in expression: {Tokenizer.DescribeToken(_tokenizer.Token, _tokenizer.TokenRaw)}", _tokenizer.TokenPosition);
        }
Exemplo n.º 3
0
        AstElement ParseAstElement()
        {
            // EOF?
            if (_tokenizer.Token == Token.EOF)
            {
                return(null);
            }

            // Blank line?
            if (_tokenizer.Token == Token.EOL)
            {
                return(null);
            }

            // ORG Element
            if (_tokenizer.TrySkipIdentifier("ORG"))
            {
                return(new AstOrgElement(ParseExpression()));
            }

            // SEEK Element
            if (_tokenizer.TrySkipIdentifier("SEEK"))
            {
                return(new AstSeekElement(ParseExpression()));
            }

            // END Element
            if (_tokenizer.TrySkipIdentifier("END"))
            {
                while (_tokenizer.Token != Token.EOF)
                {
                    _tokenizer.Next();
                }
                return(null);
            }

            // Include?
            if (_tokenizer.TrySkipIdentifier("INCLUDE"))
            {
                // Load the include file
                string includeFile = ParseIncludePath();

                // Check for recursive inclusion of the same file
                if (IsParsing(includeFile))
                {
                    throw new CodeException($"error: recursive include file {_tokenizer.TokenRaw}", _tokenizer.TokenPosition);
                }

                string includeText;
                try
                {
                    includeText = System.IO.File.ReadAllText(includeFile);
                }
                catch (Exception x)
                {
                    throw new CodeException($"error: include file '{_tokenizer.TokenRaw}' - {x.Message}", _tokenizer.TokenPosition);
                }

                // Parse it
                var p = new Parser();
                p.OuterParser = this;
                var content = p.Parse(new StringSource(includeText + "\n", System.IO.Path.GetFileName(includeFile), includeFile));

                // Skip the filename
                _tokenizer.Next();

                // Return element
                return(new AstInclude(includeFile, content));
            }

            // IncBin?
            if (_tokenizer.TrySkipIdentifier("INCBIN"))
            {
                // Load the include file
                string includeFile = ParseIncludePath();
                byte[] includeBytes;
                try
                {
                    includeBytes = System.IO.File.ReadAllBytes(includeFile);
                }
                catch (Exception x)
                {
                    throw new CodeException($"error loading incbin file '{includeFile}' - {x.Message}", _tokenizer.TokenPosition);
                }

                // Skip the filename
                _tokenizer.Next();

                // Return element
                return(new AstIncBin(includeFile, includeBytes));
            }

            // DB?

            /*
             * if (_tokenizer.TrySkipIdentifier("DB") || _tokenizer.TrySkipIdentifier("DEFB")
             || _tokenizer.TrySkipIdentifier("DM") || _tokenizer.TrySkipIdentifier("DEFM"))
             ||{
             || var elem = new AstDbElement();
             || ParseDxExpressions(elem);
             || return elem;
             ||}
             ||
             ||// DW?
             ||if (_tokenizer.TrySkipIdentifier("DW") || _tokenizer.TrySkipIdentifier("DEFW"))
             ||{
             || var elem = new AstDwElement();
             || ParseDxExpressions(elem);
             || return elem;
             ||}
             */

            // DS?
            if (_tokenizer.TrySkipIdentifier("DS") || _tokenizer.TrySkipIdentifier("DEFS"))
            {
                var elem = new AstDsElement(ParseExpression());
                if (_tokenizer.TrySkipToken(Token.Comma))
                {
                    elem.ValueExpression = ParseExpression();
                }
                return(elem);
            }

            // IF Block
            if (_tokenizer.TrySkipIdentifier("IF"))
            {
                return(ParseConditional());
            }

            // PROC?
            if (_tokenizer.TrySkipIdentifier("PROC"))
            {
                _tokenizer.SkipToken(Token.EOL);

                var proc = new AstProc();
                ParseIntoContainer(proc);

                _tokenizer.SkipIdentifier("ENDP");

                return(proc);
            }

            // RADIX
            if (_tokenizer.IsIdentifier("RADIX"))
            {
                var saveRadix = _tokenizer.DefaultRadix;
                try
                {
                    _tokenizer.DefaultRadix = 10;
                    _tokenizer.Next();
                    _tokenizer.CheckToken(Token.Number);

                    switch (_tokenizer.TokenNumber)
                    {
                    case 2:
                    case 8:
                    case 10:
                    case 16:
                        break;

                    default:
                        throw new CodeException("Invalid radix - must be 2, 8, 10, or 16", _tokenizer.TokenPosition);
                    }

                    _tokenizer.DefaultRadix = (int)_tokenizer.TokenNumber;
                    _tokenizer.Next();
                    return(null);
                }
                catch
                {
                    _tokenizer.DefaultRadix = saveRadix;
                    throw;
                }
            }

            // Error
            if (_tokenizer.TrySkipIdentifier("ERROR"))
            {
                _tokenizer.CheckToken(Token.String);
                var message = _tokenizer.TokenString;
                _tokenizer.Next();

                return(new AstErrorWarning(message, false));
            }

            // Warning
            if (_tokenizer.TrySkipIdentifier("WARNING"))
            {
                _tokenizer.CheckToken(Token.String);
                var message = _tokenizer.TokenString;
                _tokenizer.Next();

                return(new AstErrorWarning(message, true));
            }

            // DEFBITS?
            if (_tokenizer.TrySkipIdentifier("DEFBITS"))
            {
                // Get the character
                _tokenizer.CheckToken(Token.String);
                var character = _tokenizer.TokenString;
                _tokenizer.Next();

                // Skip the comma
                _tokenizer.SkipToken(Token.Comma);

                if (_tokenizer.Token == Token.String)
                {
                    // Get the bit pattern
                    _tokenizer.CheckToken(Token.String);
                    var bitPattern = _tokenizer.TokenString;
                    _tokenizer.Next();
                    return(new AstDefBits(character, bitPattern));
                }
                else
                {
                    var bitWidth = ParseExpression();
                    _tokenizer.SkipToken(Token.Comma);
                    var value = ParseExpression();
                    return(new AstDefBits(character, value, bitWidth));
                }
            }

            // BITMAP
            if (_tokenizer.TrySkipIdentifier("BITMAP"))
            {
                // Parse width and height
                var width = ParseExpression();
                _tokenizer.SkipToken(Token.Comma);
                var height = ParseExpression();

                // Bit order spec?
                bool msbFirst = true;
                if (_tokenizer.TrySkipToken(Token.Comma))
                {
                    if (_tokenizer.TrySkipIdentifier("msb"))
                    {
                        msbFirst = true;
                    }
                    else if (_tokenizer.TrySkipIdentifier("lsb"))
                    {
                        msbFirst = false;
                    }
                    else
                    {
                        throw new CodeException("Expected 'MSB' or 'LSB'", _tokenizer.TokenPosition);
                    }
                }

                // Create bitmap ast element
                var bitmap = new AstBitmap(width, height, msbFirst);

                // Move to next line
                _tokenizer.SkipToken(Token.EOL);

                // Consume all strings, one per line
                while (_tokenizer.Token == Token.String)
                {
                    bitmap.AddString(_tokenizer.TokenString);
                    _tokenizer.Next();
                    _tokenizer.SkipToken(Token.EOL);
                    continue;
                }

                // Skip the end dilimeter
                bitmap.EndPosition = _tokenizer.TokenPosition;
                _tokenizer.SkipIdentifier("ENDB");
                return(bitmap);
            }

            if (_tokenizer.Token == Token.Identifier)
            {
                // Remember the name
                var pos  = _tokenizer.TokenPosition;
                var name = _tokenizer.TokenString;
                _tokenizer.Next();
                string[] paramNames = null;

                // Parameterized EQU?
                if (_tokenizer.Token == Token.OpenRound && !IsReservedWord(name))
                {
                    paramNames = ParseParameterNames();
                }

                // Followed by colon?
                bool haveColon = false;
                if (_tokenizer.TrySkipToken(Token.Colon))
                {
                    haveColon = true;
                }

                // EQU?
                if (_tokenizer.TrySkipIdentifier("EQU"))
                {
                    return(new AstEquate(name, ParseOperandExpression(), pos)
                    {
                        ParameterNames = paramNames,
                    });
                }

                // MACRO?
                if (_tokenizer.TrySkipIdentifier("MACRO"))
                {
                    _tokenizer.SkipToken(Token.EOL);

                    var macro = new AstMacroDefinition(name, paramNames);
                    ParseIntoContainer(macro);

                    _tokenizer.SkipIdentifier("ENDM");

                    return(macro);
                }

                // STRUCT?
                if (_tokenizer.TrySkipIdentifier("STRUCT"))
                {
                    var structDef = new AstStructDefinition(name);

                    // Process field definitions
                    while (_tokenizer.Token != Token.EOF)
                    {
                        // Skip blank lines
                        if (_tokenizer.TrySkipToken(Token.EOL))
                        {
                            continue;
                        }

                        // End of struct
                        if (_tokenizer.TrySkipIdentifier("ENDS"))
                        {
                            break;
                        }

                        // Capture the field name (or could be type name)
                        var fieldDefPos = _tokenizer.TokenPosition;
                        var fieldName   = (string)null;

                        if (!_tokenizer.TrySkipToken(Token.Colon))
                        {
                            _tokenizer.CheckToken(Token.Identifier);
                            fieldName = _tokenizer.TokenString;

                            // Next token
                            _tokenizer.Next();
                        }

                        // Must be an identifier (for the type name)
                        _tokenizer.CheckToken(Token.Identifier);
                        var fieldType = _tokenizer.TokenString;
                        _tokenizer.Next();

                        // Add the field definition
                        structDef.AddField(new AstFieldDefinition(fieldDefPos, fieldName, fieldType, ParseExpressionList()));

                        _tokenizer.SkipToken(Token.EOL);
                    }

                    _tokenizer.SkipToken(Token.EOL);
                    return(structDef);
                }

                // Nothing from here on expected parameters
                if (paramNames != null)
                {
                    throw new CodeException("Unexpected parameter list in label", pos);
                }

                // Was it a label?
                if (haveColon)
                {
                    if (IsReservedWord(name))
                    {
                        throw new CodeException($"Unexpected colon after reserved word '{name}'", pos);
                    }

                    return(new AstLabel(name, pos));
                }

                // Is it an instruction?
                if (InstructionSet.IsValidInstructionName(name))
                {
                    return(ParseInstruction(pos, name));
                }

                // Must be a macro invocation or a data declaration
                return(ParseMacroInvocationOrDataDeclaration(pos, name));
            }

            // What?
            throw _tokenizer.Unexpected();
        }
Exemplo n.º 4
0
        public override void Layout(AstScope currentScope, LayoutContext ctx)
        {
            var sb = new StringBuilder();

            sb.Append(_mnemonic);

            for (int i = 0; i < _operands.Count; i++)
            {
                if (i > 0)
                {
                    sb.Append(",");
                }
                else
                {
                    sb.Append(" ");
                }

                var o = _operands[i];

                var addressingMode = o.GetAddressingMode(currentScope);

                if ((addressingMode & AddressingMode.SubOp) != 0)
                {
                    sb.Append(o.GetSubOp());
                    sb.Append(" ");
                    addressingMode = addressingMode & ~AddressingMode.SubOp;
                }

                switch (addressingMode)
                {
                case AddressingMode.Deref | AddressingMode.Immediate:
                    sb.Append($"(?)");
                    break;

                case AddressingMode.Deref | AddressingMode.Register:
                {
                    var reg = o.GetRegister(currentScope);
                    if (IsIndexRegister(reg))
                    {
                        sb.Append($"({reg}+?)");
                    }
                    else
                    {
                        sb.Append($"({reg})");
                    }
                }
                break;

                case AddressingMode.Deref | AddressingMode.RegisterPlusImmediate:
                    sb.Append($"({o.GetRegister(currentScope)}+?)");
                    break;

                case AddressingMode.Immediate:
                    sb.Append($"?");
                    break;

                case AddressingMode.Register:
                    sb.Append($"{o.GetRegister(currentScope)}");
                    break;

                case AddressingMode.RegisterPlusImmediate:
                    sb.Append($"{o.GetRegister(currentScope)}+?");
                    break;

                default:
                    sb.Append($"<illegal expression>");
                    break;
                }
            }

            _instruction = InstructionSet.Find(sb.ToString());

            if (_instruction == null)
            {
                Log.Error(_position, $"invalid addressing mode: {sb.ToString()}");
            }
            else
            {
                ctx.ReserveBytes(_instruction.Length);
            }
        }
Exemplo n.º 5
0
        public bool ProcessArg(string arg)
        {
            if (arg == null)
            {
                return(true);
            }

            if (arg.StartsWith("#"))
            {
                return(true);
            }

            // Response file
            if (arg.StartsWith("@"))
            {
                // Get the fully qualified response file name
                string strResponseFile = System.IO.Path.GetFullPath(arg.Substring(1));

                // Load and parse the response file
                var args = Utils.ParseCommandLine(System.IO.File.ReadAllText(strResponseFile));

                // Set the current directory
                string OldCurrentDir = System.IO.Directory.GetCurrentDirectory();
                System.IO.Directory.SetCurrentDirectory(System.IO.Path.GetDirectoryName(strResponseFile));

                // Load the file
                bool bRetv = ProcessArgs(args);

                // Restore current directory
                System.IO.Directory.SetCurrentDirectory(OldCurrentDir);

                return(bRetv);
            }

            // Args are in format [/-]<switchname>[:<value>];
            if (arg.StartsWith("/") || arg.StartsWith("-"))
            {
                string SwitchName = arg.Substring(arg.StartsWith("--") ? 2 : 1);
                string Value      = null;

                int colonpos = SwitchName.IndexOf(':');
                if (colonpos >= 0)
                {
                    // Split it
                    Value      = SwitchName.Substring(colonpos + 1);
                    SwitchName = SwitchName.Substring(0, colonpos);
                }

                switch (SwitchName)
                {
                case "help":
                case "h":
                case "?":
                    ShowLogo();
                    ShowHelp();
                    return(false);

                case "v":
                    ShowLogo();
                    return(false);

                case "instructionSet":
                    InstructionSet.DumpAll();
                    return(false);

                case "ast":
                    if (Value != null)
                    {
                        _astFile = Value;
                    }
                    else
                    {
                        _astFile = ":default";
                    }
                    break;

                case "sym":
                    if (Value != null)
                    {
                        _symbolsFile = Value;
                    }
                    else
                    {
                        _symbolsFile = ":default";
                    }
                    break;

                case "lst":
                case "list":
                    if (Value != null)
                    {
                        _listFile = Value;
                    }
                    else
                    {
                        _listFile = ":default";
                    }
                    break;

                case "define":
                    if (Value == null)
                    {
                        throw new InvalidOperationException("--define: requires argument value");
                    }
                    else
                    {
                        var eqPos = Value.IndexOf('=');
                        if (eqPos < 0)
                        {
                            _userDefines.Add(Value, null);
                        }
                        else
                        {
                            _userDefines.Add(Value.Substring(0, eqPos), Value.Substring(eqPos + 1));
                        }
                    }
                    break;

                case "output":
                    if (Value == null)
                    {
                        throw new InvalidOperationException("--output: requires argument value");
                    }
                    else
                    {
                        _outputFile = Value;
                    }
                    break;

                case "include":
                    if (Value == null)
                    {
                        throw new InvalidOperationException("--include: requires argument value");
                    }
                    else
                    {
                        try
                        {
                            _includePaths.Add(System.IO.Path.GetFullPath(Value));
                        }
                        catch (Exception x)
                        {
                            throw new InvalidOperationException($"Invalid include path: {Value} - {x.Message}");
                        }
                    }
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Unknown switch '{0}'", arg));
                }
            }
            else
            {
                if (_inputFile == null)
                {
                    _inputFile = arg;
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Too many command line arguments, don't know what to do with '{0}'", arg));
                }
            }

            return(true);
        }