Пример #1
0
 void assembler_EvaluateExpressionValue(object sender, EvaluateValueEventArgs e)
 {
     if (e.Value.StartsWith("#"))
     {
         e.Result = 0x1234;
         e.Handled = true;
     }
 }
Пример #2
0
        /// <summary>
        /// Given an expression, it will parse it and return the result as a nullable ushort
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ExpressionResult ParseExpression(string value)
        {
            ExpressionResult expressionResult = new ExpressionResult();
            expressionResult.Successful = true;
            expressionResult.References = new List<string>();
            value = value.Trim();
            if (HandleExpression != null)
            {
                HandleExpressionEventArgs heea = new HandleExpressionEventArgs(value);
                HandleExpression(this, heea);
                value = heea.Expression;
            }
            if (value.SafeContains('('))
            {
                // Check for advanced expression handlers
                foreach (var item in ExpressionExtensions)
                {
                    if (value.StartsWith(item.Key.ToLower() + "("))
                    {
                        string expr = value.Substring(value.SafeIndexOf('(') + 1);
                        expr = expr.Remove(expr.Length - 1);
                        expressionResult.Value = item.Value(expr);
                        return expressionResult;
                    }
                }
                return EvaluateParenthesis(value);
            }
            if (value.StartsWith("~"))
            {
                expressionResult = ParseExpression(value.Substring(1));
                if (expressionResult.Successful)
                    expressionResult.Value = (ushort)~expressionResult.Value;
                return expressionResult;
            }
            if (!HasOperators(value))
            {
                // Parse value
                ushort result;
                EvaluateValueEventArgs args = new EvaluateValueEventArgs(value);
                if (EvaluateExpressionValue != null)
                {
                    EvaluateExpressionValue(this, args);
                }
                if (args.Handled)
                {
                    expressionResult.Value = args.Result;
                    return expressionResult;
                }
                else if (value.StartsWith("0d"))
                    value = value.Substring(2);
                if (value.StartsWith("'")) // Character
                {
                    if (value.Length < 3)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    value = value.Substring(1, value.Length - 2).Unescape();
                    if (value == null)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (value.Length != 1)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = (ushort)Encoding.ASCII.GetBytes(value)[0];
                    return expressionResult;
                }
                else if (value.StartsWith("{") && value.EndsWith("}")) // instruction literal
                {
                    string instruction = value.Substring(1, value.Length - 2);
                    Assembler subAssembler = new Assembler();
                    List<ListEntry> assembly = subAssembler.Assemble(instruction);
                    if (assembly.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (assembly[0].Output == null)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (assembly[0].Output.Length == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = assembly[0].Output[0];
                    return expressionResult;
                }
                else if (value.StartsWith("0x")) // Hex
                {
                    value = value.Substring(2);
                    if (!ushort.TryParse(value.Replace("_", ""), NumberStyles.HexNumber, null, out result))
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    else
                    {
                        expressionResult.Value = result;
                        return expressionResult;
                    }
                }
                else if (value.StartsWith("0b")) // Binary
                {
                    value = value.Substring(2);
                    ushort? binResult = ParseBinary(value.Replace("_", ""));
                    if (binResult == null)
                        expressionResult.Successful = false;
                    else
                        expressionResult.Value = binResult.Value;
                    return expressionResult;
                }
                else if (value.StartsWith("0o"))
                {
                    value = value.Substring(2);
                    try
                    {
                        expressionResult.Value = Convert.ToUInt16(value.Replace("_", ""), 8);
                        return expressionResult;
                    }
                    catch
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                }
                else if (ushort.TryParse(value.Replace("_", ""), out result)) // Decimal
                {
                    expressionResult.Value = result;
                    return expressionResult;
                }
                else if (value == "$")
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = currentAddress;
                    return expressionResult;
                }
                else if (value.StartsWith("$")) // Relative label
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    value = value.Substring(1);
                    int nextLabelIndex = -1;
                    // Find the next relative label after the current line
                    for (int i = 0; i < RelativeLabels.Count; i++)
                    {
                        if (RelativeLabels.ElementAt(i).Key > LineNumbers.Peek())
                        {
                            nextLabelIndex = i;
                            break;
                        }
                    }
                    if (nextLabelIndex == -1)
                        nextLabelIndex = RelativeLabels.Count - 1; // If no such label is found, use the last one
                    bool initialPlus = true;
                    // For each plus, increment that label index, and each minus decrements it
                    foreach (char c in value)
                    {
                        if (c == '+') // The intial plus symbol is ignored
                        {
                            if (initialPlus)
                                nextLabelIndex++;
                            initialPlus = false;
                        }
                        else if (c == '-')
                            nextLabelIndex--;
                    }
                    if (nextLabelIndex < 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (nextLabelIndex > RelativeLabels.Count - 1)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = RelativeLabels.ElementAt(nextLabelIndex).Value;
                    return expressionResult;
                }
                else if (value.ToLower() == "true")
                {
                    expressionResult.Value = 1;
                    return expressionResult;
                }
                else if (value.ToLower() == "false")
                {
                    expressionResult.Value = 0;
                    return expressionResult;
                }
                else // Defined value or error
                {
                    if (value.StartsWith("."))
                        value = PriorGlobalLabel + "_" + value.Substring(1);
                    if (Values.ContainsKey(value))
                        expressionResult.Value = Values[value];
                    else if (LabelValues.ContainsKey(value))
                    {
                        expressionResult.Relocate = true;
                        expressionResult.Value = LabelValues.GetValue(value);
                    }
                    else
                        expressionResult.Successful = false;
                    expressionResult.References.Add(value);
                    if (!ReferencedValues.Contains(value))
                        ReferencedValues.Add(value);
                    return expressionResult;
                }
            }

            // Parse expression
            string[] operands = GetOperands(value);
            if (operands == null)
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            if (string.IsNullOrEmpty(operands[0]) && operands[1] == "-")
            {
                expressionResult = ParseExpression(operands[2]);
                expressionResult.Value = (ushort)-expressionResult.Value;
                return expressionResult;
            }
            if (operands == null)
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            ExpressionResult left = ParseExpression(operands[0]);
            ExpressionResult right = ParseExpression(operands[2]);
            expressionResult.References.AddRange(left.References.Concat(right.References));
            if ((!left.Successful || !right.Successful) && operands[1] != "===" && operands[1] != "!==")
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            switch (operands[1])
            {
                case "*":
                    expressionResult.Value = (ushort)(left.Value * right.Value);
                    break;
                case "/":
                    expressionResult.Value =  (ushort)(left.Value / right.Value);
                    break;
                case "+":
                    expressionResult.Value =  (ushort)(left.Value + right.Value);
                    break;
                case "-":
                    expressionResult.Value =  (ushort)(left.Value - right.Value);
                    break;
                case "<<":
                    expressionResult.Value =  (ushort)(left.Value << right.Value);
                    break;
                case ">>":
                    expressionResult.Value =  (ushort)(left.Value >> right.Value);
                    break;
                case "|":
                    expressionResult.Value =  (ushort)(left.Value | right.Value);
                    break;
                case "^":
                    expressionResult.Value =  (ushort)(left.Value ^ right.Value);
                    break;
                case "&":
                    expressionResult.Value =  (ushort)(left.Value & right.Value);
                    break;
                case "%":
                    expressionResult.Value =  (ushort)(left.Value % right.Value);
                    break;
                case "==":
                    expressionResult.Value =  (ushort)(left.Value == right.Value ? 1 : 0);
                    break;
                case "!=":
                case "<>":
                    expressionResult.Value =  (ushort)(left.Value != right.Value ? 1 : 0);
                    break;
                case "<":
                    expressionResult.Value =  (ushort)(left.Value < right.Value ? 1 : 0);
                    break;
                case ">":
                    expressionResult.Value =  (ushort)(left.Value > right.Value ? 1 : 0);
                    break;
                case "<=":
                    expressionResult.Value =  (ushort)(left.Value <= right.Value ? 1 : 0);
                    break;
                case ">=":
                    expressionResult.Value =  (ushort)(left.Value >= right.Value ? 1 : 0);
                    break;
                case "===":
                    expressionResult.Value = (ushort)(operands[0].ToLower().Trim() == operands[2].ToLower().Trim() ? 1 : 0);
                    break;
                case "!==":
                    expressionResult.Value = (ushort)(operands[0].ToLower().Trim() != operands[2].ToLower().Trim() ? 1 : 0);
                    break;
                case "&&":
                    expressionResult.Value = (ushort)(left.Value > 0 && right.Value > 1 ? 1 : 0);
                    break;
                case "||":
                    expressionResult.Value = (ushort)(left.Value > 0 || right.Value > 1 ? 1 : 0);
                    break;
                case "^^":
                    expressionResult.Value = (ushort)(left.Value > 0 ^ right.Value > 1 ? 1 : 0); // between boolean operators, ^ is ^^ in C#
                    break;
                default:
                    expressionResult.Successful = false;
                    return expressionResult;
            }
            return expressionResult;
        }