public static (bool Valid, ulong Value, int NBits) Evaluate_Constant(string str, bool isCapitals = false) { // 1] test whether str has digits, if it has none it is not a constant if (!str.Any(char.IsDigit)) { return(false, 0, -1); } // 2] test whether str is a constant var v = Parse_Constant(str, isCapitals); if (v.Valid) { return(v); } // 3] check if str contains operators if (str.Contains('+') || str.Contains('-') || str.Contains('*') || str.Contains('/') || str.Contains("<<") || str.Contains(">>")) { // second: if str is not a constant, test whether evaluating it yields a ulong try { var t = CSharpScript.EvaluateAsync <ulong>(str); ulong value = t.Result; bool isNegative = false; return(true, value, AsmSourceTools.NBitsStorageNeeded(value, isNegative)); } catch (Exception) {} } // 4] don't know what it is but it is not likely to be an constant. return(false, 0, -1); }
public static (bool valid, ulong value, int nBits) Evaluate_Constant(string str, bool isCapitals = false) { Contract.Requires(str != null); // 1] test whether str has digits, if it has none it is not a constant if (!str.Any(char.IsDigit)) { return(valid : false, value : 0, nBits : -1); } // 2] test whether str is a constant (bool valid, ulong value, int nBits)v = Parse_Constant(str, isCapitals); if (v.valid) { return(v); } // 3] check if str contains operators if (str.Contains('+') || str.Contains('-') || str.Contains('*') || str.Contains('/') || str.Contains("<<") || str.Contains(">>")) { // second: if str is not a constant, test whether evaluating it yields a ulong try { System.Threading.Tasks.Task <ulong> t = CSharpScript.EvaluateAsync <ulong>(str); ulong value = t.Result; bool isNegative = false; return(valid : true, value : value, nBits : AsmSourceTools.NBitsStorageNeeded(value, isNegative)); } catch (Exception) { // Do nothing } } // 4] don't know what it is but it is not likely to be a constant. return(valid : false, value : 0, nBits : -1); }
/// <summary> Check if the provided string is a constant. Does not evaluate arithmetic in the string </summary> public static (bool Valid, ulong Value, int NBits) Parse_Constant(string str, bool isCapitals = false) { string token2; bool isHex = false; bool isBinary = false; bool isDecimal = false; bool isOctal = false; bool isNegative = false; //Console.WriteLine("AsmSourceTools:ToConstant token=" + token); if (!isCapitals) { str = str.ToUpper(); } str = str.Trim(); if (str.StartsWith("-")) { token2 = str; isDecimal = true; isNegative = true; } // note the special case of token 0h (zero hex) should not be confused with the prefix 0h; else if (str.EndsWith("H", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isHex = true; } else if (str.StartsWith("0H", StringComparison.Ordinal) || str.StartsWith("0X", StringComparison.Ordinal) || str.StartsWith("$0", StringComparison.Ordinal)) { token2 = str.Substring(2); isHex = true; } else if (str.StartsWith("0O", StringComparison.Ordinal) || str.StartsWith("0Q", StringComparison.Ordinal)) { token2 = str.Substring(2); isOctal = true; } else if (str.EndsWith("Q", StringComparison.Ordinal) || str.EndsWith("O", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isOctal = true; } else if (str.StartsWith("0D", StringComparison.Ordinal)) { token2 = str.Substring(2); isDecimal = true; } else if (str.EndsWith("D", StringComparison.Ordinal)) { token2 = str; isDecimal = true; } else if (str.StartsWith("0B", StringComparison.Ordinal) || str.StartsWith("0Y", StringComparison.Ordinal)) { token2 = str.Substring(2); isBinary = true; } else if (str.EndsWith("Y", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isBinary = true; } else { // special case with trailing B: either this B is from a hex number of the Binary if (str.EndsWith("B", StringComparison.Ordinal)) { bool parsedSuccessfully_tmp = ulong.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var dummy); if (parsedSuccessfully_tmp) { isHex = true; token2 = str; } else { token2 = str.Substring(0, str.Length - 1); isBinary = true; } } else { // assume decimal token2 = str; isDecimal = true; } } ulong value = 0; bool parsedSuccessfully; if (isHex) { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value); } else if (isOctal) { try { value = Convert.ToUInt64(token2, 8); parsedSuccessfully = true; } catch { parsedSuccessfully = false; } } else if (isBinary) { try { value = Convert.ToUInt64(token2, 2); parsedSuccessfully = true; } catch { parsedSuccessfully = false; } } else if (isDecimal) { if (isNegative) { parsedSuccessfully = long.TryParse(token2, NumberStyles.Integer, CultureInfo.CurrentCulture, out long signedValue); value = (ulong)signedValue; //Console.WriteLine("AsmSourceTools:ToConstant token2=" + token2 + "; signed value = " + Convert.ToString(signedValue, 16) + "; unsigned value = " + string.Format("{0:X}", value)); } else { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.Integer, CultureInfo.CurrentCulture, out value); if (!parsedSuccessfully) { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value); } } } else { // unreachable parsedSuccessfully = false; } int nBits = (parsedSuccessfully) ? AsmSourceTools.NBitsStorageNeeded(value, isNegative) : -1; return(Valid : parsedSuccessfully, Value : value, NBits : nBits); }
public static (bool Valid, ulong Value, int NBits) Evaluate_Constant_OLD(string str, bool IsCapitals = false) { //Console.WriteLine("INFO: Evaluate_Constant: str=" + str + ": length=" + str.Length); if (!IsCapitals) { str = str.ToUpper(); } Stack <ulong> vStack = new Stack <ulong>(); Stack <Op> opStack = new Stack <Op>(); opStack.Push(Op.OPENING); // Implicit opening parenthesis int pos = 0; int exprLength = str.Length; while (pos <= exprLength) { if (pos == exprLength) { Process_Closing_Parenthesis(vStack, opStack); pos++; } else { char c = str[pos]; if (Char.IsWhiteSpace(c)) { pos++; } else { switch (c) { case ')': Process_Closing_Parenthesis(vStack, opStack); pos++; break; case '(': Process_Opening_Parenthesis(vStack, opStack); pos++; break; case '+': if (!Process_Input_Operator(Op.PLUS, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '-': if (!Process_Input_Operator(Op.MINUS, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '*': if (!Process_Input_Operator(Op.TIMES, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '/': if (!Process_Input_Operator(Op.DIV, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '|': if (!Process_Input_Operator(Op.OR, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '&': if (!Process_Input_Operator(Op.AND, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '<': if ((pos + 1 < exprLength) && (str[pos + 1] == '<')) { pos++; if (!Process_Input_Operator(Op.SHL, vStack, opStack)) { return(false, 0, -1); } pos++; } break; case '>': if ((pos + 1 < exprLength) && (str[pos + 1] == '>')) { pos++; if (!Process_Input_Operator(Op.SHR, vStack, opStack)) { return(false, 0, -1); } pos++; } break; default: var v = Process_Input_Number(str, pos, vStack); if (!v.Valid) { return(false, 0, -1); } pos = v.Pos; break; } } } } if (vStack.Count == 1) // Result remains on values stacks { ulong v = vStack.Pop(); return(true, v, AsmSourceTools.NBitsStorageNeeded(v, false)); } else { return(false, 0, -1); } }