Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="line">The line of code to parse.</param>
        /// <param name="sourceLine">The line number of the code file.</param>
        void ParseLine(StringSection line, int iSourceLine, out Error error)
        {
            error = Error.None;

            line = line.TrimLeft();
            RemoveComments(ref line);

            int newInstructionIndex = assembly.ParsedInstructions.Count;

            bool loopLabel;

            do   // This loop allows us to parse alternating named and anonymous labels (* label: +++ -- anotherLabel:)
            {
                loopLabel  = false;
                loopLabel |= ParseNamedLabels(ref line, newInstructionIndex, iSourceLine);
                loopLabel |= ParseAnonymousLabel(ref line, newInstructionIndex, iSourceLine);
            } while (loopLabel);

            if (line.IsNullOrEmpty || line[0] == ';')
            {
                // Nothing on this line
                return;
            }

            // Dot-prefixed directive
            if (line[0] == '.')
            {
                line = line.Substring(1);
                var directiveName = GetSymbol(line);
                line = line.Substring(directiveName.Length).TrimLeft();
                if (!ParseDirective(directiveName, line, iSourceLine, out error))
                {
                    error = new Error(ErrorCode.Directive_Not_Defined, string.Format(Error.Msg_DirectiveUndefined_name, directiveName), iSourceLine);
                    return;
                }
                return;
            }



            bool parsedUncolonedLabel = false; // Set to true when an uncoloned label is found so we don't look for one again.
            bool loopAgain            = false; // Set to true when an uncoloned label is found to loop back and try to parse the remaining text

            do
            {
                loopAgain = false;

                var symbol = GetSymbol(line);
                if (symbol.Length == 0)
                {
                    break;
                }
                line = line.Substring(symbol.Length).Trim();

                if (ParseDirective(symbol, line, iSourceLine, out error))
                {
                    return;
                }
                else if (ParseInstruction(symbol, line, iSourceLine, out error))
                {
                    return;
                }
                else if ((line.Length > 0 && line[0] == '=') || (line.Length > 1 && line[0] == ':' && line[1] == '='))     // Assignments and label assignments
                // := is a cross between a label and assignment: It declares a label with an explicit value.
                {
                    bool isLabel = (line[0] == ':');

                    var expression = line.Substring(1).TrimLeft();
                    if (isLabel)
                    {
                        expression = expression.Substring(1).TrimLeft();
                    }

                    if (expression.IsNullOrEmpty)
                    {
                        error = new Error(ErrorCode.Expected_Expression, Error.Msg_ExpectedValue, iSourceLine);
                    }
                    else
                    {
                        ParseAssignment(symbol, isLabel, expression, iSourceLine);
                    }
                }
                else
                {
                    // Todo: ensure 'symbol' is a valid label name
                    if (!Assembler.RequireColonOnLabels && !parsedUncolonedLabel && symbol.Length > 0)
                    {
                        if (symbol[0] == '@')
                        {
                            string labelName = mostRecentNamedLabel + "." + symbol.Substring(1).ToString();
                            assembly.Labels.Add(new Label(labelName, newInstructionIndex, iSourceLine, true));
                        }
                        else
                        {
                            mostRecentNamedLabel = symbol.ToString();
                            assembly.Labels.Add(new Label(symbol.ToString(), newInstructionIndex, iSourceLine, false));
                        }
                        parsedUncolonedLabel = true;
                        loopAgain            = true;
                    }
                    else
                    {
                        error = new Error(ErrorCode.Unexpected_Text, Error.Msg_BadLine, iSourceLine);
                    }
                }
            } while (parsedUncolonedLabel && loopAgain);
        }