Corrected parsing bool literal by setting lexer priority

This commit is contained in:
Benoy Bose 2024-12-10 19:04:16 +05:30
parent 81b677b9fe
commit 8835751449
6 changed files with 112 additions and 9 deletions

24
.vscode/launch.json vendored
View File

@ -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
}
]
}
]
}

View File

@ -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)

View File

@ -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]

View File

@ -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<llvm::ConstantInt>(decimalConstant)->getValue().getSExtValue();
assert(constantValue == decimalValue);
#endif

View File

@ -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)

71
tests/bool_tests.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "Compiler.hpp"
#include "Node.hpp"
#include "llvm/IR/Constants.h"
#include <gtest/gtest.h>
// Utility function to test boolean literal compilation
void testBoolLiteral(const std::string &input, bool expectedValue)
{
auto compiler = std::make_unique<Compiler>(input, "main");
auto result = compiler->compile();
auto boolNode = std::any_cast<Node>(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<llvm::ConstantInt>(value);
ASSERT_NE(value_constant, nullptr);
// Check the boolean value (1 for true, 0 for false)
ASSERT_EQ(value_constant->getValue().getLimitedValue(), static_cast<uint64_t>(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<Compiler>("notbool;", "main");
ASSERT_THROW(compiler->compile(), std::invalid_argument);
}
TEST_F(BoolTest, MissingSemicolon)
{
auto compiler = std::make_unique<Compiler>("true", "main");
ASSERT_THROW(compiler->compile(), std::runtime_error);
}
TEST_F(BoolTest, MixedCaseLiteral)
{
auto compiler = std::make_unique<Compiler>("True;", "main");
ASSERT_THROW(compiler->compile(), std::invalid_argument); // Expect strict case-sensitivity
}