Example #1
0
        List <SourceLine> ProcessFromStream(string fileName, int lineNumber, StreamReader sr, bool stopAtFirstInstruction = false)
        {
            var          sourceLines     = new List <SourceLine>();
            var          lineSources     = new List <string>();
            var          blockComment    = false;
            var          readyForNewLine = true;
            var          expected        = TokenType.LabelInstr;
            var          previousType    = TokenType.None;
            var          opens           = new Stack <char>();
            Macro        definingMacro   = null;
            string       nextLine;
            var          stopProcessing  = false;
            var          previousWasPlus = false;
            List <Token> tokens          = null;
            var          linesProcessed  = lineNumber;

            while ((nextLine = sr.ReadLine()) != null && !stopProcessing)
            {
                if (readyForNewLine)
                {
                    StartNewLine();
                }
                else
                {
                    lineSources.Add(nextLine);
                }

                linesProcessed++;
                var  it = nextLine.GetIterator();
                char c;
                var  previous = EOS;
                var  isWidth  = false;
                while (!_lineHasErrors && (c = it.GetNext()) != EOS)
                {
                    if (char.IsWhiteSpace(c))
                    {
                        while (c == ' ' || c == '\t')
                        {
                            previous = c;
                            c        = it.GetNext();
                        }
                        if (c == EOS)
                        {
                            break;
                        }
                    }
                    if (blockComment)
                    {
                        if (c == '*' && it.PeekNext() == '/')
                        {
                            blockComment = !it.MoveNext();
                        }
                        continue;
                    }
                    char peek = it.PeekNext();

                    if (c == '/' && peek == '/')
                    {
                        break;
                    }
                    if (c == '*' && peek == '/')
                    {
                        LogError(fileName, lineNumber, it.Index + 1, "\"*/\" does not close a block comment.");
                        break;
                    }
                    if (c == '/' && peek == '*')
                    {
                        it.MoveNext();
                        blockComment = true;
                        continue;
                    }
                    if (c == ';')
                    {
                        if (!_options.IgnoreCommentColons)
                        {
                            expected = TokenType.Instruction;
                            c        = it.FirstOrDefault(chr => chr == ':');
                        }
                        else
                        {
                            c = EOS;
                        }
                        if (c == EOS)
                        {
                            break;
                        }
                    }
                    if (c == ':')
                    {
                        if ((expected != TokenType.Instruction && expected != TokenType.EndOrBinary &&
                             (tokens.Count == 0 || tokens[^ 1].Type != TokenType.Instruction)) || !LineTerminates())
                        {
                            LogError(fileName, lineNumber, it.Index + 1, "Unexpected expression.");
                            break;
                        }
                        lineSources[^ 1] = lineSources[^ 1].Substring(0, it.Index);
Example #2
0
        IEnumerable <SourceLine> ProcessMacros(IEnumerable <SourceLine> uncommented)
        {
            var macroProcessed = new List <SourceLine>();
            RandomAccessIterator <SourceLine> lineIterator = uncommented.GetIterator();
            SourceLine line = null;

            while ((line = lineIterator.GetNext()) != null)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(line.ParsedSource))
                    {
                        macroProcessed.Add(line);
                        continue;
                    }
                    if (line.InstructionName.Equals(".macro"))
                    {
                        if (string.IsNullOrEmpty(line.LabelName))
                        {
                            Assembler.Log.LogEntry(line, line.Instruction, "Macro name not specified.");
                            continue;
                        }
                        var macroName = "." + line.LabelName;

                        if (_macros.ContainsKey(macroName))
                        {
                            Assembler.Log.LogEntry(line, line.Label, $"Macro named \"{line.LabelName}\" already defined.");
                            continue;
                        }
                        if (Assembler.IsReserved.Any(i => i.Invoke(macroName)) ||
                            !char.IsLetter(line.LabelName[0]))
                        {
                            Assembler.Log.LogEntry(line, line.Label, $"Macro name \"{line.LabelName}\" is not valid.");
                            continue;
                        }
                        Reserved.AddWord("MacroNames", macroName);

                        var compare = Assembler.Options.CaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
                        var macro   = new Macro(line.Operand, line.ParsedSource, compare);
                        _macros[macroName] = macro;
                        var instr = line;
                        while ((line = lineIterator.GetNext()) != null && !line.InstructionName.Equals(".endmacro"))
                        {
                            if (macroName.Equals(line.InstructionName))
                            {
                                Assembler.Log.LogEntry(line, line.Instruction, "Recursive macro call not allowed.");
                                continue;
                            }
                            if (line.InstructionName.Equals(".macro"))
                            {
                                Assembler.Log.LogEntry(line, line.Instruction, "Nested macro definitions not allowed.");
                                continue;
                            }
                            if (line.InstructionName.Equals(".include") || line.InstructionName.Equals(".binclude"))
                            {
                                var includes = ExpandInclude(line);
                                foreach (var incl in includes)
                                {
                                    if (macroName.Equals(incl.InstructionName))
                                    {
                                        Assembler.Log.LogEntry(incl, incl.Instruction, "Recursive macro call not allowed.");
                                        continue;
                                    }
                                    macro.AddSource(incl);
                                }
                            }
                            else
                            {
                                macro.AddSource(line);
                            }
                        }
                        if (!string.IsNullOrEmpty(line.LabelName))
                        {
                            if (line.OperandHasToken)
                            {
                                Assembler.Log.LogEntry(line, line.Operand, "Unexpected argument found for macro definition closure.");
                                continue;
                            }
                            line.Instruction  = null;
                            line.ParsedSource = line.ParsedSource.Replace(".endmacro", string.Empty);
                            macro.AddSource(line);
                        }
                        else if (line == null)
                        {
                            line = instr;
                            Assembler.Log.LogEntry(instr, instr.Instruction, "Missing closure for macro definition.");
                            continue;
                        }
                    }
                    else if (line.InstructionName.Equals(".include") || line.InstructionName.Equals(".binclude"))
                    {
                        macroProcessed.AddRange(ExpandInclude(line));
                    }
                    else if (_macros.ContainsKey(line.InstructionName))
                    {
                        if (!string.IsNullOrEmpty(line.LabelName))
                        {
                            SourceLine clone = line.Clone();
                            clone.Operand          =
                                clone.Instruction  = null;
                            clone.UnparsedSource   =
                                clone.ParsedSource = line.LabelName;
                            macroProcessed.Add(clone);
                        }
                        Macro macro = _macros[line.InstructionName];
                        macroProcessed.AddRange(ProcessExpansion(macro.Expand(line.Operand)));
                    }
                    else if (line.InstructionName.Equals(".endmacro"))
                    {
                        Assembler.Log.LogEntry(line, line.Instruction,
                                               "Directive \".endmacro\" does not close a macro definition.");
                        continue;
                    }
                    else
                    {
                        macroProcessed.Add(line);
                    }
                }
                catch (ExpressionException ex)
                {
                    Assembler.Log.LogEntry(line, ex.Position, ex.Message);
                }
            }
            return(macroProcessed);
        }