Loading Parser.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -73,3 +73,17 @@ void Parser::cannot_coerce(const Token& where, std::string from, std::string to) ss << "Cannot coerce " << from << " to " << to << "." << std::endl; type_error(where, ss.str()); } void Parser::extra_parameter(const Token& where) { std::ostringstream ss; ss << "Unexpected extra function call parameter." << std::endl; type_error(where, ss.str()); } void Parser::missing_parameter(const Token& where) { std::ostringstream ss; ss << "Expected extra function call parameter." << std::endl; type_error(where, ss.str()); } Parser.hpp +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ protected: void multiply_defined_function(const Token& name); void type_error(const Token& where, std::string msg); void cannot_coerce(const Token& where, std::string from, std::string to); void extra_parameter(const Token& where); void missing_parameter(const Token& where); public: virtual ~Parser() = default; Loading XMLParser.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -351,15 +351,20 @@ DataType XMLParser::grammar_arithmetic_expression() token = lexer.getNext(); if (token.term.type != TT_LEFTPAREN) expected_tokens(token, { Term::from_character.find('(')->second }); grammar_arithmetic_expression_list(); SymbolData& data = symbols.find(name_token.term.payload); if (data.symbol_type != ST_FUNCTION) undefined_function(name_token); assert(data.data_type.size() > 1); // Pass a copy of the expected types reversed, so that we can pop_back() on them. std::vector<DataType> expected_types; expected_types.resize(data.data_type.size() - 1); std::reverse_copy(data.data_type.begin(), data.data_type.end() - 1, expected_types.begin()); grammar_arithmetic_expression_list(expected_types); token = lexer.getNext(); if (token.term.type != TT_RIGHTPAREN) expected_tokens(token, { Term::from_character.find(')')->second }); get_current_out() << "</call>" << std::endl; SymbolData& data = symbols.find(name_token.term.payload); if (data.symbol_type != ST_FUNCTION) undefined_function(name_token); assert(!data.data_type.empty()); return data.data_type.back(); } else { start_buffering(); Loading Loading @@ -428,7 +433,7 @@ DataType XMLParser::grammar_arithmetic_expression_tail(DataType left_operand_typ } } void XMLParser::grammar_arithmetic_expression_list() void XMLParser::grammar_arithmetic_expression_list(std::vector<DataType>& expected_types) { get_current_out() << "<arithmetic_expressions>" << std::endl; auto token = lexer.peekNext(); Loading @@ -441,13 +446,14 @@ void XMLParser::grammar_arithmetic_expression_list() Term::from_character.find('-')->second, Term::from_character.find(')')->second }); if (token.term.type != TT_RIGHTPAREN) { grammar_arithmetic_expression(); grammar_arithmetic_expression_list_tail(); grammar_coerced_arithmetic_expression(token, expected_types.back()); expected_types.pop_back(); grammar_arithmetic_expression_list_tail(expected_types); } get_current_out() << "</arithmetic_expressions>" << std::endl; } void XMLParser::grammar_arithmetic_expression_list_tail() void XMLParser::grammar_arithmetic_expression_list_tail(std::vector<DataType>& expected_types) { auto token = lexer.peekNext(); if (token.term.type != TT_COMMA && token.term.type != TT_RIGHTPAREN) Loading @@ -455,8 +461,14 @@ void XMLParser::grammar_arithmetic_expression_list_tail() Term::from_character.find(')')->second }); if (token.term.type == TT_COMMA) { lexer.getNext(); grammar_arithmetic_expression(); grammar_arithmetic_expression_list_tail(); if (expected_types.empty()) extra_parameter(lexer.peekNext()); grammar_coerced_arithmetic_expression(token, expected_types.back()); expected_types.pop_back(); grammar_arithmetic_expression_list_tail(expected_types); } else { if (!expected_types.empty()) missing_parameter(token); } } Loading XMLParser.hpp +2 −2 Original line number Diff line number Diff line Loading @@ -112,8 +112,8 @@ private: void grammar_coerced_arithmetic_expression(const Token& where, DataType expected_type); DataType grammar_arithmetic_expression(); DataType grammar_arithmetic_expression_tail(DataType left_operand_type); void grammar_arithmetic_expression_list(); void grammar_arithmetic_expression_list_tail(); void grammar_arithmetic_expression_list(std::vector<DataType>& expected_types); void grammar_arithmetic_expression_list_tail(std::vector<DataType>& expected_types); DataType grammar_arithmetic_factor(); DataType grammar_arithmetic_factor_tail(DataType left_operand_type); DataType grammar_arithmetic_operand(); Loading tests/XMLParser.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -162,3 +162,51 @@ TEST(XMLParser, cannotCoerceReturn) std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Identifier, \"return\") at line 2, character number 3: Cannot coerce double to integer.", line); } TEST(XMLParser, cannotCoerceCall) { std::ifstream input_stream("tests/XMLParser/cannot_coerce_call.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Real number, \"1.23456\") at line 7, character number 12: Cannot coerce double to integer.", line); } TEST(XMLParser, extraParameter) { std::ifstream input_stream("tests/XMLParser/extra_parameter.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Integer, \"13\") at line 7, character number 16: Unexpected extra function call parameter.", line); } TEST(XMLParser, missingParameter) { std::ifstream input_stream("tests/XMLParser/missing_parameter.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Right parenthesis, \")\") at line 7, character number 14: Expected extra function call parameter.", line); } Loading
Parser.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -73,3 +73,17 @@ void Parser::cannot_coerce(const Token& where, std::string from, std::string to) ss << "Cannot coerce " << from << " to " << to << "." << std::endl; type_error(where, ss.str()); } void Parser::extra_parameter(const Token& where) { std::ostringstream ss; ss << "Unexpected extra function call parameter." << std::endl; type_error(where, ss.str()); } void Parser::missing_parameter(const Token& where) { std::ostringstream ss; ss << "Expected extra function call parameter." << std::endl; type_error(where, ss.str()); }
Parser.hpp +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ protected: void multiply_defined_function(const Token& name); void type_error(const Token& where, std::string msg); void cannot_coerce(const Token& where, std::string from, std::string to); void extra_parameter(const Token& where); void missing_parameter(const Token& where); public: virtual ~Parser() = default; Loading
XMLParser.cpp +23 −11 Original line number Diff line number Diff line Loading @@ -351,15 +351,20 @@ DataType XMLParser::grammar_arithmetic_expression() token = lexer.getNext(); if (token.term.type != TT_LEFTPAREN) expected_tokens(token, { Term::from_character.find('(')->second }); grammar_arithmetic_expression_list(); SymbolData& data = symbols.find(name_token.term.payload); if (data.symbol_type != ST_FUNCTION) undefined_function(name_token); assert(data.data_type.size() > 1); // Pass a copy of the expected types reversed, so that we can pop_back() on them. std::vector<DataType> expected_types; expected_types.resize(data.data_type.size() - 1); std::reverse_copy(data.data_type.begin(), data.data_type.end() - 1, expected_types.begin()); grammar_arithmetic_expression_list(expected_types); token = lexer.getNext(); if (token.term.type != TT_RIGHTPAREN) expected_tokens(token, { Term::from_character.find(')')->second }); get_current_out() << "</call>" << std::endl; SymbolData& data = symbols.find(name_token.term.payload); if (data.symbol_type != ST_FUNCTION) undefined_function(name_token); assert(!data.data_type.empty()); return data.data_type.back(); } else { start_buffering(); Loading Loading @@ -428,7 +433,7 @@ DataType XMLParser::grammar_arithmetic_expression_tail(DataType left_operand_typ } } void XMLParser::grammar_arithmetic_expression_list() void XMLParser::grammar_arithmetic_expression_list(std::vector<DataType>& expected_types) { get_current_out() << "<arithmetic_expressions>" << std::endl; auto token = lexer.peekNext(); Loading @@ -441,13 +446,14 @@ void XMLParser::grammar_arithmetic_expression_list() Term::from_character.find('-')->second, Term::from_character.find(')')->second }); if (token.term.type != TT_RIGHTPAREN) { grammar_arithmetic_expression(); grammar_arithmetic_expression_list_tail(); grammar_coerced_arithmetic_expression(token, expected_types.back()); expected_types.pop_back(); grammar_arithmetic_expression_list_tail(expected_types); } get_current_out() << "</arithmetic_expressions>" << std::endl; } void XMLParser::grammar_arithmetic_expression_list_tail() void XMLParser::grammar_arithmetic_expression_list_tail(std::vector<DataType>& expected_types) { auto token = lexer.peekNext(); if (token.term.type != TT_COMMA && token.term.type != TT_RIGHTPAREN) Loading @@ -455,8 +461,14 @@ void XMLParser::grammar_arithmetic_expression_list_tail() Term::from_character.find(')')->second }); if (token.term.type == TT_COMMA) { lexer.getNext(); grammar_arithmetic_expression(); grammar_arithmetic_expression_list_tail(); if (expected_types.empty()) extra_parameter(lexer.peekNext()); grammar_coerced_arithmetic_expression(token, expected_types.back()); expected_types.pop_back(); grammar_arithmetic_expression_list_tail(expected_types); } else { if (!expected_types.empty()) missing_parameter(token); } } Loading
XMLParser.hpp +2 −2 Original line number Diff line number Diff line Loading @@ -112,8 +112,8 @@ private: void grammar_coerced_arithmetic_expression(const Token& where, DataType expected_type); DataType grammar_arithmetic_expression(); DataType grammar_arithmetic_expression_tail(DataType left_operand_type); void grammar_arithmetic_expression_list(); void grammar_arithmetic_expression_list_tail(); void grammar_arithmetic_expression_list(std::vector<DataType>& expected_types); void grammar_arithmetic_expression_list_tail(std::vector<DataType>& expected_types); DataType grammar_arithmetic_factor(); DataType grammar_arithmetic_factor_tail(DataType left_operand_type); DataType grammar_arithmetic_operand(); Loading
tests/XMLParser.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -162,3 +162,51 @@ TEST(XMLParser, cannotCoerceReturn) std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Identifier, \"return\") at line 2, character number 3: Cannot coerce double to integer.", line); } TEST(XMLParser, cannotCoerceCall) { std::ifstream input_stream("tests/XMLParser/cannot_coerce_call.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Real number, \"1.23456\") at line 7, character number 12: Cannot coerce double to integer.", line); } TEST(XMLParser, extraParameter) { std::ifstream input_stream("tests/XMLParser/extra_parameter.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Integer, \"13\") at line 7, character number 16: Unexpected extra function call parameter.", line); } TEST(XMLParser, missingParameter) { std::ifstream input_stream("tests/XMLParser/missing_parameter.in"); Lexer lexer(input_stream, std::cout, std::cerr); std::ostringstream error_stream_out; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); XMLParser parser(lexer, null_stream, error_stream_out); ASSERT_THROW(parser.run(), std::invalid_argument); std::istringstream error_stream_in(error_stream_out.str()); std::string line; std::getline(error_stream_in, line); ASSERT_EQ("Parser error:\tType error from (Right parenthesis, \")\") at line 7, character number 14: Expected extra function call parameter.", line); }