From 8835751449ac74918605874b8d0e1e6330619221 Mon Sep 17 00:00:00 2001 From: Benoy Bose Date: Tue, 10 Dec 2024 19:04:16 +0530 Subject: [PATCH] Corrected parsing bool literal by setting lexer priority --- .vscode/launch.json | 24 +++++++++++++++ CMakeLists.txt | 3 ++ HooLexer.g4 | 12 +++----- src/Visitor.cpp | 7 ++++- tests/CMakeLists.txt | 4 +++ tests/bool_tests.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 tests/bool_tests.cpp diff --git a/.vscode/launch.json b/.vscode/launch.json index dd0d729..566cbfd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -51,6 +51,30 @@ "ignoreFailures": true } ] + }, + { + "name": "Bool Test", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/tests/bool_tests", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] } ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 88fe9f0..7f91517 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ SET (ANTLR_INCLUDE_DIR /usr/local/include/antlr4-runtime/) SET (ANTLR_GENERATED_DIR "${CMAKE_BINARY_DIR}/antlr4/generated") SET (GRAMMAR_FILE "${CMAKE_SOURCE_DIR}/Hoo.g4") SET (LLVM_LIBRARY_DIRS "/usr/lib/llvm-19/lib") +set(CMAKE_INSTALL_RPATH "/usr/local/lib") +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) LINK_DIRECTORIES(${LLVM_LIBRARY_DIRS}) FIND_PACKAGE(LLVM REQUIRED CONFIG) ADD_DEFINITIONS(${LLVM_DEFINITIONS}) @@ -26,3 +28,4 @@ ADD_SUBDIRECTORY(tests) ENABLE_TESTING() ADD_TEST(NAME integer_tests COMMAND integer_tests) ADD_TEST(NAME double_tests COMMAND double_tests) +ADD_TEST(NAME bool_tests COMMAND bool_tests) \ No newline at end of file diff --git a/HooLexer.g4 b/HooLexer.g4 index e4768a5..c85e891 100644 --- a/HooLexer.g4 +++ b/HooLexer.g4 @@ -1,16 +1,10 @@ lexer grammar HooLexer; -IDENTIFIER: Letter LetterOrDigit*; - -fragment DIGIT: [0-9]; +BOOL_LITERAL: 'true' | 'false'; INTEGER_LITERAL: '0' | ('+' | '-')? [1-9] [0-9]*; -DOUBLE_LITERAL: ('+' | '-')? Digits+ '.' Digits+ ( - [eE] [+-]? Digits+ - )?; - -BOOL_LITERAL: 'true' | 'false'; +DOUBLE_LITERAL: ('+' | '-')? Digits+ '.' Digits+; CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\''; @@ -24,6 +18,8 @@ WS: [ \t\r\n\u000C]+ -> channel(HIDDEN); COMMENT: '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN); +IDENTIFIER: Letter LetterOrDigit*; + fragment EscapeSequence: '\\' 'u005c'? [btnfr"'\\] | '\\' 'u005c'? ([0-3]? [0-7])? [0-7] diff --git a/src/Visitor.cpp b/src/Visitor.cpp index 7d9f189..2bbfbd6 100644 --- a/src/Visitor.cpp +++ b/src/Visitor.cpp @@ -14,6 +14,11 @@ Visitor::Visitor(const std::string &moduleName) : _moduleName(moduleName), std::any Visitor::visitLiteral(HooParser::LiteralContext *ctx) { +#ifndef NDEBUG + auto text = ctx->getText(); + std::cout << "Literal: " << text << std::endl; +#endif + auto value = ctx->INTEGER_LITERAL(); if (value) { @@ -22,7 +27,7 @@ std::any Visitor::visitLiteral(HooParser::LiteralContext *ctx) llvm::Type *decimalType = llvm::Type::getInt64Ty(*_context); llvm::Constant *decimalConstant = llvm::ConstantInt::getSigned(decimalType, decimalValue); -#ifdef NDEBUG +#ifndef NDEBUG auto constantValue = llvm::dyn_cast(decimalConstant)->getValue().getSExtValue(); assert(constantValue == decimalValue); #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8deadcf..6254421 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,3 +7,7 @@ TARGET_INCLUDE_DIRECTORIES(integer_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ ADD_EXECUTABLE(double_tests double_tests.cpp) TARGET_LINK_LIBRARIES(double_tests GTest::GTest GTest::Main hoocore antlr4-runtime LLVMCore LLVMSupport) TARGET_INCLUDE_DIRECTORIES(double_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src) + +ADD_EXECUTABLE(bool_tests bool_tests.cpp) +TARGET_LINK_LIBRARIES(bool_tests GTest::GTest GTest::Main hoocore antlr4-runtime LLVMCore LLVMSupport) +TARGET_INCLUDE_DIRECTORIES(bool_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src) \ No newline at end of file diff --git a/tests/bool_tests.cpp b/tests/bool_tests.cpp new file mode 100644 index 0000000..b55bc11 --- /dev/null +++ b/tests/bool_tests.cpp @@ -0,0 +1,71 @@ +#include "Compiler.hpp" +#include "Node.hpp" +#include "llvm/IR/Constants.h" +#include + +// Utility function to test boolean literal compilation +void testBoolLiteral(const std::string &input, bool expectedValue) +{ + auto compiler = std::make_unique(input, "main"); + auto result = compiler->compile(); + auto boolNode = std::any_cast(result); + + // Validate node type and data type + ASSERT_EQ(boolNode.getNodeType(), NODE_LITERAL); + ASSERT_EQ(boolNode.getDataType(), DATATYPE_BOOL); + + // Validate LLVM value + auto value = boolNode.getValue(); + ASSERT_NE(value, nullptr); + + auto value_constant = llvm::dyn_cast(value); + ASSERT_NE(value_constant, nullptr); + + // Check the boolean value (1 for true, 0 for false) + ASSERT_EQ(value_constant->getValue().getLimitedValue(), static_cast(expectedValue)); +} + +// Test fixture for boolean tests +class BoolTest : public ::testing::Test +{ +protected: + void SetUp() override + { + // Setup code if needed + } + + void TearDown() override + { + // Cleanup code if needed + } +}; + +// Test cases +TEST_F(BoolTest, LiteralTrue) +{ + testBoolLiteral("true;", true); +} + +TEST_F(BoolTest, LiteralFalse) +{ + testBoolLiteral("false;", false); +} + +// Negative test cases +TEST_F(BoolTest, InvalidLiteral) +{ + auto compiler = std::make_unique("notbool;", "main"); + ASSERT_THROW(compiler->compile(), std::invalid_argument); +} + +TEST_F(BoolTest, MissingSemicolon) +{ + auto compiler = std::make_unique("true", "main"); + ASSERT_THROW(compiler->compile(), std::runtime_error); +} + +TEST_F(BoolTest, MixedCaseLiteral) +{ + auto compiler = std::make_unique("True;", "main"); + ASSERT_THROW(compiler->compile(), std::invalid_argument); // Expect strict case-sensitivity +}