Skip to content

Commit

Permalink
Show last variable (with proper indices, if any) in EOL/EOF failure m…
Browse files Browse the repository at this point in the history
…essage (#97)

Fixed #15
  • Loading branch information
jonathanirvings authored and fushar committed Nov 30, 2016
1 parent bf52e60 commit 189b173
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 34 deletions.
6 changes: 5 additions & 1 deletion include/tcframe/io_manipulator/GridIOSegmentManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ namespace tcframe {

class GridIOSegmentManipulator {
public:
static void parse(GridIOSegment* segment, istream* in) {
static string parse(GridIOSegment* segment, istream* in) {
Matrix* variable = segment->variable();
variable->clear();
variable->parseFrom(in, *segment->rows(), *segment->columns());

return TokenFormatter::formatMatrixElement(variable->name(),
variable->rows() - 1,
variable->columns(variable->rows() - 1) - 1);
}

static void print(GridIOSegment* segment, ostream* out) {
Expand Down
13 changes: 9 additions & 4 deletions include/tcframe/io_manipulator/IOManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,21 @@ class IOManipulator {
}

void parse(const vector<IOSegment*>& segments, istream* in) {
string lastVariableName;
for (IOSegment* segment : segments) {
if (segment->type() == IOSegmentType::GRID) {
GridIOSegmentManipulator::parse((GridIOSegment*) segment, in);
lastVariableName = GridIOSegmentManipulator::parse((GridIOSegment*) segment, in);
} else if (segment->type() == IOSegmentType::LINE) {
LineIOSegmentManipulator::parse((LineIOSegment*) segment, in);
lastVariableName = LineIOSegmentManipulator::parse((LineIOSegment*) segment, in);
} else if (segment->type() == IOSegmentType::LINES) {
LinesIOSegmentManipulator::parse((LinesIOSegment*) segment, in);
lastVariableName = LinesIOSegmentManipulator::parse((LinesIOSegment*) segment, in);
}
}
WhitespaceManipulator::ensureEof(in);
if (!lastVariableName.empty()) {
WhitespaceManipulator::ensureEof(in, lastVariableName);
} else {
WhitespaceManipulator::ensureEof(in);
}
}
};

Expand Down
11 changes: 7 additions & 4 deletions include/tcframe/io_manipulator/LineIOSegmentManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace tcframe {

class LineIOSegmentManipulator {
public:
static void parse(LineIOSegment* segment, istream* in) {
static string parse(LineIOSegment* segment, istream* in) {
string lastVariableName;
for (const LineIOSegmentVariable& segmentVariable : segment->variables()) {
if (!lastVariableName.empty()) {
Expand All @@ -29,13 +29,16 @@ class LineIOSegmentManipulator {

if (variable->type() == VariableType::SCALAR) {
parseScalar((Scalar*) variable, in);
lastVariableName = TokenFormatter::formatVariable(variable->name());
} else {
parseVector((Vector*) variable, size, in);
Vector* vectorVariable = (Vector*) variable;
parseVector(vectorVariable, size, in);
lastVariableName = TokenFormatter::formatVectorElement(variable->name(), vectorVariable->size() - 1);
}

lastVariableName = TokenFormatter::formatVariable(variable->name());
}
WhitespaceManipulator::parseNewline(in, lastVariableName);

return lastVariableName;
}

static void print(LineIOSegment* segment, ostream* out) {
Expand Down
21 changes: 15 additions & 6 deletions include/tcframe/io_manipulator/LinesIOSegmentManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace tcframe {

class LinesIOSegmentManipulator {
public:
static void parse(LinesIOSegment* segment, istream* in) {
static string parse(LinesIOSegment* segment, istream* in) {
for (Variable* variable : segment->variables()) {
if (variable->type() == VariableType::VECTOR) {
((Vector*) variable)->clear();
Expand All @@ -26,24 +26,33 @@ class LinesIOSegmentManipulator {
}
}

string lastVariableName;

for (int j = 0; j < *segment->size(); j++) {
string lastVariableName;
bool isFirstColumn = true;
for (Variable* variable : segment->variables()) {
if (variable->type() == VariableType::VECTOR) {
if (!lastVariableName.empty()) {
if (!isFirstColumn) {
WhitespaceManipulator::parseSpace(in, lastVariableName);
}
((Vector*) variable)->parseAndAddElementFrom(in);
lastVariableName = TokenFormatter::formatVectorElement(variable->name(), j);
} else {
if (!lastVariableName.empty() && !WhitespaceManipulator::canParseNewline(in)) {
if (!isFirstColumn && !WhitespaceManipulator::canParseNewline(in)) {
WhitespaceManipulator::parseSpace(in, lastVariableName);
}
((Matrix*) variable)->parseAndAddRowFrom(in, j);
Matrix* matrixVariable = (Matrix*) variable;
matrixVariable->parseAndAddRowFrom(in, j);
lastVariableName = TokenFormatter::formatMatrixElement(variable->name(),
j,
matrixVariable->columns(j) - 1);
}
lastVariableName = TokenFormatter::formatVectorElement(variable->name(), j);
isFirstColumn = false;
}
WhitespaceManipulator::parseNewline(in, lastVariableName);
}

return lastVariableName;
}

static void print(LinesIOSegment* segment, ostream* out) {
Expand Down
6 changes: 6 additions & 0 deletions include/tcframe/spec/variable/WhitespaceManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ class WhitespaceManipulator {
}
}

static void ensureEof(istream* in, const string& context) {
if (in->peek() != char_traits<char>::eof()) {
throw runtime_error("Expected: <EOF> after " + context);
}
}

static void ensureNoEof(istream* in, const string& context) {
if (in->peek() == char_traits<char>::eof()) {
throw runtime_error("Cannot parse for " + context + ". Found: <EOF>");
Expand Down
6 changes: 6 additions & 0 deletions test/tcframe/io_manipulator/GridIOSegmentManipulatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ TEST_F(GridIOSegmentManipulatorTests, Parsing_Successful) {
EXPECT_THAT(M, Eq(vector<vector<int>>{{1, 2, 3}, {4, 5, 6}}));
}

TEST_F(GridIOSegmentManipulatorTests, Parsing_Successful_CheckLastVariable) {
istringstream in("1 2 3\n4 5 6\n");

EXPECT_THAT(GridIOSegmentManipulator::parse(segment, &in), Eq("'M[1][2]'"));
}

TEST_F(GridIOSegmentManipulatorTests, Printing_Successful) {
ostringstream out;

Expand Down
99 changes: 81 additions & 18 deletions test/tcframe/io_manipulator/IOManipulatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,112 @@ class IOManipulatorTests : public Test {
vector<int> V;
vector<vector<int>> M;

IOManipulator* manipulator;
IOManipulator* manipulatorWithScalarLast;
IOManipulator* manipulatorWithVectorLast;
IOManipulator* manipulatorWithMatrixLast;
IOManipulator* manipulatorEmpty;

void SetUp() {
IOFormatBuilder ioFormatBuilder;
ioFormatBuilder.prepareForInputFormat();
ioFormatBuilder.newLineIOSegment()
.addScalarVariable(Scalar::create(A, "A"));
ioFormatBuilder.newLinesIOSegment()
.addVectorVariable(Vector::create(V, "V"))
.setSize(new int(2));
ioFormatBuilder.newGridIOSegment()
.addMatrixVariable(Matrix::create(M, "M"))
.setSize(new int(2), new int(2));
IOFormat ioFormat = ioFormatBuilder.build();

manipulator = new IOManipulator(ioFormat);
{
IOFormatBuilder ioFormatBuilder;
ioFormatBuilder.prepareForInputFormat();
IOFormat ioFormat = ioFormatBuilder.build();

manipulatorEmpty = new IOManipulator(ioFormat);
}
{
IOFormatBuilder ioFormatBuilder;
ioFormatBuilder.prepareForInputFormat();
ioFormatBuilder.newLineIOSegment()
.addScalarVariable(Scalar::create(A, "A"));
IOFormat ioFormat = ioFormatBuilder.build();

manipulatorWithScalarLast = new IOManipulator(ioFormat);
}
{
IOFormatBuilder ioFormatBuilder;
ioFormatBuilder.prepareForInputFormat();
ioFormatBuilder.newLineIOSegment()
.addScalarVariable(Scalar::create(A, "A"));
ioFormatBuilder.newLinesIOSegment()
.addVectorVariable(Vector::create(V, "V"))
.setSize(new int(2));
IOFormat ioFormat = ioFormatBuilder.build();

manipulatorWithVectorLast = new IOManipulator(ioFormat);
}
{
IOFormatBuilder ioFormatBuilder;
ioFormatBuilder.prepareForInputFormat();
ioFormatBuilder.newLineIOSegment()
.addScalarVariable(Scalar::create(A, "A"));
ioFormatBuilder.newLinesIOSegment()
.addVectorVariable(Vector::create(V, "V"))
.setSize(new int(2));
ioFormatBuilder.newGridIOSegment()
.addMatrixVariable(Matrix::create(M, "M"))
.setSize(new int(2), new int(2));
IOFormat ioFormat = ioFormatBuilder.build();

manipulatorWithMatrixLast = new IOManipulator(ioFormat);
}
}
};

TEST_F(IOManipulatorTests, Parsing_Successful) {
istringstream in("123\n42\n7\n5 6\n7 8\n");
manipulator->parseInput(&in);
manipulatorWithMatrixLast->parseInput(&in);
EXPECT_THAT(A, Eq(123));
EXPECT_THAT(V, Eq((vector<int>{42, 7})));
EXPECT_THAT(M, Eq((vector<vector<int>>{{5, 6}, {7, 8}})));
}

TEST_F(IOManipulatorTests, Parsing_Failed_MissingEof) {
TEST_F(IOManipulatorTests, Parsing_Failed_MissingEof_Empty) {
istringstream in("123\n42\n7\n5 6\n7 8\nbogus");
try {
manipulator->parseInput(&in);
manipulatorEmpty->parseInput(&in);
FAIL();
} catch(runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <EOF>"));
}
}

TEST_F(IOManipulatorTests, Parsing_Failed_MissingEof_WithScalarLast) {
istringstream in("123\n42\n7\n5 6\n7 8\nbogus");
try {
manipulatorWithScalarLast->parseInput(&in);
FAIL();
} catch(runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <EOF> after 'A'"));
}
}

TEST_F(IOManipulatorTests, Parsing_Failed_MissingEof_WithVectorLast) {
istringstream in("123\n42\n7\n5 6\n7 8\nbogus");
try {
manipulatorWithVectorLast->parseInput(&in);
FAIL();
} catch(runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <EOF> after 'V[1]'"));
}
}

TEST_F(IOManipulatorTests, Parsing_Failed_MissingEof_WithMatrixLast) {
istringstream in("123\n42\n7\n5 6\n7 8\nbogus");
try {
manipulatorWithMatrixLast->parseInput(&in);
FAIL();
} catch(runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <EOF> after 'M[1][1]'"));
}
}

TEST_F(IOManipulatorTests, Printing_Successful) {
A = 123;
V = {42, 7};
M = {{5, 6}, {7, 8}};
ostringstream out;
manipulator->printInput(&out);
manipulatorWithMatrixLast->printInput(&out);
EXPECT_THAT(out.str(), Eq("123\n42\n7\n5 6\n7 8\n"));
}

Expand Down
43 changes: 42 additions & 1 deletion test/tcframe/io_manipulator/LineIOSegmentManipulatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class LineIOSegmentManipulatorTests : public Test {

int* size = new int(2);

LineIOSegment* segmentWithScalarsOnly = LineIOSegmentBuilder()
.addScalarVariable(Scalar::create(A, "A"))
.addScalarVariable(Scalar::create(B, "B"))
.build();
LineIOSegment* segment = LineIOSegmentBuilder()
.addScalarVariable(Scalar::create(A, "A"))
.addScalarVariable(Scalar::create(B, "B"))
Expand All @@ -39,6 +43,20 @@ TEST_F(LineIOSegmentManipulatorTests, Parsing_EmptyLine) {
LineIOSegmentManipulator::parse(LineIOSegmentBuilder().build(), &in);
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_WithScalarsOnly_Successful) {
istringstream in("42 123\n");

LineIOSegmentManipulator::parse(segmentWithScalarsOnly, &in);
EXPECT_THAT(A, Eq(42));
EXPECT_THAT(B, Eq(123));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_WithScalarsOnly_Successful_CheckLastVariable) {
istringstream in("42 123\n");

EXPECT_THAT(LineIOSegmentManipulator::parse(segmentWithScalarsOnly, &in), Eq("'B'"));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_Successful) {
istringstream in("42 123 1 2\n");

Expand All @@ -48,6 +66,12 @@ TEST_F(LineIOSegmentManipulatorTests, Parsing_Successful) {
EXPECT_THAT(C, Eq(vector<int>{1, 2}));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_Successful_CheckLastVariable) {
istringstream in("42 123 1 2\n");

EXPECT_THAT(LineIOSegmentManipulator::parse(segment, &in), Eq("'C[1]'"));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_Failed_MissingVariable) {
istringstream in("42 ");

Expand Down Expand Up @@ -77,7 +101,18 @@ TEST_F(LineIOSegmentManipulatorTests, Parsing_Failed_MissingNewline) {
LineIOSegmentManipulator::parse(segment, &in);
FAIL();
} catch (runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <newline> after 'C'"));
EXPECT_THAT(e.what(), StrEq("Expected: <newline> after 'C[1]'"));
}
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_Failed_TooManyElements) {
istringstream in("42 123 1 2 3 4 5\n");

try {
LineIOSegmentManipulator::parse(segment, &in);
FAIL();
} catch (runtime_error& e) {
EXPECT_THAT(e.what(), StrEq("Expected: <newline> after 'C[1]'"));
}
}

Expand All @@ -91,6 +126,12 @@ TEST_F(LineIOSegmentManipulatorTests, Parsing_WithVectorWithoutSize_Successful)
EXPECT_THAT(D, Eq(vector<int>{3, 4, 5}));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_WithVectorWithoutSize_Successful_CheckLastVariable) {
istringstream in("42 123 1 2 3 4 5\n");

EXPECT_THAT(LineIOSegmentManipulator::parse(segmentWithVectorWithoutSize, &in), Eq("'D[2]'"));
}

TEST_F(LineIOSegmentManipulatorTests, Parsing_WithVectorWithoutSize_Failed_MissingSpaceOrNewline) {
istringstream in("42 123 1 2 3 4 5");

Expand Down
12 changes: 12 additions & 0 deletions test/tcframe/io_manipulator/LinesIOSegmentManipulatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ TEST_F(LinesIOSegmentManipulatorTests, Parsing_Successful) {
EXPECT_THAT(Y, Eq(vector<int>{2, 4, 6}));
}

TEST_F(LinesIOSegmentManipulatorTests, Parsing_Successful_CheckLastVariable) {
istringstream in("1 2\n3 4\n5 6\n");

EXPECT_THAT(LinesIOSegmentManipulator::parse(segment, &in), Eq("'Y[2]'"));
}

TEST_F(LinesIOSegmentManipulatorTests, Parsing_Failed_MissingVariable) {
istringstream in("1 2\n3 ");

Expand Down Expand Up @@ -82,6 +88,12 @@ TEST_F(LinesIOSegmentManipulatorTests, Parsing_WithJaggedVector_Successful) {
EXPECT_THAT(Z, Eq(vector<vector<int>>{{10}, {}, {20, 30}}));
}

TEST_F(LinesIOSegmentManipulatorTests, Parsing_WithJaggedVector_Successful_CheckLastVariable) {
istringstream in("1 2 10\n3 4\n5 6 20 30\n");

EXPECT_THAT(LinesIOSegmentManipulator::parse(segmentWithJaggedVector, &in), Eq("'Z[2][1]'"));
}

TEST_F(LinesIOSegmentManipulatorTests, Parsing_WithJaggedVector_Failed_MissingSpaceOrNewline) {
istringstream in("1 2 10\n3 4\n5 6 20 30");

Expand Down

0 comments on commit 189b173

Please sign in to comment.