Example #1
0
 /// <summary>
 /// Increment the pass counter.
 /// </summary>
 /// <returns>The new value of the pass counter.</returns>
 public int DoNewPass()
 {
     CurrentPass++;
     SymbolManager.DefineGlobal("CURRENT_PASS", CurrentPass + 1);
     PassChanged?.Invoke(this, new EventArgs());
     PassNeeded = false;
     return(CurrentPass);
 }
Example #2
0
 /// <summary>
 /// Creates a new instance of the assembly service.
 /// </summary>
 /// <param name="options">The parsed options.</param>
 public AssemblyServices(Options options)
 {
     PassNeeded             = true;
     CurrentPass            = -1;
     IsReserved             = new List <Func <StringView, bool> >();
     InstructionLookupRules = new List <Func <StringView, bool> > {
         sv => sv[0] == '.'
     };
     Options      = options;
     OutputFormat = Options.Format;
     CPU          = Options.CPU;
     Encoding     = new AsmEncoding(Options.CaseSensitive);
     Evaluator    = new Evaluator(Options.CaseSensitive)
     {
         SymbolEvaluator = EvaluateSymbol
     };
     SymbolManager = new SymbolManager(options.CaseSensitive, Evaluator);
     SymbolManager.AddValidSymbolNameCriterion(s => !Evaluator.IsReserved(s));
     Log    = new ErrorLog(Options.WarningsAsErrors);
     Output = new BinaryOutput(true, Options.CaseSensitive, Options.LongAddressing);
 }
Example #3
0
        /// <summary>
        /// Initializes the <see cref="Assembler"/> class for use. Repeated calls will reset symbol labels and variables,
        /// assembling pass and listing printing states, the binary output, and the error log.
        /// </summary>
        /// <param name="args">The command line arguments passed by the user.</param>
        public static void Initialize(string[] args)
        {
            PassChanged            = null;
            PrintOff               = false;
            PassNeeded             = true;
            _pass                  = -1;
            LineIterator           = null;
            Options                = new CommandLineOptions();
            IsReserved             = new List <Func <string, bool> >();
            InstructionLookupRules = new List <Func <string, bool> >();
            if (args != null)
            {
                Options.ParseArgs(args);
            }


            Encoding      = new AsmEncoding(Options.CaseSensitive);
            SymbolManager = new SymbolManager(Options.CaseSensitive);
            Evaluator.Initialize();
            Evaluator.AddFunctionEvaluator(SymbolManager);
            Log    = new ErrorLog();
            Output = new BinaryOutput();
        }
Example #4
0
        double EvaluateSymbol(RandomAccessIterator <Token> tokens)
        {
            var token     = tokens.Current;
            var subscript = -1;
            var converted = double.NaN;
            var isString  = token.IsDoubleQuote();

            if (char.IsLetter(token.Name[0]) || token.Name[0] == '_')
            {
                var next = tokens.GetNext();
                if (next != null && next.IsOpen() && next.Name.Equals("["))
                {
                    subscript = (int)Evaluator.Evaluate(tokens, 0, int.MaxValue);
                }
                var symbol = SymbolManager.GetSymbol(token, CurrentPass > 0);
                if (symbol == null)
                {
                    if (token.Line.Label != null && token.Line.Label.Name.Equals(token.Name, StringViewComparer))
                    {
                        throw new SymbolException(token, SymbolException.ExceptionReason.NotDefined);
                    }
                    PassNeeded = true;
                    return(0x100);
                }
                if (subscript >= 0)
                {
                    if (symbol.StorageType != StorageType.Vector)
                    {
                        throw new SyntaxException(token.Position, "Type mismatch.");
                    }
                    if ((symbol.IsNumeric && subscript >= symbol.NumericVector.Count) ||
                        (!symbol.IsNumeric && subscript >= symbol.StringVector.Count))
                    {
                        throw new SyntaxException(token.Position, "Index was out of range.");
                    }
                    if (symbol.IsNumeric)
                    {
                        return(symbol.NumericVector[subscript]);
                    }
                    token    = new Token(symbol.StringVector[subscript], TokenType.Operand);
                    isString = true;
                }
                else if (symbol.IsNumeric)
                {
                    if (symbol.DataType == DataType.Address && symbol.Bank != Output.CurrentBank)
                    {
                        return((int)symbol.NumericValue | (symbol.Bank * 0x10000));
                    }
                    return(symbol.NumericValue);
                }
                else
                {
                    token    = new Token(symbol.StringValue, TokenType.Operand);
                    isString = true;
                }
            }
            if (isString || token.IsQuote())
            {
                // is it a string literal?
                var literal = token.IsQuote() ? token.Name.TrimOnce(token.Name[0]).ToString() : token.Name.ToString();
                if (string.IsNullOrEmpty(literal))
                {
                    throw new SyntaxException(token.Position, "Cannot evaluate empty string.");
                }
                literal = Regex.Unescape(literal);
                if (!isString)
                {
                    var charsize = 1;
                    if (char.IsSurrogate(literal[0]))
                    {
                        charsize++;
                    }
                    if (literal.Length > charsize)
                    {
                        throw new SyntaxException(token.Position, "Invalid char literal.");
                    }
                }
                // get the integral equivalent from the code points in the string
                converted = Encoding.GetEncodedValue(literal);
            }
            else if (token.Name.Equals("*"))
            {    // get the program counter
                converted = Output.LogicalPC;
            }
            else if (token.Name[0].IsSpecialOperator())
            {    // get the special character value
                if (token.Name[0] == '+' && CurrentPass == 0)
                {
                    converted  = Output.LogicalPC;
                    PassNeeded = true;
                }
                else
                {
                    converted = SymbolManager.GetLineReference(token.Name, token);
                    if (double.IsNaN(converted))
                    {
                        var reason = token.Name[0] == '+' ? SymbolException.ExceptionReason.InvalidForwardReference :
                                     SymbolException.ExceptionReason.InvalidBackReference;
                        throw new SymbolException(token, reason);
                    }
                }
            }
            if (double.IsNaN(converted))
            {
                throw new ExpressionException(token.Position,
                                              $"\"{token.Name}\" is not a expression.");
            }
            return(converted);
        }