private void ParseDirectives(List <ListEntry> output, string line, bool lineFromMacro) { string directive = line.Substring(1); string[] parameters = directive.Split(' '); if (directive.ToLower() == "endif" || directive.ToLower() == "end") { if (IfStack.Count == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro)); } else { IfStack.Pop(); output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } } else if (directive.ToLower().StartsWith("elseif") || directive.ToLower().StartsWith("elif")) { if (IfStack.Count == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro)); } else { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { var result = ParseExpression(line.Substring(line.IndexOf(' '))); if (result.Successful) { if (result.Value > 0) { IfStack.Push(!IfStack.Pop()); } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } } } else if (directive.ToLower() == "else") { if (IfStack.Count == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); IfStack.Push(!IfStack.Pop()); } } else if (IfStack.Peek()) { if (directive.ToLower() == "region" || directive.ToLower() == "endregion") { } // Allowed but ignored else if (directive.ToLower() == "nolist") { noList = true; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); } else if (directive.ToLower() == "list") { noList = false; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); } else if ((directive.ToLower().StartsWith("dat ") || directive.ToLower().StartsWith("dw "))) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(','); List <ushort> binOutput = new List <ushort>(); Dictionary <ushort, string> postponedExpressions = new Dictionary <ushort, string>(); foreach (string data in dataStrings) { if (data.Trim().StartsWith("\"")) { if (!data.Trim().EndsWith("\"")) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape(); foreach (byte b in Encoding.ASCII.GetBytes(str)) { binOutput.Add(b); } } } else { postponedExpressions.Add((ushort)binOutput.Count, data.Trim()); binOutput.Add(0); } } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList)); output[output.Count - 1].PostponedExpressions = postponedExpressions; if (!noList) { currentAddress += (ushort)binOutput.Count; } } } else if (directive.ToLower().StartsWith("scope")) { if (parameters.Length < 2) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else if (parameters.Length > 2) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } else { PriorGlobalLabel = parameters[1]; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); } } else if (directive.ToLower() == "uniquescope") { PriorGlobalLabel = "_unique" + UniqueScopeNumber++; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); } else if (directive.ToLower().StartsWith("echo")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(','); string consoleOutput = ""; foreach (string data in dataStrings) { if (data.Trim().StartsWith("\"")) { if (!data.Trim().EndsWith("\"")) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape(); consoleOutput += str; } } else { ExpressionResult value = ParseExpression(data.Trim()); if (!value.Successful) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { consoleOutput += value.Value; } } } Console.Write(consoleOutput + "\n"); output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); output.Add(new ListEntry(consoleOutput, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); } } else if (directive.ToLower().StartsWith("ref")) { ReferencedValues.Add(directive.Substring(directive.IndexOf(" ") + 1)); } else if (directive.ToLower().StartsWith("asciip")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(','); List <ushort> binOutput = new List <ushort>(); foreach (string data in dataStrings) { if (data.Trim().StartsWith("\"")) { if (!data.Trim().EndsWith("\"")) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape(); binOutput.Add((ushort)str.Length); foreach (byte b in Encoding.ASCII.GetBytes(str)) { binOutput.Add(b); } } } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList)); if (!noList) { currentAddress += (ushort)binOutput.Count; } } } else if (directive.ToLower().StartsWith("asciic") || directive.ToLower().StartsWith("asciiz")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(','); List <ushort> binOutput = new List <ushort>(); foreach (string data in dataStrings) { if (data.Trim().StartsWith("\"")) { if (!data.Trim().EndsWith("\"")) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape(); foreach (byte b in Encoding.ASCII.GetBytes(str)) { binOutput.Add(b); } binOutput.Add(0); } } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList)); if (!noList) { currentAddress += (ushort)binOutput.Count; } } } else if (directive.ToLower().StartsWith("ascii")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(','); List <ushort> binOutput = new List <ushort>(); foreach (string data in dataStrings) { if (data.Trim().StartsWith("\"")) { if (!data.Trim().EndsWith("\"")) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape(); foreach (byte b in Encoding.ASCII.GetBytes(str)) { binOutput.Add(b); } } } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList)); if (!noList) { currentAddress += (ushort)binOutput.Count; } } } else if (directive.ToLower() == "longform") // Handled properly in the second pass { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else if (directive.ToLower() == "shortform") { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else if (directive.ToLower().StartsWith("org")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else if (parameters.Length > 2) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } else { ExpressionResult value = ParseExpression(parameters[1]); if (value == null) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { currentAddress = value.Value; var entry = new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList); entry.RootLineNumber = RootLineNumber; output.Add(entry); } } } else if (directive.ToLower().StartsWith("ifdef")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else if (parameters.Length > 2) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } else { if (Values.ContainsKey(parameters[1].ToLower())) { IfStack.Push(true); } else { IfStack.Push(false); } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } } else if (directive.ToLower().StartsWith("ifndef")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else if (parameters.Length > 2) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } else { if (Values.ContainsKey(parameters[1].ToLower())) { IfStack.Push(false); } else { IfStack.Push(true); } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } } else if (directive.ToLower().StartsWith("if")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { var result = ParseExpression(line.Substring(3)); if (result.Successful) { if (result.Value > 0) { IfStack.Push(true); } else { IfStack.Push(false); } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } } else if (directive.ToLower().StartsWith("equ") || directive.ToLower().StartsWith("define") || directive.ToLower().StartsWith("equate")) { if (parameters.Length > 1) { if (Values.ContainsKey(parameters[1])) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.DuplicateName, lineFromMacro)); } else { if (parameters.Length == 2) { Values.Add(parameters[1], 1); output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else if (parameters.Length > 2) { string expression = directive.TrimExcessWhitespace(); expression = expression.Substring(expression.IndexOf(' ') + 1); expression = expression.Substring(expression.IndexOf(' ') + 1); ExpressionResult value = ParseExpression(expression); // TODO: find a way to forward reference if (value != null) { Values.Add(parameters[1], value.Value); output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } } } } else if (directive.ToLower().StartsWith("pad") || directive.ToLower().StartsWith("fill")) // .pad length, value { parameters = line.SafeSplit(',', ' '); string[] fixedParams = new string[0]; foreach (string parameter in parameters) { if (!string.IsNullOrEmpty(parameter)) { fixedParams = fixedParams.Concat(new string[] { parameter }).ToArray(); } } parameters = fixedParams; if (parameters.Length == 3) { var length = ParseExpression(parameters[1]); var value = ParseExpression(parameters[2]); if (!length.Successful) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { ushort[] padding = new ushort[length.Value]; Dictionary <ushort, string> postponed = new Dictionary <ushort, string>(); for (int i = 0; i < padding.Length; i++) { padding[i] = value.Value; if (!value.Successful) { postponed.Add((ushort)i, parameters[2]); } } output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList)); output[output.Count - 1].PostponedExpressions = postponed; if (!noList) { currentAddress += (ushort)padding.Length; } } } else if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } } else if (directive.ToLower().StartsWith("reserve")) { if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { var expression = directive.Substring(7).Trim(); var result = ParseExpression(expression); if (result.Successful) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), new ushort[result.Value], currentAddress, !noList)); currentAddress += result.Value; } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } } } else if (directive.ToLower().StartsWith("align")) // .align addr { if (parameters.Length == 2) { var addr = ParseExpression(parameters[1]); if (!addr.Successful) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro)); } else { if (currentAddress > addr.Value) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.AlignToPast, lineFromMacro)); } else { var amount = (ushort)(addr.Value - currentAddress); ushort[] padding = new ushort[amount]; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList)); if (!noList) { currentAddress = addr.Value; } } } } else if (parameters.Length == 1) { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro)); } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro)); } } else if (directive == "relocate") { OldAddress = currentAddress; currentAddress = 0; output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); output[output.Count - 1].CodeType = CodeType.RelocationTable; RelocationGroup++; IsRelocating = true; } else if (directive == "endrelocate") { // TODO: Errors output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro)); currentAddress = OldAddress; IsRelocating = false; } else { output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InvalidDirective, lineFromMacro)); } } output[output.Count - 1].CodeType = CodeType.Directive; }
/// <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); }