예제 #1
0
        public override void Layout(AstScope currentScope, LayoutContext ctx)
        {
            // Is it a data declaration?
            _dataType = currentScope.FindSymbol(_macroOrDataTypeName) as AstType;
            if (_dataType != null)
            {
                // Work out how many elements in total
                int totalElements = 0;
                foreach (var n in _operands)
                {
                    totalElements += n.EnumData(currentScope).Count();
                }

                // Reserve space
                ctx.ReserveBytes(_reservedBytes = totalElements * _dataType.SizeOf);

                return;
            }

            // Is it a macro invocation?
            _macroDefinition = currentScope.FindSymbol(_macroOrDataTypeName + ExprNodeParameterized.MakeSuffix(_operands.Count)) as AstMacroDefinition;
            if (_macroDefinition != null)
            {
                // Create resolved scope
                _resolvedScope = _macroDefinition.Resolve(currentScope, _operands.ToArray());

                // Define macro symbols
                _macroDefinition.DefineSymbolsResolved(_resolvedScope);

                // Layout
                _macroDefinition.LayoutResolved(_resolvedScope, ctx);

                return;
            }

            throw new CodeException($"Unrecognized symbol: '{_macroOrDataTypeName}' is not a known data type or macro (with {_operands.Count} arguments)", SourcePosition);
        }
예제 #2
0
파일: Parser.cs 프로젝트: m4k3r-org/yazd
        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();
        }