diff options
Diffstat (limited to 'archive/1.vm/015literal_noninteger.cc')
-rw-r--r-- | archive/1.vm/015literal_noninteger.cc | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/archive/1.vm/015literal_noninteger.cc b/archive/1.vm/015literal_noninteger.cc new file mode 100644 index 00000000..12f24586 --- /dev/null +++ b/archive/1.vm/015literal_noninteger.cc @@ -0,0 +1,51 @@ +//: Support literal non-integers. + +void test_noninteger_literal() { + load( + "def main [\n" + " 1:number <- copy 3.14159\n" + "]\n" + ); + CHECK_TRACE_CONTENTS( + "parse: ingredient: {3.14159: \"literal-fractional-number\"}\n" + ); +} + +:(after "Parsing reagent(string s)") +if (is_noninteger(s)) { + name = s; + type = new type_tree("literal-fractional-number", 0); + set_value(to_double(s)); + return; +} + +:(code) +bool is_noninteger(const string& s) { + return s.find_first_not_of("0123456789-.") == string::npos // no other characters + && s.find_first_of("0123456789") != string::npos // at least one digit + && s.find('-', 1) == string::npos // '-' only at first position + && std::count(s.begin(), s.end(), '.') == 1; // exactly one decimal point +} + +double to_double(string n) { + char* end = NULL; + // safe because string.c_str() is guaranteed to be null-terminated + double result = strtod(n.c_str(), &end); + assert(*end == '\0'); + return result; +} + +void test_is_noninteger() { + CHECK(!is_noninteger("1234")); + CHECK(!is_noninteger("1a2")); + CHECK(is_noninteger("234.0")); + CHECK(!is_noninteger("...")); + CHECK(!is_noninteger(".")); + CHECK(is_noninteger("2.")); + CHECK(is_noninteger(".2")); + CHECK(is_noninteger("-.2")); + CHECK(is_noninteger("-2.")); + CHECK(!is_noninteger("--.2")); + CHECK(!is_noninteger(".-2")); + CHECK(!is_noninteger("..2")); +} |