Skip to content

Commit 349dcd6

Browse files
Support string starts with number
1 parent 4cf4c8b commit 349dcd6

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

src/tokenizer.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,35 @@ Tokenizer::Token Tokenizer::GetToken() {
2929
if (c == '/') {
3030
_lasttok.reset(new Tokenizer::Token{Slash{}});
3131
// NB: Move cursor to the next symbol
32-
_in->get();
32+
(void)_in->get();
3333
} else if (std::isdigit(c) || c == '-') {
34-
_lasttok.reset(new Tokenizer::Token{Double{ParseDouble()}});
34+
// NB: Move cursor to the next symbol
35+
(void)_in->get();
36+
37+
std::string accum;
38+
accum += c;
39+
bool met_dot = false;
40+
bool not_number = false;
41+
while (true) {
42+
auto ch = _in->peek();
43+
if (ch == '/' || ch == '#' || std::isspace(ch) || ch == EOF) {
44+
break;
45+
}
46+
if (!std::isdigit(ch)) {
47+
if (ch == '.' && !met_dot) {
48+
met_dot = true;
49+
} else {
50+
not_number = true;
51+
}
52+
}
53+
accum += ch;
54+
_in->get();
55+
}
56+
if (not_number) {
57+
_lasttok.reset(new Tokenizer::Token{String{accum}});
58+
} else {
59+
_lasttok.reset(new Tokenizer::Token{Double{std::stod(accum)}});
60+
}
3561
} else if (std::isalpha(c)) {
3662
auto word = ParseString();
3763
_lasttok.reset(new Tokenizer::Token{String{word}});

tests/test_tokenizer.cpp

+53-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ TEST(TokenizerTests, EmptyStream) {
1212
}
1313

1414
TEST(TokenizerTests, Double) {
15+
std::stringstream ss{"42.0"};
16+
Tokenizer t(&ss);
17+
18+
auto tok = t.GetToken();
19+
20+
EXPECT_TRUE(std::holds_alternative<Tokenizer::Double>(tok));
21+
EXPECT_EQ(42, std::get<Tokenizer::Double>(tok).val);
22+
}
23+
24+
TEST(TokenizerTests, Int) {
1525
std::stringstream ss{"42"};
1626
Tokenizer t(&ss);
1727

@@ -21,6 +31,49 @@ TEST(TokenizerTests, Double) {
2131
EXPECT_EQ(42, std::get<Tokenizer::Double>(tok).val);
2232
}
2333

34+
TEST(TokenizerTests, Negative) {
35+
std::stringstream ss{"-42.5"};
36+
Tokenizer t(&ss);
37+
38+
auto tok = t.GetToken();
39+
40+
EXPECT_TRUE(std::holds_alternative<Tokenizer::Double>(tok));
41+
EXPECT_EQ(-42.5, std::get<Tokenizer::Double>(tok).val);
42+
}
43+
44+
TEST(TokenizerTests, StringWithDot) {
45+
std::stringstream ss{"42.0.0"};
46+
Tokenizer t(&ss);
47+
48+
auto tok = t.GetToken();
49+
50+
EXPECT_TRUE(std::holds_alternative<Tokenizer::String>(tok));
51+
EXPECT_EQ("42.0.0", std::get<Tokenizer::String>(tok).str);
52+
}
53+
54+
TEST(TokenizerTests, StringStartsWithNumber) {
55+
std::stringstream ss{"1212_foo"};
56+
Tokenizer t(&ss);
57+
58+
EXPECT_EQ("1212_foo", std::get<Tokenizer::String>(t.GetToken()).str);
59+
}
60+
61+
TEST(TokenizerTests, NumbersWithSlashes) {
62+
std::stringstream ss{"0/1/2/"};
63+
Tokenizer t(&ss);
64+
65+
for (int i = 0; i < 3; ++i) {
66+
auto tok = t.GetToken();
67+
ASSERT_EQ(i, std::get<Tokenizer::Double>(tok).val);
68+
t.Next();
69+
tok = t.GetToken();
70+
ASSERT_TRUE(std::holds_alternative<Tokenizer::Slash>(tok));
71+
t.Next();
72+
}
73+
74+
EXPECT_TRUE(t.IsEnd());
75+
}
76+
2477
TEST(TokenizerTests, String) {
2578
std::stringstream ss{"foo"};
2679
Tokenizer t(&ss);
@@ -121,10 +174,3 @@ TEST(TokenizerTests, NextLineBeforeEnd) {
121174

122175
EXPECT_TRUE(t.IsEnd());
123176
}
124-
125-
TEST(TokenizerTests, ParseStringStartsWithNumber) {
126-
std::stringstream ss{"1212_foo"};
127-
Tokenizer t(&ss);
128-
129-
EXPECT_EQ("1212_foo", std::get<Tokenizer::String>(t.GetToken()).str);
130-
}

0 commit comments

Comments
 (0)