예제 #1
0
        static void Main(string[] args)
        {
            /*
             * Set up options for the assembler.
             */
            var opt = new AssemblerOptions()
            {
                LanguageOptions = DasmGrammar.Options.Extended,
            };
            var showHelp = false;

            var os = new OptionSet()
            {
                {"t|target=", "target {PATH} for output",
                    a => opt.TargetPath = a},
                {"f|format=", "target {FORMAT}; one of: " + AssemblerOptions.FormatNames,
                    a => opt.TargetFormatFrom(a)},
                {"std", "stick to standard language",
                    a => opt.LanguageOptions = DasmGrammar.Options.Standard},
                {"s|symbols", "output symbol list to TARGET.lst",
                    a => opt.DumpSymbols = (a != null)},
                {"help", "show this message and exit",
                    a => showHelp = a != null},
            };

            var files = new List<string>();
            try
            {
                files = os.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Error.WriteLine(e.Message);
            }

            if (files.Count == 0 || showHelp)
            {
                ShowHelp(os);
                return;
            }

            if (opt.TargetPath == null)
            {
                opt.TargetPath = System.IO.Path.ChangeExtension(files[0], "dcpu");
            }

            opt.SourceFilePaths.AddRange(files);

            /*
             * Do the assemble thing.
             */
            var asm = new Assembler();
            try
            {
                asm.Assemble(opt);
            }
            catch (Codegen.CodegenException e)
            {
                Console.Error.WriteLine(e.Message);
            }
        }
예제 #2
0
        /// <summary>
        /// Performs assembly based on the given options object.
        /// </summary>
        public void Assemble(AssemblerOptions options)
        {
            if (options.SourceFilePaths.Count == 0)
                throw new ArgumentOutOfRangeException("No source files specified.");
            if (options.SourceFilePaths.Count > 1)
                throw new ArgumentOutOfRangeException("Can only assemble one source file right now.");

            /*
             * Parse the source file.
             */

            var sourceFilePath = options.SourceFilePaths[0];
            ParseTreeNode rootNode = null;
            {
                var src = ReadFile(sourceFilePath);

                var g = new DasmGrammar(options.LanguageOptions);
                var ld = new LanguageData(g);
                var p = new Parser(ld);
                var pt = p.Parse(src, sourceFilePath);

                // Emit error messages.
                if (pt.ParserMessages.Count > 0)
                {
                    foreach (var msg in pt.ParserMessages)
                        Error(sourceFilePath, msg.Location, msg.Message);
                    throw new CodegenException("Compilation failed.");
                }

                rootNode = pt.Root;
            }

            /*
             * Do codegen.
             */

            DasmCodegen.CgResult cgr;
            {
                var cg = new DasmCodegen();
                cgr = cg.CgProgram(rootNode);
            }

            /*
             * Write the output file.
             */

            using (var target = OpenFile(options.TargetPath, FileMode.Create))
            {
                switch (options.TargetFormat)
                {
                    case ImageFormat.Binary:
                        foreach (var word in cgr.Image)
                        {
                            target.WriteByte((byte)(word & 0xFF));
                            target.WriteByte((byte)(word >> 8));
                        }
                        break;

                    case ImageFormat.Hexadecimal:
                        {
                            const int HexWidth = 8;
                            using (var tw = new StreamWriter(target))
                            {
                                for (var i = 0; i < cgr.Image.Length; ++i)
                                {
                                    tw.Write(string.Format("{0:x4}", cgr.Image[i]));
                                    tw.Write(i % HexWidth == (HexWidth - 1) ? tw.NewLine : " ");
                                }
                                tw.WriteLine();
                            }
                        }
                        break;

                    case ImageFormat.HexWithAddress:
                        {
                            const int HexWidth = 8;
                            using (var tw = new StreamWriter(target))
                            {
                                for (var i = 0; i < cgr.Image.Length; ++i)
                                {
                                    if (i % HexWidth == 0)
                                        tw.Write(string.Format("{0:x4} ", i));

                                    tw.Write(string.Format("{0:x4}", cgr.Image[i]));
                                    tw.Write(i % HexWidth == (HexWidth - 1) ? tw.NewLine : " ");
                                }
                                tw.WriteLine();
                            }
                        }
                        break;

                    case ImageFormat.AssemblyHex:
                        {
                            const int HexWidth = 8;
                            using (var tw = new StreamWriter(target))
                            {
                                for (var i = 0; i < cgr.Image.Length; ++i)
                                {
                                    if (i % HexWidth == 0)
                                        tw.Write("dat ");

                                    tw.Write(string.Format("0x{0:x4}", cgr.Image[i]));
                                    tw.Write(
                                        (i % HexWidth == (HexWidth - 1))
                                            || (i + 1 == cgr.Image.Length)
                                        ? tw.NewLine
                                        : ", ");
                                }
                                tw.WriteLine();
                            }
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                }
            }

            /*
             * Generate symbol map.
             */

            if (options.DumpSymbols)
            {
                using (var f = OpenFile(
                    Path.ChangeExtension(options.TargetPath, "sym"),
                    FileMode.Create))
                {
                    {
                        using (var tw = new StreamWriter(f))
                        {
                            foreach (var label in cgr.Labels)
                                tw.WriteLine("{0:X4} {1} {2}",
                                    label.Value,
                                    label.Type.ToShorthand(),
                                    label.Name);
                        }
                    }
                }
            }
        }