📄 expr.cxx
字号:
case T_Exclamation: result = CdlExprOp_LogicalNot; break; case T_Tilde: result = CdlExprOp_BitNot; break; case T_Questionmark: case T_Colon: result = CdlExprOp_Cond; break; // best guess case T_OpenBracket: case T_CloseBracket: case T_Invalid: default: result = CdlExprOp_Invalid; break; } } CYG_REPORT_RETVAL(result); return result;}// A utility routine to turn the current token back into a string// This is used for diagnostics.static std::stringtoken_to_string(){ CYG_REPORT_FUNCNAME("token_to_string"); std::string result = ""; switch(current_token) { case T_EOD: result = "<end of data>"; break; case T_Reference: result = "reference to " + current_reference; break; case T_String: result = "string \"" + current_string + "\""; break; case T_Integer: { std::string tmp; Cdl::integer_to_string(current_int, tmp, current_format); result = "integer constant " + tmp; break; } case T_Double: { std::string tmp; Cdl::double_to_string(current_double, tmp, current_format); result = "double constant " + tmp; break; } case T_Range: result = "range operator \"to\""; break; case T_OpenBracket: result = "open bracket ("; break; case T_CloseBracket: result = "close bracket )"; break; case T_Minus: result = "minus sign -"; break; case T_Plus: result = "plus sign +"; break; case T_Times: result = "multiply operator *"; break; case T_Divide: result = "divide operator /"; break; case T_Exclamation: result = "not operator !"; break; case T_Tilde: result = "bitwise not operator ~"; break; case T_Questionmark: result = "question mark ?"; break; case T_Remainder: result = "remainder operator %"; break; case T_LeftShift: result = "left shift operator <<"; break; case T_RightShift: result = "right shift operator >>"; break; case T_LessThan: result = "less-than operator <"; break; case T_LessEqual: result = "less-or-equal operator <="; break; case T_GreaterThan: result = "greater-than operator >"; break; case T_GreaterEqual: result = "greater-or-equal operator >="; break; case T_Equal: result = "equality operator =="; break; case T_NotEqual: result = "not-equal operator !="; break; case T_BitAnd: result = "bitwise and operator &"; break; case T_BitXor: result = "bitwise xor operator ^"; break; case T_BitOr: result = "bitwise or operator |"; break; case T_And: result = "and operator &&"; break; case T_Or: result = "or operator ||"; break; case T_Colon: result = "colon"; break; case T_Invalid: default: result = "<invalid token>"; break; } CYG_REPORT_RETURN(); return result;}//}}}//{{{ Literals // ----------------------------------------------------------------------------//{{{ process_string() // The start of a string has been detected. Work out the entire string,// allowing for backslash escapes.static voidprocess_string() throw(CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAME("process_string"); CYG_ASSERTC('"' == current_char); CYG_ASSERTC("" == current_string); std::string result = ""; // Move past the leading quote mark. next_char(); while ('"' != current_char) { if (EOF == current_char) { throw CdlParseException("Premature end of data in string constant.\n" + get_error_location()); } else if ('\\' == current_char) { // Allow \a, \b, \f, \n, \r, \t, \v, \ddd and \xhh. // Also copy with \newline space. // Any other character gets passed through unchanged. next_char(); switch(current_char) { case EOF: throw CdlParseException("Premature end of data after backslash in string constant.\n" + get_error_location()); case 'a': result += '\a'; break; case 'b': result += '\b'; break; case 'f': result += '\f'; break; case 'n': result += '\n'; break; case 'r': result += '\r'; break; case 't': result += '\t'; break; case 'v': result += '\v'; break; case 'x': { cdl_int tmp = 0; next_char(); if (!isxdigit(current_char)) { throw CdlParseException("Non-hexadecimal digit detected in string \\x escape sequence.\n" + get_error_location()); } // NOTE: there is no overflow detection here. do { tmp *= 16; if (('0' <= current_char) && (current_char <= '9')) { tmp += (current_char - '0'); } else if (('a' <= current_char) && (current_char <= 'f')) { tmp += 10 + (current_char - 'a'); } else if (('A' <= current_char) && (current_char <= 'F')) { tmp += 10 + (current_char - 'A'); } else { CYG_FAIL("C library error, isxdigit() succeeded on non-hexadecimal character"); } next_char(); } while(isxdigit(current_char)); backup_char(); result += (char) tmp; } case '\n': next_char(); while ((EOF != current_char) && isspace(current_char)) { next_char(); } // We have gone one too far, back up. backup_char(); result += " "; break; default: if (('0' <= current_char) && (current_char <= '7')) { // A sequence of octal digits. cdl_int tmp = 0; do { tmp = (8 * tmp) + (current_char - '0'); next_char(); } while (('0' <= current_char) && (current_char <= '7')); backup_char(); result += (char) tmp; } else { // For all other backslash sequences, just add the second character result += (char) current_char; } } } else { result += (char) current_char; } next_char(); } // The closing quote has been reached, move past it. next_char(); // And all done. current_token = T_String; current_string = result; CYG_REPORT_RETURN();}//}}}//{{{ process_number() // The start of a number has been detected. This number may be an// integer or a double. It is necessary to figure out where the number// ends and invoke the appropriate Cdl:: conversion utility.//// Care has to be taken with termination. Consider a token such as// 134_5. This is not a string because there are no quote marks, nor// is it a valid reference, and because it begins with a digit it// should be interpreted as a number. The 134 bit works fine, then// number processing stops leaving current_char as '_'. If we are// parsing a list expression then the following _5 will actually// be interpreted as a reference. To avoid this, here is a utility// which checks number completion and throws an exception if// necessary.static void check_number_termination() throw(CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAME("check_number_termination"); // End-of-data or any whitespace is ok. if ((EOF != current_char) && !isspace(current_char)) { // Any valid operator is ok as well, or brackets for that matter. if (('-' != current_char) && ('+' != current_char) && ('*' != current_char) && ('/' != current_char) && ('!' != current_char) && ('~' != current_char) && ('?' != current_char) && ('%' != current_char) && ('<' != current_char) && ('>' != current_char) && ('=' != current_char) && ('&' != current_char) && ('^' != current_char) && ('|' != current_char) && (':' != current_char) && ('(' != current_char) && (')' != current_char)) { std::string tmp; Cdl::integer_to_string(current_int, tmp); throw CdlParseException("Invalid character detected after number " + tmp + "\n" + get_error_location()); } } CYG_REPORT_RETURN();}static voidprocess_number() throw(CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAME("process_number"); std::string tmp = ""; bool is_float = false; // Detect the special cases of 0x and octal numbers. if ('0' == current_char) { next_char(); if (('x' == current_char) || ('X' == current_char)) { next_char(); if (!isxdigit(current_char)) { throw CdlParseException("Invalid hexadecimal number, expected at least one hexadecimal digit after 0x.\n" + get_error_location()); } current_int = 0; do { current_int *= 16; if (('0' <= current_char) && (current_char <= '9')) { current_int += (current_char - '0'); } else if (('a' <= current_char) && (current_char <= 'f')) { current_int += 10 + (current_char - 'a'); } else { current_int += 10 + (current_char - 'A'); } next_char(); } while(isxdigit(current_char)); current_token = T_Integer; current_format = CdlValueFormat_Hex; check_number_termination(); CYG_REPORT_RETURN(); return; } else if (('0' <= current_char) && (current_char <= '7')) { current_int = 0; do { current_int *= 8; current_int += (current_char - '0'); next_char(); } while (('0' <= current_char) && (current_char <= '7')); current_token = T_Integer; current_format = CdlValueFormat_Octal; check_number_termination(); CYG_REPORT_RETURN(); return; } else if (('8' == current_char) || ('9' == current_char)) { throw CdlParseException("08... and 09... are not valid octal numbers.\n" + get_error_location()); } else { // This could be plain 0, or 0.123 // Backup, and let the rest of the code take care of things backup_char(); } } do { tmp += (char) current_char; next_char(); } while(isdigit(current_char)); // If we have found a . then we have a floating point number with a fraction. if ('.' == current_char) { tmp += '.'; next_char(); if (!isdigit(current_char)) { throw CdlParseException("Invalid floating point constant, expected a digit for the fractional part.\n" + get_error_location()); } is_float = true; do { tmp += (char) current_char; next_char(); } while(isdigit(current_char)); } // If we have found e or E then we have a floating point number with an exponent if (('e' == current_char) || ('E' == current_char)) { tmp += 'E'; next_char(); if (('+' == current_char) || ('-' == current_char)) { tmp += current_char; next_char(); } if (!isdigit(current_char)) { throw CdlParseException("Invalid floating point constant, expected a digit for the exponent.\n" + get_error_location()); } is_float = true; do { tmp += (char) current_char; next_char(); } while(isdigit(current_char)); } if (is_float) { if (!Cdl::string_to_double(tmp, current_double)) { throw CdlParseException("Invalid floating point constant `" + tmp + "'.\n" + get_error_location()); } else { current_token = T_Double; } } else { if (!Cdl::string_to_integer(tmp, current_int)) { throw CdlParseException("Invalid integer constant `" + tmp + "'.\n" + get_error_location()); } else { current_token = T_Integer; } } check_number_termination(); CYG_REPORT_RETURN();}//}}}//{{{ process_reference() // The start of a reference has been detected.// A reference name must be a valid C preprocessor name, so the// only characters allowed are underscore, upper and lower case// characters, and digits. The first character cannot be a digit,// but that has been checked already.//// Some care has to be taken with locale's, the C library may decide// that a character is a letter even though the same character is not// valid as far as the preprocessor is concerned.static voidprocess_reference() throw(CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAME("process_reference"); do { current_reference += (char) current_char; next_char(); } while (('_' == current_char) || isdigit(current_char) || (('a' <= current_char) && (current_char <= 'z')) || (('A' <= current_char) && (current_char <= 'Z'))); current_token = T_Reference; CYG_REPORT_RETURN();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -