mirror of
https://github.com/fedapo/vb6-parser.git
synced 2025-12-16 16:27:03 +03:00
Review all tests
This commit is contained in:
162
CMakeLists.txt
162
CMakeLists.txt
@@ -1,148 +1,66 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
project(vb6_parser)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# see https://google.github.io/googletest/quickstart-cmake.html
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/7df7853ea02371f6d24ccf4a0cf9e16553d23d05.zip
|
||||
)
|
||||
# for Windows: prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
#------------------------------------------------------------------------------
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
add_compile_options($<$<CXX_COMPILER_ID:GNU,Clang>:-Wall> $<$<CXX_COMPILER_ID:GNU,Clang>:-Wextra>)
|
||||
|
||||
#find_package(GTest CONFIG REQUIRED) # GoogleTest with vcpkg
|
||||
find_package(ut CONFIG REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS system)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Boost REQUIRED QUIET COMPONENTS system)
|
||||
|
||||
add_compile_definitions(
|
||||
BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
BOOST_MPL_LIMIT_LIST_SIZE=30
|
||||
)
|
||||
|
||||
add_library(vb6_parser_lib
|
||||
src/raw_ast_printer.cpp
|
||||
src/raw_ast_printer.hpp
|
||||
src/color_console.cpp
|
||||
src/color_console.hpp
|
||||
src/cpp_ast_printer.cpp
|
||||
src/cpp_ast_printer.hpp
|
||||
src/vb6_ast.hpp
|
||||
src/vb6_ast_adapt.hpp
|
||||
src/vb6_config.hpp
|
||||
src/vb6_error_handler.hpp
|
||||
src/vb6_parser.cpp
|
||||
src/vb6_parser.hpp
|
||||
src/vb6_parser_def.hpp
|
||||
src/vb6_parser_functions.cpp
|
||||
src/vb6_parser_helper.cpp
|
||||
src/vb6_parser_keywords.hpp
|
||||
src/vb6_parser_operators.hpp
|
||||
src/vb6_parser_statements.cpp
|
||||
src/vb6_parser_statements_def.hpp
|
||||
src/vb6_ast_printer.cpp
|
||||
src/vb6_ast_printer.hpp
|
||||
src/visual_basic_x3.hpp
|
||||
src/raw_ast_printer.cpp
|
||||
src/color_console.cpp
|
||||
src/cpp_ast_printer.cpp
|
||||
src/vb6_parser.cpp
|
||||
src/vb6_parser_functions.cpp
|
||||
src/vb6_parser_helper.cpp
|
||||
src/vb6_parser_statements.cpp
|
||||
src/vb6_ast_printer.cpp
|
||||
|
||||
src/raw_ast_printer.hpp
|
||||
src/color_console.hpp
|
||||
src/cpp_ast_printer.hpp
|
||||
src/vb6_ast.hpp
|
||||
src/vb6_ast_adapt.hpp
|
||||
src/vb6_config.hpp
|
||||
src/vb6_error_handler.hpp
|
||||
src/vb6_parser.hpp
|
||||
src/vb6_parser_def.hpp
|
||||
src/vb6_parser_keywords.hpp
|
||||
src/vb6_parser_operators.hpp
|
||||
src/vb6_parser_statements_def.hpp
|
||||
src/vb6_ast_printer.hpp
|
||||
src/visual_basic_x3.hpp
|
||||
)
|
||||
|
||||
target_compile_definitions(vb6_parser_lib
|
||||
PRIVATE
|
||||
-DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
-DBOOST_MPL_LIMIT_LIST_SIZE=30
|
||||
)
|
||||
target_include_directories(vb6_parser_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
target_link_libraries(vb6_parser_lib
|
||||
PRIVATE
|
||||
Boost::system
|
||||
Boost::system
|
||||
)
|
||||
|
||||
add_executable(vb6_parser
|
||||
src/vb6_parser_main.cpp
|
||||
src/vb6_test1.cpp
|
||||
src/vb6_test2.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(vb6_parser
|
||||
PRIVATE
|
||||
-DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
-DBOOST_MPL_LIMIT_LIST_SIZE=30
|
||||
src/vb6_parser_main.cpp
|
||||
src/vb6_test1.cpp
|
||||
src/vb6_test2.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
vb6_parser_lib
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
# ---- test
|
||||
|
||||
add_executable(vb6_parser.ut
|
||||
#src/test_gosub.cpp
|
||||
#src/test_grammar_helper_gtest.hpp
|
||||
#src/vb6_parser_statements_test.cpp
|
||||
src/vb6_parser.ut.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(vb6_parser.ut
|
||||
PRIVATE
|
||||
-DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
-DBOOST_MPL_LIMIT_LIST_SIZE=30
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser.ut
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
Boost::ut
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
add_executable(vb6_parser_test
|
||||
src/test_gosub.cpp
|
||||
src/test_grammar_helper_gtest.hpp
|
||||
src/vb6_parser_statements_test.cpp
|
||||
src/vb6_parser_test.cpp
|
||||
src/vb6_parser_test_main.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(vb6_parser_test
|
||||
PRIVATE
|
||||
-DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
-DBOOST_MPL_LIMIT_LIST_SIZE=30
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser_test
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
gtest_main
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
#[[
|
||||
# GoogleTest with vcpkg, probably not a good idea
|
||||
target_link_libraries(vb6_parser_test
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
)
|
||||
#]]
|
||||
|
||||
set_target_properties(vb6_parser.ut PROPERTIES EXCLUDE_FROM_ALL 1)
|
||||
|
||||
include(CTest)
|
||||
#enable_testing()
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(vb6_parser_test)
|
||||
|
||||
add_test(AllTestsInMain vb6_parser_test)
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -2,16 +2,26 @@
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"displayName": "vcpkg Config",
|
||||
"description": "Build using vcpkg as a package manager",
|
||||
"generator": "Unix Makefiles",
|
||||
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"name": "default",
|
||||
"generator": "Ninja",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"inherits": "default",
|
||||
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"binaryDir": "${sourceDir}/build"
|
||||
},
|
||||
{
|
||||
"name": "clang",
|
||||
"inherits": "vcpkg",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
|
||||
19
README.md
19
README.md
@@ -1,6 +1,6 @@
|
||||
# vb6-parser
|
||||
|
||||
A parsing engine for Microsoft's Visual Basic 6 programming language based on the Boost.Spirit library.
|
||||
A parsing engine for Microsoft's Visual Basic 6 programming language based on the Boost.Spirit X3 library.
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -10,10 +10,9 @@ https://github.com/fedapo/vb6-parser.git
|
||||
|
||||
## Building with CMake
|
||||
|
||||
```shell
|
||||
> mkdir build
|
||||
> cmake . -B build/
|
||||
> cmake --build build/
|
||||
```sh
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
## Building with Microsoft Visual Studio
|
||||
@@ -22,10 +21,12 @@ Open the file `vb_parser.sln` with Microsoft Visual Studio. Build all.
|
||||
|
||||
## Usage
|
||||
|
||||
The project produces a library, vb_parser_lib, used for the moment only by two executables.
|
||||
The project produces a library, vb_parser_lib, used by these executables.
|
||||
|
||||
- vb6_parser
|
||||
- vb6_parser_test
|
||||
- `vb6_parser`
|
||||
- `vb6_parser.doctest`
|
||||
- `vb6_parser.gtest`
|
||||
- `vb6_parser.ut`
|
||||
|
||||
These run a series of tests to ensure the parser runs correctly.
|
||||
|
||||
@@ -37,6 +38,8 @@ These run a series of tests to ensure the parser runs correctly.
|
||||
|
||||
- Boost Spirit X3
|
||||
- GTest
|
||||
- Doctest
|
||||
- Boost.UT
|
||||
- CMake
|
||||
- GCC
|
||||
- Clang
|
||||
|
||||
@@ -21,6 +21,9 @@ BASIC = Beginner's All-purpose Symbolic Instruction Code
|
||||
Visual Basic 6 Renewed to Run on Windows 8 \
|
||||
https://www.infoq.com/news/2012/02/vb6_supported_on_win8
|
||||
|
||||
https://www.indiegogo.com/projects/a-replacement-to-visual-basic-6-ide-and-compiler#/
|
||||
https://www.codeproject.com/Articles/710181/Visual-Basic-6-0-A-giant-more-powerful-than-ever
|
||||
|
||||
---
|
||||
## Complete VB6 Grammars
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
|
||||
template <class ruleType, class attrType>
|
||||
@@ -53,10 +53,10 @@ void test_grammar(std::ostream& os, std::string_view testName, ruleType rule,
|
||||
{
|
||||
os << tag_ok << '\n';
|
||||
if(it1 != it2)
|
||||
os << " but we stopped at " << std::string(it1, it2) << '\n';
|
||||
os << " but we stopped at " << std::string_view(it1, it2) << '\n';
|
||||
}
|
||||
else
|
||||
os << tag_fail << " - stopped at: " << std::string(it1, it2) << '\n';
|
||||
os << tag_fail << " - stopped at: " << std::string_view(it1, it2) << '\n';
|
||||
}
|
||||
catch(x3::expectation_failure<decltype(it1)>& e)
|
||||
{
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
//: test_grammar_helper.hpp
|
||||
|
||||
// vb6_parser
|
||||
// Copyright (c) 2022 Federico Aponte
|
||||
// This code is licensed under GNU Software License (see LICENSE.txt for details)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "color_console.hpp"
|
||||
#include "vb6_config.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
template <class ruleType, class attrType>
|
||||
void test_grammar(std::string_view fragment, ruleType rule, attrType& attr, bool expected = true)
|
||||
{
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
auto it1 = cbegin(fragment);
|
||||
auto const it2 = cend(fragment);
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
vb6_grammar::error_handler_type error_handler(it1, it2, out, "source.bas");
|
||||
|
||||
auto const parser =
|
||||
// we pass our error handler to the parser so we can access
|
||||
// it later on in our on_error and on_success handlers
|
||||
x3::with<vb6_grammar::vb6_error_handler_tag>(std::ref(error_handler))
|
||||
[
|
||||
rule
|
||||
];
|
||||
|
||||
ASSERT_TRUE(x3::phrase_parse(it1, it2, parser, vb6_grammar::skip, attr) == expected)
|
||||
<< "stopped at: " << std::string(it1, it2);
|
||||
|
||||
EXPECT_EQ(it1, it2);
|
||||
}
|
||||
@@ -1,853 +0,0 @@
|
||||
//: vb6_parser.ut.cpp
|
||||
|
||||
// vb6_parser
|
||||
// Copyright (c) 2022 Federico Aponte
|
||||
// This code is licensed under GNU Software License (see LICENSE.txt for details)
|
||||
|
||||
//#define BOOST_SPIRIT_X3_DEBUG
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
|
||||
#include "test_grammar_helper_ut.hpp"
|
||||
#include "vb6_parser.hpp"
|
||||
#include "vb6_ast_printer.hpp"
|
||||
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include <boost/ut.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
namespace x3 = boost::spirit::x3;
|
||||
namespace ut = boost::ut;
|
||||
|
||||
void log_compiler_info(std::ostream& os)
|
||||
{
|
||||
// how to tell that AppleClang and not plain Clang has been used?
|
||||
// __APPLE_CC__ does not work as it's always defined
|
||||
#if defined(__clang__)
|
||||
os << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__<< '\n';
|
||||
#elif defined(__GNUC__)
|
||||
os << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__<< '\n';
|
||||
#elif defined(__MSC_VER)
|
||||
os << "Compiler: MSC " << __MSC_VER << '\n';
|
||||
#endif
|
||||
}
|
||||
|
||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
|
||||
{
|
||||
using namespace boost::ut;
|
||||
|
||||
log_compiler_info(cout);
|
||||
|
||||
[[maybe_unused]] ut::suite vb6_parser_simple = []
|
||||
{
|
||||
"lonely_comment"_test = []
|
||||
{
|
||||
vector<vb6_ast::lonely_comment> ast;
|
||||
test_grammar(
|
||||
"' This is comment line 1\r\n' Comment line 2\r\n",
|
||||
*vb6_grammar::lonely_comment, ast);
|
||||
|
||||
cout << ast.size() << "\n";
|
||||
ut::expect(ut::eq(ast.size(), 2));
|
||||
|
||||
ut::expect(ast[0].content == " This is comment line 1");
|
||||
ut::expect(ast[1].content == " Comment line 2");
|
||||
};
|
||||
|
||||
"empty_lines"_test = []
|
||||
{
|
||||
vector<
|
||||
boost::variant<vb6_ast::empty_line, vb6_ast::lonely_comment>
|
||||
> ast;
|
||||
// critical to have lonely_comment first in the parsing rule
|
||||
auto const G = *(vb6_grammar::lonely_comment | vb6_grammar::empty_line);
|
||||
auto str = "' comment1\r\n"
|
||||
"\r\n"
|
||||
"' comment2\r\n";
|
||||
test_grammar(str, G, ast);
|
||||
|
||||
ut::expect(ast.size() == 3);
|
||||
|
||||
ut::expect(boost::get<vb6_ast::lonely_comment>(ast[0]).content == " comment1");
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast[1]);}));
|
||||
ut::expect(boost::get<vb6_ast::lonely_comment>(ast[2]).content == " comment2");
|
||||
};
|
||||
|
||||
"quoted_string"_test = []
|
||||
{
|
||||
string str;
|
||||
test_grammar("\"Quoted string.\"", vb6_grammar::quoted_string, str);
|
||||
ut::expect(str == "Quoted string.");
|
||||
};
|
||||
|
||||
"basic_identifier"_test = []
|
||||
{
|
||||
string id;
|
||||
test_grammar("iden_tifier", vb6_grammar::basic_identifier, id);
|
||||
ut::expect(id == "iden_tifier");
|
||||
};
|
||||
|
||||
"var_identifier"_test = []
|
||||
{
|
||||
string var;
|
||||
test_grammar("g_logger", vb6_grammar::var_identifier, var);
|
||||
ut::expect(var == "g_logger");
|
||||
|
||||
var.clear();
|
||||
test_grammar("forth ", vb6_grammar::sub_identifier, var);
|
||||
ut::expect(var == "forth");
|
||||
|
||||
var.clear();
|
||||
test_grammar("subroutine ", vb6_grammar::sub_identifier, var);
|
||||
ut::expect(var == "subroutine");
|
||||
|
||||
/*
|
||||
string code = "sub ";
|
||||
string_view code_sv = code;
|
||||
auto it1 = cbegin(code_sv);
|
||||
auto const it2 = cend(code_sv);
|
||||
ut::expect(!boost::spirit::x3::phrase_parse(it1, it2, vb6_grammar::sub_identifier, vb6_grammar::skip, var));
|
||||
ut::expect(it1 == begin(code_sv));
|
||||
*/
|
||||
};
|
||||
|
||||
"type_identifier"_test = []
|
||||
{
|
||||
string type;
|
||||
test_grammar("Long", vb6_grammar::type_identifier, type);
|
||||
ut::expect(that % type == "Long"s);
|
||||
};
|
||||
|
||||
"complex_type_identifier"_test = []
|
||||
{
|
||||
string type;
|
||||
test_grammar("VB.Form", vb6_grammar::complex_type_identifier, type);
|
||||
ut::expect(that % type == "VB.Form"s);
|
||||
};
|
||||
|
||||
"const_expression_non_numeric"_test = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "\"una stringa\""s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::quoted_string>(ast.get()) == "una stringa"s);
|
||||
|
||||
str = "True"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(boost::get<bool>(ast.get()));
|
||||
|
||||
str = "Nothing"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::nothing>(ast.get());}));
|
||||
};
|
||||
|
||||
"const_expression_integers"_test = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "1234%"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::integer_dec>(ast.get()).val == 1234);
|
||||
|
||||
str = "1234&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::long_dec>(ast.get()).val == 1234);
|
||||
|
||||
str = "&Hcafedead&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::long_hex>(ast.get()).val == 0xcafedead);
|
||||
|
||||
str = "&01234&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::long_oct>(ast.get()).val == 01234);
|
||||
|
||||
str = "1234"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(that % boost::get<vb6_ast::integer_dec>(ast.get()).val == 1234);
|
||||
};
|
||||
|
||||
"const_expression_floats"_test = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "1234!"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(boost::get<float>(ast.get()) == 1234.0f);
|
||||
|
||||
str = "1234#"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(boost::get<double>(ast.get()) == 1234.0);
|
||||
|
||||
str = "2.8"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect(boost::get<float>(ast.get()) == 2.8f);
|
||||
};
|
||||
|
||||
"sample_expression"_test = []
|
||||
{
|
||||
vb6_ast::expression ast;
|
||||
test_grammar("foo1(foo2(3, M.x_coord), True)", vb6_grammar::expression, ast);
|
||||
ut::expect(ast.get().type() == typeid(x3::forward_ast<vb6_ast::func_call>));
|
||||
ut::expect(boost::get<x3::forward_ast<vb6_ast::func_call>>(ast.get()).get().func_name == "foo1");
|
||||
};
|
||||
|
||||
"single_var_declaration"_test = []
|
||||
{
|
||||
vb6_ast::variable P1;
|
||||
test_grammar("g_logger As Long", vb6_grammar::single_var_declaration, P1);
|
||||
ut::expect(P1.name == "g_logger");
|
||||
ut::expect(!P1.construct);
|
||||
ut::expect(P1.type.has_value());
|
||||
if(P1.type)
|
||||
{
|
||||
ut::expect(*P1.type == "Long");
|
||||
}
|
||||
|
||||
vb6_ast::variable P2;
|
||||
test_grammar("name As New String", vb6_grammar::single_var_declaration, P2);
|
||||
ut::expect(P2.name == "name");
|
||||
ut::expect(P2.construct);
|
||||
ut::expect(P2.type.has_value());
|
||||
if(P2.type)
|
||||
{
|
||||
ut::expect(*P2.type == "String");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
[[maybe_unused]] ut::suite vb6_parser_tests = []
|
||||
{
|
||||
"record_declaration"_test = []
|
||||
{
|
||||
vb6_ast::record rec;
|
||||
test_grammar("Type PatRecord\r\n name As String\r\n age As Integer\r\nEnd Type\r\n",
|
||||
vb6_grammar::record_declaration, rec);
|
||||
|
||||
ut::expect(rec.name == "PatRecord");
|
||||
ut::expect(rec.at == vb6_ast::access_type::na);
|
||||
ut::expect(rec.members.size() == 2);
|
||||
|
||||
ut::expect(rec.members[0].name == "name");
|
||||
ut::expect(rec.members[0].type.has_value());
|
||||
if(rec.members[0].type)
|
||||
{
|
||||
ut::expect(*rec.members[0].type == "String");
|
||||
}
|
||||
ut::expect(!rec.members[0].construct);
|
||||
|
||||
ut::expect(rec.members[1].name == "age");
|
||||
ut::expect(rec.members[1].type.has_value());
|
||||
if(rec.members[1].type)
|
||||
{
|
||||
ut::expect(*rec.members[1].type == "Integer");
|
||||
}
|
||||
ut::expect(!rec.members[1].construct);
|
||||
};
|
||||
|
||||
"enum_declaration"_test = []
|
||||
{
|
||||
vb6_ast::vb_enum enum1;
|
||||
test_grammar("Enum PatTypes\r\n inpatient\r\n outpatient\r\nEnd Enum\r\n",
|
||||
vb6_grammar::enum_declaration, enum1);
|
||||
|
||||
ut::expect(enum1.name == "PatTypes");
|
||||
ut::expect(enum1.at == vb6_ast::access_type::na);
|
||||
ut::expect((enum1.values.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(enum1.values[0].first == "inpatient");
|
||||
ut::expect(!enum1.values[0].second);
|
||||
|
||||
ut::expect(enum1.values[1].first == "outpatient");
|
||||
ut::expect(!enum1.values[1].second);
|
||||
};
|
||||
|
||||
"global_var_declaration"_test = []
|
||||
{
|
||||
auto str = "Global g_logger As Long, v1, XRes As New Object, ptr As Module.MyRec, g_active As Boolean\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
|
||||
ut::expect(vars.at == vb6_ast::access_type::global);
|
||||
ut::expect(!vars.with_events);
|
||||
ut::expect((vars.vars.size() == 5) >> ut::fatal);
|
||||
|
||||
cout << "size: " << vars.vars.size() << "\n";
|
||||
|
||||
ut::expect(vars.vars[0].name == "g_logger");
|
||||
ut::expect(!vars.vars[0].construct);
|
||||
ut::expect(vars.vars[0].type.has_value());
|
||||
if(vars.vars[0].type)
|
||||
{
|
||||
ut::expect(*vars.vars[0].type == "Long");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[1].name == "v1");
|
||||
ut::expect(!vars.vars[1].construct);
|
||||
ut::expect(!vars.vars[1].type.has_value());
|
||||
|
||||
ut::expect(vars.vars[2].name == "XRes");
|
||||
ut::expect(vars.vars[2].construct);
|
||||
ut::expect(vars.vars[2].type.has_value());
|
||||
if(vars.vars[2].type)
|
||||
{
|
||||
ut::expect(*vars.vars[2].type == "Object");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[3].name == "ptr");
|
||||
ut::expect(!vars.vars[3].construct);
|
||||
ut::expect(vars.vars[3].type.has_value());
|
||||
if(vars.vars[3].type)
|
||||
{
|
||||
ut::expect(*vars.vars[3].type == "MyRec");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[4].name == "g_active");
|
||||
ut::expect(!vars.vars[4].construct);
|
||||
ut::expect(vars.vars[4].type.has_value());
|
||||
if(vars.vars[4].type)
|
||||
{
|
||||
ut::expect(*vars.vars[4].type == "Boolean");
|
||||
}
|
||||
};
|
||||
|
||||
"const_var_declaration1"_test = []
|
||||
{
|
||||
auto cstr = "Const e As Single = 2.8, pi As Double = 3.14, u As Integer = -1\r\n"s;
|
||||
vb6_ast::const_var_stat cvars;
|
||||
test_grammar(cstr, vb6_grammar::const_var_declaration, cvars);
|
||||
|
||||
ut::expect((cvars.size() == 3) >> ut::fatal);
|
||||
|
||||
cout << "size: " << cvars.size() << "\n";
|
||||
|
||||
ut::expect(cvars[0].var.name == "e");
|
||||
if(cvars[0].var.type)
|
||||
{
|
||||
ut::expect(*cvars[0].var.type == "Single");
|
||||
}
|
||||
ut::expect(!cvars[0].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[0].value.get()) == 2.8f);
|
||||
|
||||
ut::expect(cvars[1].var.name == "pi");
|
||||
if(cvars[1].var.type)
|
||||
{
|
||||
ut::expect(*cvars[1].var.type == "Double");
|
||||
}
|
||||
ut::expect(!cvars[1].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[1].value.get()) == 3.14f);
|
||||
|
||||
ut::expect(cvars[2].var.name == "u");
|
||||
if(cvars[2].var.type)
|
||||
{
|
||||
ut::expect(*cvars[2].var.type == "Integer");
|
||||
}
|
||||
ut::expect(!cvars[2].var.construct);
|
||||
ut::expect(boost::get<vb6_ast::integer_dec>(cvars[2].value.get()).val == -1);
|
||||
};
|
||||
|
||||
"const_var_declaration2"_test = []
|
||||
{
|
||||
vb6_ast::const_var_stat cvars;
|
||||
test_grammar("Private Const PI As Double = 3.1415\r\n",
|
||||
vb6_grammar::const_var_declaration, cvars);
|
||||
|
||||
ut::expect((cvars.size() == 1) >> ut::fatal);
|
||||
|
||||
cout << "size: " << cvars.size() << "\n";
|
||||
|
||||
ut::expect(cvars[0].var.name == "PI");
|
||||
if(cvars[0].var.type)
|
||||
{
|
||||
ut::expect(*cvars[0].var.type == "Double");
|
||||
}
|
||||
ut::expect(!cvars[0].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[0].value.get()) == 3.1415f);
|
||||
};
|
||||
|
||||
"param_decl"_test = []
|
||||
{
|
||||
vb6_ast::func_param fp;
|
||||
test_grammar("Optional ByVal name As String = \"pippo\"", vb6_grammar::param_decl, fp);
|
||||
|
||||
ut::expect(fp.isoptional);
|
||||
ut::expect(fp.qualifier.has_value());
|
||||
if(fp.qualifier)
|
||||
{
|
||||
ut::expect(*fp.qualifier == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(fp.var.name == "name");
|
||||
ut::expect(!fp.var.construct);
|
||||
ut::expect(fp.var.type.has_value());
|
||||
if(fp.var.type)
|
||||
{
|
||||
ut::expect(*fp.var.type == "String");
|
||||
}
|
||||
ut::expect(fp.defvalue.has_value());
|
||||
if(fp.defvalue)
|
||||
{
|
||||
ut::expect(boost::get<vb6_ast::quoted_string>(fp.defvalue.get()) == "pippo");
|
||||
}
|
||||
};
|
||||
|
||||
"param_list_decl"_test = []
|
||||
{
|
||||
vector<vb6_ast::func_param> fps;
|
||||
test_grammar("ByVal name As String, ByRef val As Integer",
|
||||
-(vb6_grammar::param_decl % ','), fps);
|
||||
|
||||
cout << "size: " << fps.size() << "\n";
|
||||
|
||||
ut::expect((fps.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(!fps[0].isoptional);
|
||||
ut::expect(fps[0].qualifier.has_value());
|
||||
if(fps[0].qualifier)
|
||||
{
|
||||
ut::expect(*fps[0].qualifier == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(fps[0].var.name == "name");
|
||||
ut::expect(!fps[0].var.construct);
|
||||
ut::expect(fps[0].var.type.has_value());
|
||||
if(fps[0].var.type)
|
||||
{
|
||||
ut::expect(*fps[0].var.type == "String");
|
||||
}
|
||||
ut::expect(!fps[0].defvalue);
|
||||
|
||||
ut::expect(!fps[1].isoptional);
|
||||
ut::expect(fps[1].qualifier.has_value());
|
||||
if(fps[1].qualifier)
|
||||
{
|
||||
ut::expect(*fps[1].qualifier == vb6_ast::param_qualifier::byref);
|
||||
}
|
||||
ut::expect(fps[1].var.name == "val");
|
||||
ut::expect(!fps[1].var.construct);
|
||||
ut::expect(fps[1].var.type.has_value());
|
||||
if(fps[1].var.type)
|
||||
{
|
||||
ut::expect(*fps[1].var.type == "Integer");
|
||||
}
|
||||
ut::expect(!fps[1].defvalue);
|
||||
};
|
||||
|
||||
"event_declaration"_test = []
|
||||
{
|
||||
vb6_ast::eventHead event_decl;
|
||||
test_grammar("Public Event OnChange(ByVal Text As String)\r\n",
|
||||
vb6_grammar::eventHead, event_decl);
|
||||
|
||||
ut::expect(event_decl.at == vb6_ast::access_type::public_);
|
||||
ut::expect(event_decl.name == "OnChange");
|
||||
ut::expect(event_decl.params.size() == 1);
|
||||
};
|
||||
|
||||
"function_head"_test = []
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
test_grammar(
|
||||
"Private Function OneFunc(ByVal name As String, ByRef val As Integer) As Integer\r\n",
|
||||
vb6_grammar::functionHead, fh);
|
||||
|
||||
ut::expect(fh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(fh.name == "OneFunc");
|
||||
ut::expect(fh.params.size() == 2);
|
||||
ut::expect(fh.return_type.has_value());
|
||||
ut::expect(*fh.return_type == "Integer");
|
||||
};
|
||||
|
||||
"function_head_no_params"_test = []
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
test_grammar(
|
||||
"Private Function NoParamFunc() As Object\r\n", vb6_grammar::functionHead, fh);
|
||||
|
||||
ut::expect(fh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(fh.name == "NoParamFunc");
|
||||
ut::expect(fh.params.empty());
|
||||
ut::expect((fh.return_type.has_value()) >> ut::fatal);
|
||||
ut::expect(*fh.return_type == "Object");
|
||||
};
|
||||
|
||||
"subroutine_head"_test = []
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, ByVal valid As Boolean)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect(sh.params.size() == 2);
|
||||
};
|
||||
|
||||
"subroutine_head2"_test = []
|
||||
{
|
||||
auto str = "Private Sub my_sub(ByRef str As String, ByVal valid As Boolean, Optional ByVal flag As Boolean = True)\r\n"s;
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(str, vb6_grammar::subHead, sh);
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect(sh.params.size() == 3);
|
||||
};
|
||||
|
||||
"subroutine_head_with_optional_params"_test = []
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, Optional ByVal valid As Boolean = false)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect((sh.params.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(sh.params[0].qualifier.has_value());
|
||||
if (sh.params[0].qualifier)
|
||||
ut::expect(sh.params[0].qualifier.get() == vb6_ast::param_qualifier::byref);
|
||||
ut::expect(sh.params[0].var.name == "str");
|
||||
if(sh.params[0].var.type)
|
||||
{
|
||||
ut::expect(*sh.params[0].var.type == "String");
|
||||
}
|
||||
ut::expect(!sh.params[0].var.construct);
|
||||
ut::expect(!sh.params[0].isoptional);
|
||||
ut::expect(!sh.params[0].defvalue);
|
||||
|
||||
ut::expect(sh.params[1].qualifier.has_value());
|
||||
if(sh.params[1].qualifier)
|
||||
{
|
||||
ut::expect(sh.params[1].qualifier.get() == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(sh.params[1].var.name == "valid");
|
||||
if(sh.params[1].var.type)
|
||||
{
|
||||
ut::expect(*sh.params[1].var.type == "Boolean");
|
||||
}
|
||||
ut::expect(!sh.params[1].var.construct);
|
||||
ut::expect(sh.params[1].isoptional);
|
||||
ut::expect(sh.params[1].defvalue.has_value());
|
||||
if(sh.params[0].defvalue)
|
||||
{
|
||||
ut::expect(boost::get<bool>(*sh.params[0].defvalue) == false);
|
||||
}
|
||||
};
|
||||
|
||||
"property_let_head"_test = []
|
||||
{
|
||||
auto str = "Public Property Let Width(ByVal w As Integer)\r\n"s;
|
||||
vb6_ast::propertyLetHead ast;
|
||||
test_grammar(str, vb6_grammar::property_letHead, ast);
|
||||
|
||||
ut::expect(ast.at == vb6_ast::access_type::public_);
|
||||
ut::expect(ast.name == "Width");
|
||||
ut::expect(ast.params.size() == 1);
|
||||
};
|
||||
|
||||
"property_get_head"_test = []
|
||||
{
|
||||
auto str = "Public Property Get Width() As Integer\r\n"s;
|
||||
vb6_ast::propertyGetHead ast;
|
||||
test_grammar(str, vb6_grammar::property_getHead, ast);
|
||||
|
||||
ut::expect(ast.at == vb6_ast::access_type::public_);
|
||||
ut::expect(ast.name == "Width");
|
||||
ut::expect(ast.params.size() == 0);
|
||||
ut::expect(ast.return_type >> fatal);
|
||||
ut::expect(*ast.return_type == "Integer");
|
||||
};
|
||||
|
||||
"dll_subroutine_declaration"_test = []
|
||||
{
|
||||
vb6_ast::externalSub extsub;
|
||||
auto str = "Private Declare Sub BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single)\r\n"s;
|
||||
test_grammar(str, vb6_grammar::external_sub_decl, extsub);
|
||||
|
||||
ut::expect(extsub.at == vb6_ast::access_type::private_);
|
||||
ut::expect(extsub.name == "BeepVB");
|
||||
ut::expect(extsub.alias == "Beep");
|
||||
ut::expect(extsub.params.size() == 2);
|
||||
ut::expect(extsub.lib == "kernel32.dll");
|
||||
};
|
||||
|
||||
"dll_function_declaration"_test = []
|
||||
{
|
||||
vb6_ast::externalFunction extfunc;
|
||||
auto str = "Private Declare Function BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single) As Long\r\n"s;
|
||||
test_grammar(str, vb6_grammar::external_function_decl, extfunc);
|
||||
|
||||
ut::expect(extfunc.at == vb6_ast::access_type::private_);
|
||||
ut::expect(extfunc.name == "BeepVB");
|
||||
ut::expect(extfunc.return_type.has_value());
|
||||
if(extfunc.return_type)
|
||||
{
|
||||
ut::expect(*extfunc.return_type == "Long");
|
||||
}
|
||||
ut::expect(extfunc.alias == "Beep");
|
||||
ut::expect(extfunc.params.size() == 2);
|
||||
ut::expect(extfunc.lib == "kernel32.dll");
|
||||
};
|
||||
|
||||
"identifier_context"_test = []
|
||||
{
|
||||
vb6_ast::identifier_context ctx;
|
||||
test_grammar("var1.func().pnt1.", vb6_grammar::identifier_context, ctx);
|
||||
|
||||
ut::expect(!ctx.leading_dot);
|
||||
ut::expect((ctx.elements.size() == 3) >> ut::fatal);
|
||||
ut::expect(boost::get<string>(ctx.elements[0].get()) == "var1");
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(ctx.elements[1].get()).get();
|
||||
ut::expect(tmp.func_name == "func");
|
||||
ut::expect(tmp.params.empty());
|
||||
ut::expect(boost::get<string>(ctx.elements[2].get()) == "pnt1");
|
||||
};
|
||||
|
||||
"decorated_variable"_test = []
|
||||
{
|
||||
vb6_ast::decorated_variable dec_var;
|
||||
test_grammar("var1.func().pnt1.X", vb6_grammar::decorated_variable, dec_var);
|
||||
|
||||
ut::expect(!dec_var.ctx.leading_dot);
|
||||
ut::expect((dec_var.ctx.elements.size() == 3) >> ut::fatal);
|
||||
ut::expect(boost::get<string>(dec_var.ctx.elements[0].get()) == "var1");
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(dec_var.ctx.elements[1].get()).get();
|
||||
ut::expect(tmp.func_name == "func");
|
||||
ut::expect(tmp.params.empty());
|
||||
ut::expect(boost::get<string>(dec_var.ctx.elements[2].get()) == "pnt1");
|
||||
ut::expect(dec_var.var == "X");
|
||||
};
|
||||
|
||||
"attribute_block"_test = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::module_attributes attrs;
|
||||
auto str = "Attribute ModuleName = \"MyForm\"\r\n"
|
||||
"Attribute ProgID = \"00-00-00-00\"\r\n"s;
|
||||
test_grammar(str, *vb6_grammar::attributeDef, attrs);
|
||||
|
||||
ut::expect(attrs.size() == 2);
|
||||
|
||||
auto it1 = attrs.find("ModuleName");
|
||||
ut::expect(it1 != attrs.cend());
|
||||
if(it1 != attrs.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto it2 = attrs.find("ProgID");
|
||||
ut::expect(it2 != attrs.cend());
|
||||
if(it2 != attrs.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
};
|
||||
|
||||
"attributes"_test = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::module_attributes ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
)vb"s;
|
||||
//test_grammar(str, vb6_grammar::preamble, ast);
|
||||
test_grammar(str, *vb6_grammar::attributeDef, ast);
|
||||
|
||||
ut::expect(ast.size() == 2);
|
||||
|
||||
auto const it1 = ast.find("ModuleName");
|
||||
ut::expect(it1 != ast.cend());
|
||||
if(it1 != ast.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto const it2 = ast.find("ProgID");
|
||||
ut::expect(it2 != ast.cend());
|
||||
if(it2 != ast.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
};
|
||||
|
||||
"options"_test = []
|
||||
{
|
||||
vector<vb6_ast::module_option> ast;
|
||||
auto str = R"vb(Option Explicit
|
||||
Option Base 0
|
||||
)vb"s;
|
||||
test_grammar(str, *vb6_grammar::option_item, ast);
|
||||
|
||||
ut::expect((ast.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(ast[0] == vb6_ast::module_option::explicit_);
|
||||
ut::expect(ast[1] == vb6_ast::module_option::base_0);
|
||||
};
|
||||
|
||||
#if 0
|
||||
"declaration_block"_test = []
|
||||
{
|
||||
auto const declarations
|
||||
= boost::spirit::x3::rule<class _, vector<vb6_ast::STRICT_MODULE_STRUCTURE::declaration>>("declaration_block")
|
||||
= *vb6_grammar::STRICT_MODULE_STRUCTURE::declaration;
|
||||
|
||||
vector<vb6_ast::STRICT_MODULE_STRUCTURE::declaration> decls;
|
||||
auto str = "Const e As Double = 2.8, pi As Double = 3.14, u As Integer = -1\r\n"
|
||||
"Global g_logger As Long, v1, XRes As Object, ptr As MyRec, g_active As Boolean\r\n"
|
||||
"Private Declare Sub PFoo Lib \"mylib.dll\" Alias \"PFoo\" (ByVal val As Long)\r\n"
|
||||
"Enum MyEnum1\r\n c1 = 0\r\n c2 = 1\r\nEnd Enum\r\n"
|
||||
"Public Type MyRecord1\r\n v1 As String\r\n v2 As Long\r\nEnd Type\r\n"s;
|
||||
test_grammar(str, declarations, decls);
|
||||
|
||||
ut::expect((decls.size() == 5) >> ut::fatal);
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(decls[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(decls[1].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::externalSub>(decls[2].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(decls[3].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::record>(decls[4].get();})));
|
||||
};
|
||||
|
||||
"bas_unit_STRICT_MODULE_STRUCTURE"_test = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::vb_module ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
Option Explicit
|
||||
Option Base 0
|
||||
|
||||
' declarations
|
||||
Const u As Integer = 1234
|
||||
Global g_logger As Long
|
||||
Enum MyEnum1
|
||||
c1 = 0
|
||||
c2 = 1
|
||||
End Enum
|
||||
Sub my_sub(ByRef str As String)
|
||||
End Sub
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
test_grammar(str, vb6_grammar::STRICT_MODULE_STRUCTURE::basModDef, ast);
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
|
||||
ut::expect(ast.attrs.size() == 2);
|
||||
|
||||
auto const it1 = ast.attrs.find("ModuleName");
|
||||
EXPECT_NE(it1, ast.attrs.cend());
|
||||
if(it1 != ast.attrs.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto const it2 = ast.attrs.find("ProgID");
|
||||
EXPECT_NE(it2, ast.attrs.cend());
|
||||
if(it2 != ast.attrs.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
|
||||
ut::expect(ast.opts.items.size() == 4);
|
||||
if(ast.opts.items.size() == 4)
|
||||
{
|
||||
#if 0
|
||||
ut::expect(ast.opts.items[0] == vb6_ast::module_option::explicit_);
|
||||
ut::expect(ast.opts.items[1] == vb6_ast::module_option::base_0);
|
||||
#else
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast.opts.items[0].get()) == vb6_ast::module_option::explicit_);
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast.opts.items[1].get()) == vb6_ast::module_option::base_0);
|
||||
#endif
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast.opts.items[2].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::lonely_comment>(ast.opts.items[3].get();})));
|
||||
}
|
||||
|
||||
ut::expect(ast.declarations.size() == 3);
|
||||
if(ast.declarations.size() == 3)
|
||||
{
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(ast.declarations[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(ast.declarations[1].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(ast.declarations[2].get();})));
|
||||
}
|
||||
|
||||
ut::expect(ast.functions.size() == 2);
|
||||
if(ast.functions.size() == 2)
|
||||
{
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::subDef>(ast.functions[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::functionDef>(ast.functions[1].get();})));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
"bas_unit"_test = []
|
||||
{
|
||||
vb6_ast::vb_module ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
Option Explicit
|
||||
Option Base 0
|
||||
|
||||
' declarations
|
||||
Const u As Integer = 1234
|
||||
Global g_logger As Long
|
||||
Enum MyEnum1
|
||||
c1 = 0
|
||||
c2 = 1
|
||||
End Enum
|
||||
Sub my_sub(ByRef str As String)
|
||||
End Sub
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
test_grammar(str, vb6_grammar::basModDef, ast);
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
|
||||
ut::expect(ut::eq(ast.size(), 11) >> ut::fatal);
|
||||
|
||||
ut::expect(boost::get<vb6_ast::module_attribute>(ast[0].get()).first == "ModuleName");
|
||||
ut::expect(boost::get<vb6_ast::module_attribute>(ast[1].get()).first == "ProgID");
|
||||
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast[2].get()) == vb6_ast::module_option::explicit_);
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast[3].get()) == vb6_ast::module_option::base_0);
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast[4].get());}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::lonely_comment>(ast[5].get());}));
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(boost::get<vb6_ast::declaration>(ast[6].get()));}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(boost::get<vb6_ast::declaration>(ast[7].get()));}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(boost::get<vb6_ast::declaration>(ast[8].get()));}));
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::subDef>(ast[9].get());}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::functionDef>(ast[10].get());}));
|
||||
};
|
||||
|
||||
"trailing_comment"_test = []
|
||||
{
|
||||
auto str = "Global g_var As Long ' how can we catch a trailing comment?\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
|
||||
ut::expect(vars.at == vb6_ast::access_type::global);
|
||||
ut::expect(!vars.with_events);
|
||||
ut::expect((vars.vars.size() == 1) >> ut::fatal);
|
||||
|
||||
ut::expect(vars.vars[0].name == "g_var");
|
||||
ut::expect(!vars.vars[0].construct);
|
||||
ut::expect(vars.vars[0].type.has_value());
|
||||
if(vars.vars[0].type)
|
||||
{
|
||||
ut::expect(*vars.vars[0].type == "Long");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
bool res = boost::ut::cfg<boost::ut::override>.run();
|
||||
return res ? 0 : -1;
|
||||
}
|
||||
64
test/CMakeLists.txt
Normal file
64
test/CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS system)
|
||||
find_package(doctest CONFIG REQUIRED)
|
||||
find_package(GTest CONFIG REQUIRED)
|
||||
find_package(ut CONFIG REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_executable(vb6_parser.ut
|
||||
vb6_parser.ut.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser.ut
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
Boost::system
|
||||
Boost::ut
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
# --------------------------------
|
||||
|
||||
add_executable(vb6_parser.doctest
|
||||
vb6_parser.doctest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser.doctest
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
Boost::system
|
||||
doctest::doctest
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
# --------------------------------
|
||||
|
||||
add_executable(vb6_parser.gtest
|
||||
test_gosub.cpp
|
||||
vb6_parser_statements.gtest.cpp
|
||||
vb6_parser.gtest.cpp
|
||||
vb6_parser_test_main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(vb6_parser.gtest
|
||||
PRIVATE
|
||||
vb6_parser_lib
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main
|
||||
Boost::system
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
# --------------------------------
|
||||
|
||||
add_test(NAME vb6_parser.ut COMMAND vb6_parser.ut)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(vb6_parser.gtest)
|
||||
|
||||
#add_test(NAME vb6_parser.doctest COMMAND vb6_parser.doctest)
|
||||
include(doctest)
|
||||
doctest_discover_tests(vb6_parser.doctest)
|
||||
@@ -10,14 +10,13 @@
|
||||
#include "vb6_config.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/ut.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
template <class ruleType, class attrType>
|
||||
void test_grammar(std::string_view fragment, ruleType rule, attrType& attr, bool expected = true)
|
||||
std::pair<bool, std::string_view> test_grammar(std::string_view fragment, ruleType rule, attrType& attr)
|
||||
{
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
@@ -36,10 +35,7 @@ void test_grammar(std::string_view fragment, ruleType rule, attrType& attr, bool
|
||||
rule
|
||||
];
|
||||
|
||||
using namespace boost::ut;
|
||||
bool res = x3::phrase_parse(it1, it2, parser, vb6_grammar::skip, attr);
|
||||
|
||||
expect((x3::phrase_parse(it1, it2, parser, vb6_grammar::skip, attr) == expected) >> fatal)
|
||||
<< "stopped at: " << std::string(it1, it2);
|
||||
|
||||
expect(it1 == it2);
|
||||
return std::make_pair(res, std::string_view(it1, it2));
|
||||
}
|
||||
1001
test/vb6_parser.doctest.cpp
Normal file
1001
test/vb6_parser.doctest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
|
||||
//#define BOOST_SPIRIT_X3_DEBUG
|
||||
|
||||
#include "test_grammar_helper_gtest.hpp"
|
||||
#include "test_grammar_helper_ut.hpp"
|
||||
#include "vb6_parser.hpp"
|
||||
#include "vb6_ast_printer.hpp"
|
||||
|
||||
@@ -23,9 +23,11 @@ namespace x3 = boost::spirit::x3;
|
||||
GTEST_TEST(vb6_parser_simple, lonely_comment)
|
||||
{
|
||||
vector<vb6_ast::lonely_comment> ast;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
"' This is comment line 1\r\n' Comment line 2\r\n",
|
||||
*vb6_grammar::lonely_comment, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(ast.size(), 2);
|
||||
|
||||
@@ -43,7 +45,9 @@ GTEST_TEST(vb6_parser_simple, empty_lines)
|
||||
auto str = "' comment1\r\n"
|
||||
"\r\n"
|
||||
"' comment2\r\n";
|
||||
test_grammar(str, G, ast);
|
||||
auto [res, sv] = test_grammar(str, G, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(ast.size(), 3);
|
||||
|
||||
@@ -55,30 +59,49 @@ GTEST_TEST(vb6_parser_simple, empty_lines)
|
||||
GTEST_TEST(vb6_parser_simple, quoted_string)
|
||||
{
|
||||
string str;
|
||||
test_grammar("\"Quoted string.\"", vb6_grammar::quoted_string, str);
|
||||
auto [res, sv] = test_grammar("\"Quoted string.\"", vb6_grammar::quoted_string, str);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(str, "Quoted string.");
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, basic_identifier)
|
||||
{
|
||||
string id;
|
||||
test_grammar("iden_tifier", vb6_grammar::basic_identifier, id);
|
||||
auto [res, sv] = test_grammar("iden_tifier", vb6_grammar::basic_identifier, id);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(id, "iden_tifier");
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, var_identifier)
|
||||
{
|
||||
string var;
|
||||
test_grammar("g_logger", vb6_grammar::var_identifier, var);
|
||||
EXPECT_EQ(var, "g_logger");
|
||||
{
|
||||
string var;
|
||||
auto [res, sv] = test_grammar("g_logger", vb6_grammar::var_identifier, var);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
var.clear();
|
||||
test_grammar("forth ", vb6_grammar::sub_identifier, var);
|
||||
EXPECT_EQ(var, "forth");
|
||||
EXPECT_EQ(var, "g_logger");
|
||||
}
|
||||
{
|
||||
string var;
|
||||
auto [res, sv] = test_grammar("forth ", vb6_grammar::sub_identifier, var);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
var.clear();
|
||||
test_grammar("subroutine ", vb6_grammar::sub_identifier, var);
|
||||
EXPECT_EQ(var, "subroutine");
|
||||
EXPECT_EQ(var, "forth");
|
||||
}
|
||||
{
|
||||
string var;
|
||||
auto [res, sv] = test_grammar("subroutine ", vb6_grammar::sub_identifier, var);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(var, "subroutine");
|
||||
}
|
||||
|
||||
/*
|
||||
string code = "sub ";
|
||||
@@ -93,14 +116,20 @@ GTEST_TEST(vb6_parser_simple, var_identifier)
|
||||
GTEST_TEST(vb6_parser_simple, type_identifier)
|
||||
{
|
||||
string type;
|
||||
test_grammar("Long", vb6_grammar::type_identifier, type);
|
||||
auto [res, sv] = test_grammar("Long", vb6_grammar::type_identifier, type);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(type, "Long");
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, complex_type_identifier)
|
||||
{
|
||||
string type;
|
||||
test_grammar("VB.Form", vb6_grammar::complex_type_identifier, type);
|
||||
auto [res, sv] = test_grammar("VB.Form", vb6_grammar::complex_type_identifier, type);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(type, "VB.Form");
|
||||
}
|
||||
|
||||
@@ -109,17 +138,30 @@ GTEST_TEST(vb6_parser_simple, const_expression_non_numeric)
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "\"una stringa\""s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::quoted_string>(ast.get()), "una stringa");
|
||||
{
|
||||
str = "\"una stringa\""s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "True"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<bool>(ast.get()), true);
|
||||
EXPECT_EQ(boost::get<vb6_ast::quoted_string>(ast.get()), "una stringa");
|
||||
}
|
||||
{
|
||||
str = "True"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "Nothing"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_NO_THROW(boost::get<vb6_ast::nothing>(ast.get()));
|
||||
EXPECT_EQ(boost::get<bool>(ast.get()), true);
|
||||
}
|
||||
{
|
||||
str = "Nothing"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_NO_THROW(boost::get<vb6_ast::nothing>(ast.get()));
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, const_expression_integers)
|
||||
@@ -127,25 +169,46 @@ GTEST_TEST(vb6_parser_simple, const_expression_integers)
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "1234%"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::integer_dec>(ast.get()).val, 1234);
|
||||
{
|
||||
str = "1234%"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "1234&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_dec>(ast.get()).val, 1234);
|
||||
EXPECT_EQ(boost::get<vb6_ast::integer_dec>(ast.get()).val, 1234);
|
||||
}
|
||||
{
|
||||
str = "1234&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "&Hcafedead&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_hex>(ast.get()).val, 0xcafedead);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_dec>(ast.get()).val, 1234);
|
||||
}
|
||||
{
|
||||
str = "&Hcafedead&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "&01234&"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_oct>(ast.get()).val, 01234);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_hex>(ast.get()).val, 0xcafedead);
|
||||
}
|
||||
{
|
||||
str = "&01234&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "1234"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<vb6_ast::integer_dec>(ast.get()).val, 1234);
|
||||
EXPECT_EQ(boost::get<vb6_ast::long_oct>(ast.get()).val, 01234);
|
||||
}
|
||||
{
|
||||
str = "1234"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(boost::get<vb6_ast::integer_dec>(ast.get()).val, 1234);
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, const_expression_floats)
|
||||
@@ -153,55 +216,82 @@ GTEST_TEST(vb6_parser_simple, const_expression_floats)
|
||||
vb6_ast::const_expr ast;
|
||||
string str;
|
||||
|
||||
str = "1234!"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<float>(ast.get()), 1234.0f);
|
||||
{
|
||||
str = "1234!"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "1234#"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<double>(ast.get()), 1234.0);
|
||||
EXPECT_EQ(boost::get<float>(ast.get()), 1234.0f);
|
||||
}
|
||||
{
|
||||
str = "1234#"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
str = "2.8"s;
|
||||
test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
EXPECT_EQ(boost::get<float>(ast.get()), 2.8f);
|
||||
EXPECT_EQ(boost::get<double>(ast.get()), 1234.0);
|
||||
}
|
||||
{
|
||||
str = "2.8"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(boost::get<float>(ast.get()), 2.8f);
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, sample_expression)
|
||||
{
|
||||
vb6_ast::expression ast;
|
||||
test_grammar("foo1(foo2(3, M.x_coord), True)", vb6_grammar::expression, ast);
|
||||
auto [res, sv] = test_grammar("foo1(foo2(3, M.x_coord), True)", vb6_grammar::expression, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(ast.get().type(), typeid(x3::forward_ast<vb6_ast::func_call>));
|
||||
EXPECT_EQ(boost::get<x3::forward_ast<vb6_ast::func_call>>(ast.get()).get().func_name, "foo1");
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_simple, single_var_declaration)
|
||||
{
|
||||
vb6_ast::variable P1;
|
||||
test_grammar("g_logger As Long", vb6_grammar::single_var_declaration, P1);
|
||||
EXPECT_EQ(P1.name, "g_logger");
|
||||
EXPECT_FALSE(P1.construct);
|
||||
EXPECT_TRUE(P1.type);
|
||||
if(P1.type)
|
||||
{
|
||||
EXPECT_EQ(*P1.type, "Long");
|
||||
}
|
||||
vb6_ast::variable P1;
|
||||
auto [res, sv] = test_grammar("g_logger As Long", vb6_grammar::single_var_declaration, P1);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
vb6_ast::variable P2;
|
||||
test_grammar("name As New String", vb6_grammar::single_var_declaration, P2);
|
||||
EXPECT_EQ(P2.name, "name");
|
||||
EXPECT_TRUE(P2.construct);
|
||||
EXPECT_TRUE(P2.type);
|
||||
if(P2.type)
|
||||
EXPECT_EQ(P1.name, "g_logger");
|
||||
EXPECT_FALSE(P1.construct);
|
||||
EXPECT_TRUE(P1.type);
|
||||
if(P1.type)
|
||||
{
|
||||
EXPECT_EQ(*P1.type, "Long");
|
||||
}
|
||||
}
|
||||
{
|
||||
EXPECT_EQ(*P2.type, "String");
|
||||
vb6_ast::variable P2;
|
||||
auto [res, sv] = test_grammar("name As New String", vb6_grammar::single_var_declaration, P2);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(P2.name, "name");
|
||||
EXPECT_TRUE(P2.construct);
|
||||
EXPECT_TRUE(P2.type);
|
||||
if(P2.type)
|
||||
{
|
||||
EXPECT_EQ(*P2.type, "String");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_tests, record_declaration)
|
||||
{
|
||||
vb6_ast::record rec;
|
||||
test_grammar("Type PatRecord\r\n name As String\r\n age As Integer\r\nEnd Type\r\n",
|
||||
auto [res, sv] = test_grammar("Type PatRecord\r\n name As String\r\n age As Integer\r\nEnd Type\r\n",
|
||||
vb6_grammar::record_declaration, rec);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(rec.name, "PatRecord");
|
||||
EXPECT_EQ(rec.at, vb6_ast::access_type::na);
|
||||
@@ -227,8 +317,10 @@ GTEST_TEST(vb6_parser_tests, record_declaration)
|
||||
GTEST_TEST(vb6_parser_tests, enum_declaration)
|
||||
{
|
||||
vb6_ast::vb_enum enum1;
|
||||
test_grammar("Enum PatTypes\r\n inpatient\r\n outpatient\r\nEnd Enum\r\n",
|
||||
auto [res, sv] = test_grammar("Enum PatTypes\r\n inpatient\r\n outpatient\r\nEnd Enum\r\n",
|
||||
vb6_grammar::enum_declaration, enum1);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(enum1.name, "PatTypes");
|
||||
EXPECT_EQ(enum1.at, vb6_ast::access_type::na);
|
||||
@@ -245,7 +337,9 @@ GTEST_TEST(vb6_parser_tests, global_var_declaration)
|
||||
{
|
||||
auto str = "Global g_logger As Long, v1, XRes As New Object, ptr As Module.MyRec, g_active As Boolean\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(vars.at, vb6_ast::access_type::global);
|
||||
EXPECT_FALSE(vars.with_events);
|
||||
@@ -292,7 +386,9 @@ GTEST_TEST(vb6_parser_tests, const_var_declaration1)
|
||||
{
|
||||
auto cstr = "Const e As Single = 2.8, pi As Double = 3.14, u As Integer = -1\r\n"s;
|
||||
vb6_ast::const_var_stat cvars;
|
||||
test_grammar(cstr, vb6_grammar::const_var_declaration, cvars);
|
||||
auto [res, sv] = test_grammar(cstr, vb6_grammar::const_var_declaration, cvars);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(cvars.size(), 3);
|
||||
|
||||
@@ -324,8 +420,10 @@ GTEST_TEST(vb6_parser_tests, const_var_declaration1)
|
||||
GTEST_TEST(vb6_parser_tests, const_var_declaration2)
|
||||
{
|
||||
vb6_ast::const_var_stat cvars;
|
||||
test_grammar("Private Const PI As Double = 3.1415\r\n",
|
||||
auto [res, sv] = test_grammar("Private Const PI As Double = 3.1415\r\n",
|
||||
vb6_grammar::const_var_declaration, cvars);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(cvars.size(), 1);
|
||||
|
||||
@@ -341,7 +439,9 @@ GTEST_TEST(vb6_parser_tests, const_var_declaration2)
|
||||
GTEST_TEST(vb6_parser_tests, param_decl)
|
||||
{
|
||||
vb6_ast::func_param fp;
|
||||
test_grammar("Optional ByVal name As String = \"pippo\"", vb6_grammar::param_decl, fp);
|
||||
auto [res, sv] = test_grammar("Optional ByVal name As String = \"pippo\"", vb6_grammar::param_decl, fp);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_TRUE(fp.isoptional);
|
||||
EXPECT_TRUE(fp.qualifier);
|
||||
@@ -366,8 +466,10 @@ GTEST_TEST(vb6_parser_tests, param_decl)
|
||||
GTEST_TEST(vb6_parser_tests, param_list_decl)
|
||||
{
|
||||
vector<vb6_ast::func_param> fps;
|
||||
test_grammar("ByVal name As String, ByRef val As Integer",
|
||||
auto [res, sv] = test_grammar("ByVal name As String, ByRef val As Integer",
|
||||
-(vb6_grammar::param_decl % ','), fps);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(fps.size(), 2);
|
||||
|
||||
@@ -405,8 +507,10 @@ GTEST_TEST(vb6_parser_tests, param_list_decl)
|
||||
GTEST_TEST(vb6_parser_tests, event_declaration)
|
||||
{
|
||||
vb6_ast::eventHead event_decl;
|
||||
test_grammar("Public Event OnChange(ByVal Text As String)\r\n",
|
||||
auto [res, sv] = test_grammar("Public Event OnChange(ByVal Text As String)\r\n",
|
||||
vb6_grammar::eventHead, event_decl);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(event_decl.at, vb6_ast::access_type::public_);
|
||||
EXPECT_EQ(event_decl.name, "OnChange");
|
||||
@@ -416,9 +520,11 @@ GTEST_TEST(vb6_parser_tests, event_declaration)
|
||||
GTEST_TEST(vb6_parser_tests, function_head)
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Function OneFunc(ByVal name As String, ByRef val As Integer) As Integer\r\n",
|
||||
vb6_grammar::functionHead, fh);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(fh.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(fh.name, "OneFunc");
|
||||
@@ -430,8 +536,10 @@ GTEST_TEST(vb6_parser_tests, function_head)
|
||||
GTEST_TEST(vb6_parser_tests, function_head_no_params)
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Function NoParamFunc() As Object\r\n", vb6_grammar::functionHead, fh);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(fh.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(fh.name, "NoParamFunc");
|
||||
@@ -443,9 +551,11 @@ GTEST_TEST(vb6_parser_tests, function_head_no_params)
|
||||
GTEST_TEST(vb6_parser_tests, subroutine_head)
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, ByVal valid As Boolean)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(sh.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(sh.name, "my_sub");
|
||||
@@ -456,7 +566,9 @@ GTEST_TEST(vb6_parser_tests, subroutine_head2)
|
||||
{
|
||||
auto str = "Private Sub my_sub(ByRef str As String, ByVal valid As Boolean, Optional ByVal flag As Boolean = True)\r\n"s;
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(str, vb6_grammar::subHead, sh);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::subHead, sh);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(sh.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(sh.name, "my_sub");
|
||||
@@ -466,17 +578,21 @@ GTEST_TEST(vb6_parser_tests, subroutine_head2)
|
||||
GTEST_TEST(vb6_parser_tests, subroutine_head_with_optional_params)
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, Optional ByVal valid As Boolean = false)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(sh.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(sh.name, "my_sub");
|
||||
ASSERT_EQ(sh.params.size(), 2);
|
||||
|
||||
EXPECT_TRUE(sh.params[0].qualifier.has_value());
|
||||
if (sh.params[0].qualifier)
|
||||
if(sh.params[0].qualifier)
|
||||
{
|
||||
EXPECT_EQ(sh.params[0].qualifier.get(), vb6_ast::param_qualifier::byref);
|
||||
}
|
||||
EXPECT_EQ(sh.params[0].var.name, "str");
|
||||
if(sh.params[0].var.type)
|
||||
{
|
||||
@@ -509,7 +625,9 @@ GTEST_TEST(vb6_parser_tests, property_let_head)
|
||||
{
|
||||
auto str = "Public Property Let Width(ByVal w As Integer)\r\n"s;
|
||||
vb6_ast::propertyLetHead ast;
|
||||
test_grammar(str, vb6_grammar::property_letHead, ast);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::property_letHead, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(ast.at, vb6_ast::access_type::public_);
|
||||
EXPECT_EQ(ast.name, "Width");
|
||||
@@ -520,7 +638,9 @@ GTEST_TEST(vb6_parser_tests, property_get_head)
|
||||
{
|
||||
auto str = "Public Property Get Width() As Integer\r\n"s;
|
||||
vb6_ast::propertyGetHead ast;
|
||||
test_grammar(str, vb6_grammar::property_getHead, ast);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::property_getHead, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(ast.at, vb6_ast::access_type::public_);
|
||||
EXPECT_EQ(ast.name, "Width");
|
||||
@@ -533,7 +653,9 @@ GTEST_TEST(vb6_parser_tests, dll_subroutine_declaration)
|
||||
{
|
||||
vb6_ast::externalSub extsub;
|
||||
auto str = "Private Declare Sub BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single)\r\n"s;
|
||||
test_grammar(str, vb6_grammar::external_sub_decl, extsub);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::external_sub_decl, extsub);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(extsub.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(extsub.name, "BeepVB");
|
||||
@@ -546,7 +668,9 @@ GTEST_TEST(vb6_parser_tests, dll_function_declaration)
|
||||
{
|
||||
vb6_ast::externalFunction extfunc;
|
||||
auto str = "Private Declare Function BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single) As Long\r\n"s;
|
||||
test_grammar(str, vb6_grammar::external_function_decl, extfunc);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::external_function_decl, extfunc);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(extfunc.at, vb6_ast::access_type::private_);
|
||||
EXPECT_EQ(extfunc.name, "BeepVB");
|
||||
@@ -563,7 +687,9 @@ GTEST_TEST(vb6_parser_tests, dll_function_declaration)
|
||||
GTEST_TEST(vb6_parser_tests, identifier_context)
|
||||
{
|
||||
vb6_ast::identifier_context ctx;
|
||||
test_grammar("var1.func().pnt1.", vb6_grammar::identifier_context, ctx);
|
||||
auto [res, sv] = test_grammar("var1.func().pnt1.", vb6_grammar::identifier_context, ctx);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_FALSE(ctx.leading_dot);
|
||||
ASSERT_EQ(ctx.elements.size(), 3);
|
||||
@@ -577,7 +703,9 @@ GTEST_TEST(vb6_parser_tests, identifier_context)
|
||||
GTEST_TEST(vb6_parser_tests, decorated_variable)
|
||||
{
|
||||
vb6_ast::decorated_variable dec_var;
|
||||
test_grammar("var1.func().pnt1.X", vb6_grammar::decorated_variable, dec_var);
|
||||
auto [res, sv] = test_grammar("var1.func().pnt1.X", vb6_grammar::decorated_variable, dec_var);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_FALSE(dec_var.ctx.leading_dot);
|
||||
ASSERT_EQ(dec_var.ctx.elements.size(), 3);
|
||||
@@ -594,7 +722,9 @@ GTEST_TEST(vb6_parser_tests, attribute_block)
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::module_attributes attrs;
|
||||
auto str = "Attribute ModuleName = \"MyForm\"\r\n"
|
||||
"Attribute ProgID = \"00-00-00-00\"\r\n"s;
|
||||
test_grammar(str, *vb6_grammar::attributeDef, attrs);
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::attributeDef, attrs);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(attrs.size(), 2);
|
||||
|
||||
@@ -619,8 +749,10 @@ GTEST_TEST(vb6_parser_tests, attributes)
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
)vb"s;
|
||||
//test_grammar(str, vb6_grammar::preamble, ast);
|
||||
test_grammar(str, *vb6_grammar::attributeDef, ast);
|
||||
//auto [res, sv] = test_grammar(str, vb6_grammar::preamble, ast);
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::attributeDef, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(ast.size(), 2);
|
||||
|
||||
@@ -645,7 +777,9 @@ GTEST_TEST(vb6_parser_tests, options)
|
||||
auto str = R"vb(Option Explicit
|
||||
Option Base 0
|
||||
)vb"s;
|
||||
test_grammar(str, *vb6_grammar::option_item, ast);
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::option_item, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(ast.size(), 2);
|
||||
|
||||
@@ -666,7 +800,9 @@ GTEST_TEST(vb6_parser_tests, declaration_block)
|
||||
"Private Declare Sub PFoo Lib \"mylib.dll\" Alias \"PFoo\" (ByVal val As Long)\r\n"
|
||||
"Enum MyEnum1\r\n c1 = 0\r\n c2 = 1\r\nEnd Enum\r\n"
|
||||
"Public Type MyRecord1\r\n v1 As String\r\n v2 As Long\r\nEnd Type\r\n"s;
|
||||
test_grammar(str, declarations, decls);
|
||||
auto [res, sv] = test_grammar(str, declarations, decls);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(decls.size(), 5);
|
||||
|
||||
@@ -697,7 +833,9 @@ GTEST_TEST(vb6_parser_tests, bas_unit_STRICT_MODULE_STRUCTURE)
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
test_grammar(str, vb6_grammar::STRICT_MODULE_STRUCTURE::basModDef, ast);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::STRICT_MODULE_STRUCTURE::basModDef, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
@@ -769,7 +907,9 @@ GTEST_TEST(vb6_parser_tests, bas_unit)
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
test_grammar(str, vb6_grammar::basModDef, ast);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::basModDef, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
@@ -797,7 +937,9 @@ GTEST_TEST(vb6_parser_tests, trailing_comment)
|
||||
{
|
||||
auto str = "Global g_var As Long ' how can we catch a trailing comment?\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(vars.at, vb6_ast::access_type::global);
|
||||
EXPECT_FALSE(vars.with_events);
|
||||
996
test/vb6_parser.ut.cpp
Normal file
996
test/vb6_parser.ut.cpp
Normal file
@@ -0,0 +1,996 @@
|
||||
//: vb6_parser.ut.cpp
|
||||
|
||||
// vb6_parser
|
||||
// Copyright (c) 2022 Federico Aponte
|
||||
// This code is licensed under GNU Software License (see LICENSE.txt for details)
|
||||
|
||||
//#define BOOST_SPIRIT_X3_DEBUG
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
|
||||
#include "test_grammar_helper_ut.hpp"
|
||||
#include "vb6_parser.hpp"
|
||||
#include "vb6_ast_printer.hpp"
|
||||
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include <boost/ut.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
namespace ut = boost::ut;
|
||||
|
||||
using namespace std;
|
||||
// need for ut's user-defined literals and overloaded operators
|
||||
using namespace boost::ut;
|
||||
|
||||
void log_compiler_info(std::ostream& os)
|
||||
{
|
||||
// how to tell that AppleClang and not plain Clang has been used?
|
||||
// __APPLE_CC__ does not work as it's always defined
|
||||
#if defined(__clang__)
|
||||
os << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__<< '\n';
|
||||
#elif defined(__GNUC__)
|
||||
os << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__<< '\n';
|
||||
#elif defined(__MSC_VER)
|
||||
os << "Compiler: MSC " << __MSC_VER << '\n';
|
||||
#endif
|
||||
}
|
||||
|
||||
ut::suite<"vb6_parser_simple"> _ = []
|
||||
{
|
||||
ut::test("lonely_comment") = []
|
||||
{
|
||||
vector<vb6_ast::lonely_comment> ast;
|
||||
auto [res, sv] = test_grammar(
|
||||
"' This is comment line 1\r\n' Comment line 2\r\n",
|
||||
*vb6_grammar::lonely_comment, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
//cout << ast.size() << "\n";
|
||||
ut::expect(ut::eq(ast.size(), 2));
|
||||
|
||||
ut::expect(ast[0].content == " This is comment line 1");
|
||||
ut::expect(ast[1].content == " Comment line 2");
|
||||
};
|
||||
|
||||
ut::test("empty_lines") = []
|
||||
{
|
||||
vector<
|
||||
boost::variant<vb6_ast::empty_line, vb6_ast::lonely_comment>
|
||||
> ast;
|
||||
// critical to have lonely_comment first in the parsing rule
|
||||
auto const G = *(vb6_grammar::lonely_comment | vb6_grammar::empty_line);
|
||||
auto str = "' comment1\r\n"
|
||||
"\r\n"
|
||||
"' comment2\r\n";
|
||||
auto [res, sv] = test_grammar(str, G, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(ast.size() == 3);
|
||||
|
||||
ut::expect(boost::get<vb6_ast::lonely_comment>(ast[0]).content == " comment1");
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast[1]);}));
|
||||
ut::expect(boost::get<vb6_ast::lonely_comment>(ast[2]).content == " comment2");
|
||||
};
|
||||
|
||||
ut::test("quoted_string") = []
|
||||
{
|
||||
string str;
|
||||
auto [res, sv] = test_grammar("\"Quoted string.\"", vb6_grammar::quoted_string, str);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(str == "Quoted string.");
|
||||
};
|
||||
|
||||
ut::test("basic_identifier") = []
|
||||
{
|
||||
string id;
|
||||
auto [res, sv] = test_grammar("iden_tifier", vb6_grammar::basic_identifier, id);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(id == "iden_tifier");
|
||||
};
|
||||
|
||||
ut::test("var_identifier") = []
|
||||
{
|
||||
string var;
|
||||
|
||||
ut::test("1") = [&var]
|
||||
{
|
||||
auto [res, sv] = test_grammar("g_logger", vb6_grammar::var_identifier, var);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(var == "g_logger");
|
||||
};
|
||||
|
||||
ut::test("2") = [&var]
|
||||
{
|
||||
auto [res, sv] = test_grammar("forth ", vb6_grammar::sub_identifier, var);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(var == "forth");
|
||||
};
|
||||
|
||||
ut::test("3") = [&var]
|
||||
{
|
||||
auto [res, sv] = test_grammar("subroutine ", vb6_grammar::sub_identifier, var);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(var == "subroutine");
|
||||
};
|
||||
|
||||
/*
|
||||
string code = "sub ";
|
||||
string_view code_sv = code;
|
||||
auto it1 = cbegin(code_sv);
|
||||
auto const it2 = cend(code_sv);
|
||||
ut::expect(!boost::spirit::x3::phrase_parse(it1, it2, vb6_grammar::sub_identifier, vb6_grammar::skip, var));
|
||||
ut::expect(it1 == begin(code_sv));
|
||||
*/
|
||||
};
|
||||
|
||||
ut::test("type_identifier") = []
|
||||
{
|
||||
string type;
|
||||
auto [res, sv] = test_grammar("Long", vb6_grammar::type_identifier, type);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % type == "Long"s);
|
||||
};
|
||||
|
||||
ut::test("complex_type_identifier") = []
|
||||
{
|
||||
string type;
|
||||
auto [res, sv] = test_grammar("VB.Form", vb6_grammar::complex_type_identifier, type);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % type == "VB.Form"s);
|
||||
};
|
||||
|
||||
ut::test("const_expression_non_numeric") = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
|
||||
ut::test("1") = [&ast]
|
||||
{
|
||||
string str = "\"una stringa\""s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::quoted_string>(ast.get()) == "una stringa"s);
|
||||
};
|
||||
|
||||
ut::test("2") = [&ast]
|
||||
{
|
||||
string str = "True"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(boost::get<bool>(ast.get()));
|
||||
};
|
||||
|
||||
ut::test("3") = [&ast]
|
||||
{
|
||||
string str = "Nothing"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::nothing>(ast.get());}));
|
||||
};
|
||||
};
|
||||
|
||||
ut::test("const_expression_integers") = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
|
||||
ut::test("1") = [&ast]
|
||||
{
|
||||
string str = "1234%"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::integer_dec>(ast.get()).val == 1234);
|
||||
};
|
||||
|
||||
ut::test("2") = [&ast]
|
||||
{
|
||||
string str = "1234&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::long_dec>(ast.get()).val == 1234);
|
||||
};
|
||||
|
||||
ut::test("3") = [&ast]
|
||||
{
|
||||
string str = "&Hcafedead&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::long_hex>(ast.get()).val == 0xcafedead);
|
||||
};
|
||||
|
||||
ut::test("4") = [&ast]
|
||||
{
|
||||
string str = "&01234&"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::long_oct>(ast.get()).val == 01234);
|
||||
};
|
||||
|
||||
ut::test("5") = [&ast]
|
||||
{
|
||||
string str = "1234"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(that % boost::get<vb6_ast::integer_dec>(ast.get()).val == 1234);
|
||||
};
|
||||
};
|
||||
|
||||
ut::test("const_expression_floats") = []
|
||||
{
|
||||
vb6_ast::const_expr ast;
|
||||
|
||||
ut::test("1") = [&ast]
|
||||
{
|
||||
string str = "1234!"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(boost::get<float>(ast.get()) == 1234.0f);
|
||||
};
|
||||
|
||||
ut::test("2") = [&ast]
|
||||
{
|
||||
string str = "1234#"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(boost::get<double>(ast.get()) == 1234.0);
|
||||
};
|
||||
|
||||
ut::test("3") = [&ast]
|
||||
{
|
||||
string str = "2.8"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::const_expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(boost::get<float>(ast.get()) == 2.8f);
|
||||
};
|
||||
};
|
||||
|
||||
ut::test("sample_expression") = []
|
||||
{
|
||||
vb6_ast::expression ast;
|
||||
auto [res, sv] = test_grammar("foo1(foo2(3, M.x_coord), True)", vb6_grammar::expression, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(ast.get().type() == typeid(x3::forward_ast<vb6_ast::func_call>));
|
||||
ut::expect(boost::get<x3::forward_ast<vb6_ast::func_call>>(ast.get()).get().func_name == "foo1");
|
||||
};
|
||||
|
||||
ut::test("single_var_declaration") = []
|
||||
{
|
||||
ut::test("1") = []
|
||||
{
|
||||
vb6_ast::variable P1;
|
||||
auto [res, sv] = test_grammar("g_logger As Long", vb6_grammar::single_var_declaration, P1);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(P1.name == "g_logger");
|
||||
ut::expect(!P1.construct);
|
||||
ut::expect(P1.type.has_value());
|
||||
if(P1.type)
|
||||
{
|
||||
ut::expect(*P1.type == "Long");
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("2") = []
|
||||
{
|
||||
vb6_ast::variable P2;
|
||||
auto [res, sv] = test_grammar("name As New String", vb6_grammar::single_var_declaration, P2);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
ut::expect(P2.name == "name");
|
||||
ut::expect(P2.construct);
|
||||
ut::expect(P2.type.has_value());
|
||||
if(P2.type)
|
||||
{
|
||||
ut::expect(*P2.type == "String");
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ut::suite<"vb6_parser_tests"> __ = []
|
||||
{
|
||||
ut::test("record_declaration") = []
|
||||
{
|
||||
vb6_ast::record rec;
|
||||
auto [res, sv] = test_grammar("Type PatRecord\r\n name As String\r\n age As Integer\r\nEnd Type\r\n",
|
||||
vb6_grammar::record_declaration, rec);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(rec.name == "PatRecord");
|
||||
ut::expect(rec.at == vb6_ast::access_type::na);
|
||||
ut::expect(rec.members.size() == 2);
|
||||
|
||||
ut::expect(rec.members[0].name == "name");
|
||||
ut::expect(rec.members[0].type.has_value());
|
||||
if(rec.members[0].type)
|
||||
{
|
||||
ut::expect(*rec.members[0].type == "String");
|
||||
}
|
||||
ut::expect(!rec.members[0].construct);
|
||||
|
||||
ut::expect(rec.members[1].name == "age");
|
||||
ut::expect(rec.members[1].type.has_value());
|
||||
if(rec.members[1].type)
|
||||
{
|
||||
ut::expect(*rec.members[1].type == "Integer");
|
||||
}
|
||||
ut::expect(!rec.members[1].construct);
|
||||
};
|
||||
|
||||
ut::test("enum_declaration") = []
|
||||
{
|
||||
vb6_ast::vb_enum enum1;
|
||||
auto [res, sv] = test_grammar("Enum PatTypes\r\n inpatient\r\n outpatient\r\nEnd Enum\r\n",
|
||||
vb6_grammar::enum_declaration, enum1);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(enum1.name == "PatTypes");
|
||||
ut::expect(enum1.at == vb6_ast::access_type::na);
|
||||
ut::expect((enum1.values.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(enum1.values[0].first == "inpatient");
|
||||
ut::expect(!enum1.values[0].second);
|
||||
|
||||
ut::expect(enum1.values[1].first == "outpatient");
|
||||
ut::expect(!enum1.values[1].second);
|
||||
};
|
||||
|
||||
ut::test("global_var_declaration") = []
|
||||
{
|
||||
auto str = "Global g_logger As Long, v1, XRes As New Object, ptr As Module.MyRec, g_active As Boolean\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(vars.at == vb6_ast::access_type::global);
|
||||
ut::expect(!vars.with_events);
|
||||
ut::expect((vars.vars.size() == 5) >> ut::fatal);
|
||||
|
||||
//cout << "size: " << vars.vars.size() << "\n";
|
||||
|
||||
ut::expect(vars.vars[0].name == "g_logger");
|
||||
ut::expect(!vars.vars[0].construct);
|
||||
ut::expect(vars.vars[0].type.has_value());
|
||||
if(vars.vars[0].type)
|
||||
{
|
||||
ut::expect(*vars.vars[0].type == "Long");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[1].name == "v1");
|
||||
ut::expect(!vars.vars[1].construct);
|
||||
ut::expect(!vars.vars[1].type.has_value());
|
||||
|
||||
ut::expect(vars.vars[2].name == "XRes");
|
||||
ut::expect(vars.vars[2].construct);
|
||||
ut::expect(vars.vars[2].type.has_value());
|
||||
if(vars.vars[2].type)
|
||||
{
|
||||
ut::expect(*vars.vars[2].type == "Object");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[3].name == "ptr");
|
||||
ut::expect(!vars.vars[3].construct);
|
||||
ut::expect(vars.vars[3].type.has_value());
|
||||
if(vars.vars[3].type)
|
||||
{
|
||||
ut::expect(*vars.vars[3].type == "MyRec");
|
||||
}
|
||||
|
||||
ut::expect(vars.vars[4].name == "g_active");
|
||||
ut::expect(!vars.vars[4].construct);
|
||||
ut::expect(vars.vars[4].type.has_value());
|
||||
if(vars.vars[4].type)
|
||||
{
|
||||
ut::expect(*vars.vars[4].type == "Boolean");
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("const_var_declaration1") = []
|
||||
{
|
||||
auto cstr = "Const e As Single = 2.8, pi As Double = 3.14, u As Integer = -1\r\n"s;
|
||||
vb6_ast::const_var_stat cvars;
|
||||
auto [res, sv] = test_grammar(cstr, vb6_grammar::const_var_declaration, cvars);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect((cvars.size() == 3) >> ut::fatal);
|
||||
|
||||
//cout << "size: " << cvars.size() << "\n";
|
||||
|
||||
ut::expect(cvars[0].var.name == "e");
|
||||
if(cvars[0].var.type)
|
||||
{
|
||||
ut::expect(*cvars[0].var.type == "Single");
|
||||
}
|
||||
ut::expect(!cvars[0].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[0].value.get()) == 2.8f);
|
||||
|
||||
ut::expect(cvars[1].var.name == "pi");
|
||||
if(cvars[1].var.type)
|
||||
{
|
||||
ut::expect(*cvars[1].var.type == "Double");
|
||||
}
|
||||
ut::expect(!cvars[1].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[1].value.get()) == 3.14f);
|
||||
|
||||
ut::expect(cvars[2].var.name == "u");
|
||||
if(cvars[2].var.type)
|
||||
{
|
||||
ut::expect(*cvars[2].var.type == "Integer");
|
||||
}
|
||||
ut::expect(!cvars[2].var.construct);
|
||||
ut::expect(boost::get<vb6_ast::integer_dec>(cvars[2].value.get()).val == -1);
|
||||
};
|
||||
|
||||
ut::test("const_var_declaration2") = []
|
||||
{
|
||||
vb6_ast::const_var_stat cvars;
|
||||
auto [res, sv] = test_grammar("Private Const PI As Double = 3.1415\r\n",
|
||||
vb6_grammar::const_var_declaration, cvars);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect((cvars.size() == 1) >> ut::fatal);
|
||||
|
||||
//cout << "size: " << cvars.size() << "\n";
|
||||
|
||||
ut::expect(cvars[0].var.name == "PI");
|
||||
if(cvars[0].var.type)
|
||||
{
|
||||
ut::expect(*cvars[0].var.type == "Double");
|
||||
}
|
||||
ut::expect(!cvars[0].var.construct);
|
||||
ut::expect(boost::get<float>(cvars[0].value.get()) == 3.1415f);
|
||||
};
|
||||
|
||||
ut::test("param_decl") = []
|
||||
{
|
||||
vb6_ast::func_param fp;
|
||||
auto [res, sv] = test_grammar("Optional ByVal name As String = \"pippo\"", vb6_grammar::param_decl, fp);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(fp.isoptional);
|
||||
ut::expect(fp.qualifier.has_value());
|
||||
if(fp.qualifier)
|
||||
{
|
||||
ut::expect(*fp.qualifier == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(fp.var.name == "name");
|
||||
ut::expect(!fp.var.construct);
|
||||
ut::expect(fp.var.type.has_value());
|
||||
if(fp.var.type)
|
||||
{
|
||||
ut::expect(*fp.var.type == "String");
|
||||
}
|
||||
ut::expect(fp.defvalue.has_value());
|
||||
if(fp.defvalue)
|
||||
{
|
||||
ut::expect(boost::get<vb6_ast::quoted_string>(fp.defvalue.get()) == "pippo");
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("param_list_decl") = []
|
||||
{
|
||||
vector<vb6_ast::func_param> fps;
|
||||
auto [res, sv] = test_grammar("ByVal name As String, ByRef val As Integer",
|
||||
-(vb6_grammar::param_decl % ','), fps);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
//cout << "size: " << fps.size() << "\n";
|
||||
|
||||
ut::expect((fps.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(!fps[0].isoptional);
|
||||
ut::expect(fps[0].qualifier.has_value());
|
||||
if(fps[0].qualifier)
|
||||
{
|
||||
ut::expect(*fps[0].qualifier == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(fps[0].var.name == "name");
|
||||
ut::expect(!fps[0].var.construct);
|
||||
ut::expect(fps[0].var.type.has_value());
|
||||
if(fps[0].var.type)
|
||||
{
|
||||
ut::expect(*fps[0].var.type == "String");
|
||||
}
|
||||
ut::expect(!fps[0].defvalue);
|
||||
|
||||
ut::expect(!fps[1].isoptional);
|
||||
ut::expect(fps[1].qualifier.has_value());
|
||||
if(fps[1].qualifier)
|
||||
{
|
||||
ut::expect(*fps[1].qualifier == vb6_ast::param_qualifier::byref);
|
||||
}
|
||||
ut::expect(fps[1].var.name == "val");
|
||||
ut::expect(!fps[1].var.construct);
|
||||
ut::expect(fps[1].var.type.has_value());
|
||||
if(fps[1].var.type)
|
||||
{
|
||||
ut::expect(*fps[1].var.type == "Integer");
|
||||
}
|
||||
ut::expect(!fps[1].defvalue);
|
||||
};
|
||||
|
||||
ut::test("event_declaration") = []
|
||||
{
|
||||
vb6_ast::eventHead event_decl;
|
||||
auto [res, sv] = test_grammar("Public Event OnChange(ByVal Text As String)\r\n",
|
||||
vb6_grammar::eventHead, event_decl);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(event_decl.at == vb6_ast::access_type::public_);
|
||||
ut::expect(event_decl.name == "OnChange");
|
||||
ut::expect(event_decl.params.size() == 1);
|
||||
};
|
||||
|
||||
ut::test("function_head") = []
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Function OneFunc(ByVal name As String, ByRef val As Integer) As Integer\r\n",
|
||||
vb6_grammar::functionHead, fh);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(fh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(fh.name == "OneFunc");
|
||||
ut::expect(fh.params.size() == 2);
|
||||
ut::expect(fh.return_type.has_value());
|
||||
ut::expect(*fh.return_type == "Integer");
|
||||
};
|
||||
|
||||
ut::test("function_head_no_params") = []
|
||||
{
|
||||
vb6_ast::functionHead fh;
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Function NoParamFunc() As Object\r\n", vb6_grammar::functionHead, fh);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(fh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(fh.name == "NoParamFunc");
|
||||
ut::expect(fh.params.empty());
|
||||
ut::expect((fh.return_type.has_value()) >> ut::fatal);
|
||||
ut::expect(*fh.return_type == "Object");
|
||||
};
|
||||
|
||||
ut::test("subroutine_head") = []
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, ByVal valid As Boolean)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect(sh.params.size() == 2);
|
||||
};
|
||||
|
||||
ut::test("subroutine_head2") = []
|
||||
{
|
||||
auto str = "Private Sub my_sub(ByRef str As String, ByVal valid As Boolean, Optional ByVal flag As Boolean = True)\r\n"s;
|
||||
vb6_ast::subHead sh;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::subHead, sh);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect(sh.params.size() == 3);
|
||||
};
|
||||
|
||||
ut::test("subroutine_head_with_optional_params") = []
|
||||
{
|
||||
vb6_ast::subHead sh;
|
||||
auto [res, sv] = test_grammar(
|
||||
"Private Sub my_sub(ByRef str As String, Optional ByVal valid As Boolean = false)\r\n",
|
||||
vb6_grammar::subHead, sh);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(sh.at == vb6_ast::access_type::private_);
|
||||
ut::expect(sh.name == "my_sub");
|
||||
ut::expect((sh.params.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(sh.params[0].qualifier.has_value());
|
||||
if (sh.params[0].qualifier)
|
||||
ut::expect(sh.params[0].qualifier.get() == vb6_ast::param_qualifier::byref);
|
||||
ut::expect(sh.params[0].var.name == "str");
|
||||
if(sh.params[0].var.type)
|
||||
{
|
||||
ut::expect(*sh.params[0].var.type == "String");
|
||||
}
|
||||
ut::expect(!sh.params[0].var.construct);
|
||||
ut::expect(!sh.params[0].isoptional);
|
||||
ut::expect(!sh.params[0].defvalue);
|
||||
|
||||
ut::expect(sh.params[1].qualifier.has_value());
|
||||
if(sh.params[1].qualifier)
|
||||
{
|
||||
ut::expect(sh.params[1].qualifier.get() == vb6_ast::param_qualifier::byval);
|
||||
}
|
||||
ut::expect(sh.params[1].var.name == "valid");
|
||||
if(sh.params[1].var.type)
|
||||
{
|
||||
ut::expect(*sh.params[1].var.type == "Boolean");
|
||||
}
|
||||
ut::expect(!sh.params[1].var.construct);
|
||||
ut::expect(sh.params[1].isoptional);
|
||||
ut::expect(sh.params[1].defvalue.has_value());
|
||||
if(sh.params[0].defvalue)
|
||||
{
|
||||
ut::expect(boost::get<bool>(*sh.params[0].defvalue) == false);
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("property_let_head") = []
|
||||
{
|
||||
auto str = "Public Property Let Width(ByVal w As Integer)\r\n"s;
|
||||
vb6_ast::propertyLetHead ast;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::property_letHead, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(ast.at == vb6_ast::access_type::public_);
|
||||
ut::expect(ast.name == "Width");
|
||||
ut::expect(ast.params.size() == 1);
|
||||
};
|
||||
|
||||
ut::test("property_get_head") = []
|
||||
{
|
||||
auto str = "Public Property Get Width() As Integer\r\n"s;
|
||||
vb6_ast::propertyGetHead ast;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::property_getHead, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(ast.at == vb6_ast::access_type::public_);
|
||||
ut::expect(ast.name == "Width");
|
||||
ut::expect(ast.params.size() == 0);
|
||||
ut::expect(ast.return_type >> fatal);
|
||||
ut::expect(*ast.return_type == "Integer");
|
||||
};
|
||||
|
||||
ut::test("dll_subroutine_declaration") = []
|
||||
{
|
||||
vb6_ast::externalSub extsub;
|
||||
auto str = "Private Declare Sub BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single)\r\n"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::external_sub_decl, extsub);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(extsub.at == vb6_ast::access_type::private_);
|
||||
ut::expect(extsub.name == "BeepVB");
|
||||
ut::expect(extsub.alias == "Beep");
|
||||
ut::expect(extsub.params.size() == 2);
|
||||
ut::expect(extsub.lib == "kernel32.dll");
|
||||
};
|
||||
|
||||
ut::test("dll_function_declaration") = []
|
||||
{
|
||||
vb6_ast::externalFunction extfunc;
|
||||
auto str = "Private Declare Function BeepVB Lib \"kernel32.dll\" Alias \"Beep\" (ByVal time As Long, ByVal xx As Single) As Long\r\n"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::external_function_decl, extfunc);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(extfunc.at == vb6_ast::access_type::private_);
|
||||
ut::expect(extfunc.name == "BeepVB");
|
||||
ut::expect(extfunc.return_type.has_value());
|
||||
if(extfunc.return_type)
|
||||
{
|
||||
ut::expect(*extfunc.return_type == "Long");
|
||||
}
|
||||
ut::expect(extfunc.alias == "Beep");
|
||||
ut::expect(extfunc.params.size() == 2);
|
||||
ut::expect(extfunc.lib == "kernel32.dll");
|
||||
};
|
||||
|
||||
ut::test("identifier_context") = []
|
||||
{
|
||||
vb6_ast::identifier_context ctx;
|
||||
auto [res, sv] = test_grammar("var1.func().pnt1.", vb6_grammar::identifier_context, ctx);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(!ctx.leading_dot);
|
||||
ut::expect((ctx.elements.size() == 3) >> ut::fatal);
|
||||
ut::expect(boost::get<string>(ctx.elements[0].get()) == "var1");
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(ctx.elements[1].get()).get();
|
||||
ut::expect(tmp.func_name == "func");
|
||||
ut::expect(tmp.params.empty());
|
||||
ut::expect(boost::get<string>(ctx.elements[2].get()) == "pnt1");
|
||||
};
|
||||
|
||||
ut::test("decorated_variable") = []
|
||||
{
|
||||
vb6_ast::decorated_variable dec_var;
|
||||
auto [res, sv] = test_grammar("var1.func().pnt1.X", vb6_grammar::decorated_variable, dec_var);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(!dec_var.ctx.leading_dot);
|
||||
ut::expect((dec_var.ctx.elements.size() == 3) >> ut::fatal);
|
||||
ut::expect(boost::get<string>(dec_var.ctx.elements[0].get()) == "var1");
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(dec_var.ctx.elements[1].get()).get();
|
||||
ut::expect(tmp.func_name == "func");
|
||||
ut::expect(tmp.params.empty());
|
||||
ut::expect(boost::get<string>(dec_var.ctx.elements[2].get()) == "pnt1");
|
||||
ut::expect(dec_var.var == "X");
|
||||
};
|
||||
|
||||
ut::test("attribute_block") = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::module_attributes attrs;
|
||||
auto str = "Attribute ModuleName = \"MyForm\"\r\n"
|
||||
"Attribute ProgID = \"00-00-00-00\"\r\n"s;
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::attributeDef, attrs);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(attrs.size() == 2);
|
||||
|
||||
auto it1 = attrs.find("ModuleName");
|
||||
ut::expect(it1 != attrs.cend());
|
||||
if(it1 != attrs.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto it2 = attrs.find("ProgID");
|
||||
ut::expect(it2 != attrs.cend());
|
||||
if(it2 != attrs.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("attributes") = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::module_attributes ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
)vb"s;
|
||||
//auto [res, sv] = test_grammar(str, vb6_grammar::preamble, ast);
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::attributeDef, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(ast.size() == 2);
|
||||
|
||||
auto const it1 = ast.find("ModuleName");
|
||||
ut::expect(it1 != ast.cend());
|
||||
if(it1 != ast.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto const it2 = ast.find("ProgID");
|
||||
ut::expect(it2 != ast.cend());
|
||||
if(it2 != ast.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
};
|
||||
|
||||
ut::test("options") = []
|
||||
{
|
||||
vector<vb6_ast::module_option> ast;
|
||||
auto str = R"vb(Option Explicit
|
||||
Option Base 0
|
||||
)vb"s;
|
||||
auto [res, sv] = test_grammar(str, *vb6_grammar::option_item, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect((ast.size() == 2) >> ut::fatal);
|
||||
|
||||
ut::expect(ast[0] == vb6_ast::module_option::explicit_);
|
||||
ut::expect(ast[1] == vb6_ast::module_option::base_0);
|
||||
};
|
||||
|
||||
#if 0
|
||||
ut::test("declaration_block") = []
|
||||
{
|
||||
auto const declarations
|
||||
= boost::spirit::x3::rule<class _, vector<vb6_ast::STRICT_MODULE_STRUCTURE::declaration>>("declaration_block")
|
||||
= *vb6_grammar::STRICT_MODULE_STRUCTURE::declaration;
|
||||
|
||||
vector<vb6_ast::STRICT_MODULE_STRUCTURE::declaration> decls;
|
||||
auto str = "Const e As Double = 2.8, pi As Double = 3.14, u As Integer = -1\r\n"
|
||||
"Global g_logger As Long, v1, XRes As Object, ptr As MyRec, g_active As Boolean\r\n"
|
||||
"Private Declare Sub PFoo Lib \"mylib.dll\" Alias \"PFoo\" (ByVal val As Long)\r\n"
|
||||
"Enum MyEnum1\r\n c1 = 0\r\n c2 = 1\r\nEnd Enum\r\n"
|
||||
"Public Type MyRecord1\r\n v1 As String\r\n v2 As Long\r\nEnd Type\r\n"s;
|
||||
auto [res, sv] = test_grammar(str, declarations, decls);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect((decls.size() == 5) >> ut::fatal);
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(decls[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(decls[1].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::externalSub>(decls[2].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(decls[3].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::record>(decls[4].get();})));
|
||||
};
|
||||
|
||||
ut::test("bas_unit_STRICT_MODULE_STRUCTURE") = []
|
||||
{
|
||||
vb6_ast::STRICT_MODULE_STRUCTURE::vb_module ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
Option Explicit
|
||||
Option Base 0
|
||||
|
||||
' declarations
|
||||
Const u As Integer = 1234
|
||||
Global g_logger As Long
|
||||
Enum MyEnum1
|
||||
c1 = 0
|
||||
c2 = 1
|
||||
End Enum
|
||||
Sub my_sub(ByRef str As String)
|
||||
End Sub
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::STRICT_MODULE_STRUCTURE::basModDef, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
|
||||
ut::expect(ast.attrs.size() == 2);
|
||||
|
||||
auto const it1 = ast.attrs.find("ModuleName");
|
||||
EXPECT_NE(it1, ast.attrs.cend());
|
||||
if(it1 != ast.attrs.cend())
|
||||
{
|
||||
ut::expect(it1->second == "MyForm");
|
||||
}
|
||||
|
||||
auto const it2 = ast.attrs.find("ProgID");
|
||||
EXPECT_NE(it2, ast.attrs.cend());
|
||||
if(it2 != ast.attrs.cend())
|
||||
{
|
||||
ut::expect(it2->second == "00-00-00-00");
|
||||
}
|
||||
|
||||
ut::expect(ast.opts.items.size() == 4);
|
||||
if(ast.opts.items.size() == 4)
|
||||
{
|
||||
#if 0
|
||||
ut::expect(ast.opts.items[0] == vb6_ast::module_option::explicit_);
|
||||
ut::expect(ast.opts.items[1] == vb6_ast::module_option::base_0);
|
||||
#else
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast.opts.items[0].get()) == vb6_ast::module_option::explicit_);
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast.opts.items[1].get()) == vb6_ast::module_option::base_0);
|
||||
#endif
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast.opts.items[2].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::lonely_comment>(ast.opts.items[3].get();})));
|
||||
}
|
||||
|
||||
ut::expect(ast.declarations.size() == 3);
|
||||
if(ast.declarations.size() == 3)
|
||||
{
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(ast.declarations[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(ast.declarations[1].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(ast.declarations[2].get();})));
|
||||
}
|
||||
|
||||
ut::expect(ast.functions.size() == 2);
|
||||
if(ast.functions.size() == 2)
|
||||
{
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::subDef>(ast.functions[0].get();})));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::functionDef>(ast.functions[1].get();})));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
ut::test("bas_unit") = []
|
||||
{
|
||||
vb6_ast::vb_module ast;
|
||||
auto str = R"vb(Attribute ModuleName = "MyForm"
|
||||
Attribute ProgID = "00-00-00-00"
|
||||
Option Explicit
|
||||
Option Base 0
|
||||
|
||||
' declarations
|
||||
Const u As Integer = 1234
|
||||
Global g_logger As Long
|
||||
Enum MyEnum1
|
||||
c1 = 0
|
||||
c2 = 1
|
||||
End Enum
|
||||
Sub my_sub(ByRef str As String)
|
||||
End Sub
|
||||
Function my_fun(ByRef str As String) As Long
|
||||
End Function
|
||||
)vb"s;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::basModDef, ast);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
vb6_ast_printer P(cout);
|
||||
P(ast);
|
||||
|
||||
ut::expect(ut::eq(ast.size(), 11) >> ut::fatal);
|
||||
|
||||
ut::expect(boost::get<vb6_ast::module_attribute>(ast[0].get()).first == "ModuleName");
|
||||
ut::expect(boost::get<vb6_ast::module_attribute>(ast[1].get()).first == "ProgID");
|
||||
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast[2].get()) == vb6_ast::module_option::explicit_);
|
||||
ut::expect(boost::get<vb6_ast::module_option>(ast[3].get()) == vb6_ast::module_option::base_0);
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::empty_line>(ast[4].get());}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::lonely_comment>(ast[5].get());}));
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::const_var_stat>(boost::get<vb6_ast::declaration>(ast[6].get()));}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::global_var_decls>(boost::get<vb6_ast::declaration>(ast[7].get()));}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::vb_enum>(boost::get<vb6_ast::declaration>(ast[8].get()));}));
|
||||
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::subDef>(ast[9].get());}));
|
||||
ut::expect(ut::nothrow([ast](){boost::get<vb6_ast::functionDef>(ast[10].get());}));
|
||||
};
|
||||
|
||||
ut::test("trailing_comment") = []
|
||||
{
|
||||
auto str = "Global g_var As Long ' how can we catch a trailing comment?\r\n"s;
|
||||
vb6_ast::global_var_decls vars;
|
||||
auto [res, sv] = test_grammar(str, vb6_grammar::global_var_declaration, vars);
|
||||
ut::expect((res) >> fatal) << "stopped at: " << sv;
|
||||
ut::expect(sv.empty());
|
||||
|
||||
ut::expect(vars.at == vb6_ast::access_type::global);
|
||||
ut::expect(!vars.with_events);
|
||||
ut::expect((vars.vars.size() == 1) >> ut::fatal);
|
||||
|
||||
ut::expect(vars.vars[0].name == "g_var");
|
||||
ut::expect(!vars.vars[0].construct);
|
||||
ut::expect(vars.vars[0].type.has_value());
|
||||
if(vars.vars[0].type)
|
||||
{
|
||||
ut::expect(*vars.vars[0].type == "Long");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
|
||||
{
|
||||
log_compiler_info(std::cout);
|
||||
|
||||
bool res = boost::ut::cfg<boost::ut::override>.run();
|
||||
return res ? 0 : -1;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
//#define BOOST_SPIRIT_X3_DEBUG
|
||||
|
||||
#include "test_grammar_helper_gtest.hpp"
|
||||
#include "test_grammar_helper_ut.hpp"
|
||||
#include "vb6_parser.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -21,7 +21,9 @@ namespace x3 = boost::spirit::x3;
|
||||
GTEST_TEST(vb6_parser_statements, Assignment_0)
|
||||
{
|
||||
vb6_ast::statements::assignStmt st;
|
||||
test_grammar("Set var1 = \" ciao\"\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
auto [res, sv] = test_grammar("Set var1 = \" ciao\"\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::assignmentType::set);
|
||||
EXPECT_EQ(st.var.var, "var1");
|
||||
@@ -35,7 +37,9 @@ GTEST_TEST(vb6_parser_statements, Assignment_0)
|
||||
GTEST_TEST(vb6_parser_statements, Assignment_1)
|
||||
{
|
||||
vb6_ast::statements::assignStmt st;
|
||||
test_grammar("Let var2 = 54.7\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
auto [res, sv] = test_grammar("Let var2 = 54.7\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::assignmentType::let);
|
||||
EXPECT_EQ(st.var.var, "var2");
|
||||
@@ -49,7 +53,9 @@ GTEST_TEST(vb6_parser_statements, Assignment_1)
|
||||
GTEST_TEST(vb6_parser_statements, Assignment_2)
|
||||
{
|
||||
vb6_ast::statements::assignStmt st;
|
||||
test_grammar("var3 = Func(\"descr\", 54.7)\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
auto [res, sv] = test_grammar("var3 = Func(\"descr\", 54.7)\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::assignmentType::na);
|
||||
EXPECT_EQ(st.var.var, "var3");
|
||||
@@ -64,7 +70,9 @@ GTEST_TEST(vb6_parser_statements, Assignment_2)
|
||||
GTEST_TEST(vb6_parser_statements, Assignment_3)
|
||||
{
|
||||
vb6_ast::statements::assignStmt st;
|
||||
test_grammar("str = CStr(i)\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
auto [res, sv] = test_grammar("str = CStr(i)\r\n", vb6_grammar::statements::assignmentStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::assignmentType::na);
|
||||
EXPECT_EQ(st.var.var, "str");
|
||||
@@ -75,7 +83,9 @@ GTEST_TEST(vb6_parser_statements, Assignment_3)
|
||||
GTEST_TEST(vb6_parser_statements, LocalVarDecl_1)
|
||||
{
|
||||
vb6_ast::statements::localVarDeclStmt st;
|
||||
test_grammar("Dim var As New Form\r\n", vb6_grammar::statements::localvardeclStmt, st);
|
||||
auto [res, sv] = test_grammar("Dim var As New Form\r\n", vb6_grammar::statements::localvardeclStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::localvardeclType::Dim);
|
||||
|
||||
@@ -90,7 +100,9 @@ GTEST_TEST(vb6_parser_statements, LocalVarDecl_1)
|
||||
GTEST_TEST(vb6_parser_statements, LocalVarDecl_2)
|
||||
{
|
||||
vb6_ast::statements::localVarDeclStmt st;
|
||||
test_grammar("Static var1 As String, var2 As Integer\r\n", vb6_grammar::statements::localvardeclStmt, st);
|
||||
auto [res, sv] = test_grammar("Static var1 As String, var2 As Integer\r\n", vb6_grammar::statements::localvardeclStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::localvardeclType::Static);
|
||||
|
||||
@@ -110,8 +122,11 @@ GTEST_TEST(vb6_parser_statements, LocalVarDecl_2)
|
||||
GTEST_TEST(vb6_parser_statements, ReDim)
|
||||
{
|
||||
vb6_ast::statements::redimStmt st;
|
||||
test_grammar("ReDim var1(15)\r\n", vb6_grammar::statements::redimStmt, st);
|
||||
//test_grammar("ReDim var1(2*L + 1)\r\n", vb6_grammar::statements::redimStmt, st);
|
||||
auto [res, sv] = test_grammar("ReDim var1(15)\r\n", vb6_grammar::statements::redimStmt, st);
|
||||
//auto [res, sv] = test_grammar("ReDim var1(2*L + 1)\r\n", vb6_grammar::statements::redimStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_FALSE(st.preserve);
|
||||
EXPECT_EQ(st.var.var, "var1");
|
||||
}
|
||||
@@ -119,7 +134,9 @@ GTEST_TEST(vb6_parser_statements, ReDim)
|
||||
GTEST_TEST(vb6_parser_statements, Exit)
|
||||
{
|
||||
vb6_ast::statements::exitStmt st;
|
||||
test_grammar("Exit Function\r\n", vb6_grammar::statements::exitStmt, st);
|
||||
auto [res, sv] = test_grammar("Exit Function\r\n", vb6_grammar::statements::exitStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::exit_type::function);
|
||||
}
|
||||
@@ -127,7 +144,9 @@ GTEST_TEST(vb6_parser_statements, Exit)
|
||||
GTEST_TEST(vb6_parser_statements, GoTo)
|
||||
{
|
||||
vb6_ast::statements::gotoStmt st;
|
||||
test_grammar("GoSub label1\r\n", vb6_grammar::statements::gotoStmt, st);
|
||||
auto [res, sv] = test_grammar("GoSub label1\r\n", vb6_grammar::statements::gotoStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::gotoType::gosub_v);
|
||||
EXPECT_EQ(st.label, "label1");
|
||||
@@ -136,7 +155,9 @@ GTEST_TEST(vb6_parser_statements, GoTo)
|
||||
GTEST_TEST(vb6_parser_statements, OnError)
|
||||
{
|
||||
vb6_ast::statements::onerrorStmt st;
|
||||
test_grammar("On Error Resume Next\r\n", vb6_grammar::statements::onerrorStmt, st);
|
||||
auto [res, sv] = test_grammar("On Error Resume Next\r\n", vb6_grammar::statements::onerrorStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.type, vb6_ast::onerror_type::resume_next);
|
||||
EXPECT_TRUE(st.label.empty());
|
||||
@@ -146,25 +167,40 @@ GTEST_TEST(vb6_parser_statements, Resume)
|
||||
{
|
||||
vb6_ast::statements::resumeStmt st;
|
||||
|
||||
test_grammar("Resume\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::implicit);
|
||||
|
||||
test_grammar("Resume Next\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::next);
|
||||
|
||||
test_grammar("Resume 0\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::line_nr);
|
||||
EXPECT_EQ(boost::get<int>(st.label_or_line_nr), 0);
|
||||
|
||||
test_grammar("Resume resume_point\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::label);
|
||||
EXPECT_EQ(boost::get<string>(st.label_or_line_nr), "resume_point");
|
||||
{
|
||||
auto [res, sv] = test_grammar("Resume\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::implicit);
|
||||
}
|
||||
{
|
||||
auto [res, sv] = test_grammar("Resume Next\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::next);
|
||||
}
|
||||
{
|
||||
auto [res, sv] = test_grammar("Resume 0\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::line_nr);
|
||||
EXPECT_EQ(boost::get<int>(st.label_or_line_nr), 0);
|
||||
}
|
||||
{
|
||||
auto [res, sv] = test_grammar("Resume resume_point\r\n", vb6_grammar::statements::resumeStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
EXPECT_EQ(st.type, vb6_ast::resume_type::label);
|
||||
EXPECT_EQ(boost::get<string>(st.label_or_line_nr), "resume_point");
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_statements, Label)
|
||||
{
|
||||
vb6_ast::statements::labelStmt st;
|
||||
test_grammar("label1:\r\n", vb6_grammar::statements::labelStmt, st);
|
||||
auto [res, sv] = test_grammar("label1:\r\n", vb6_grammar::statements::labelStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.label, "label1");
|
||||
}
|
||||
@@ -172,19 +208,27 @@ GTEST_TEST(vb6_parser_statements, Label)
|
||||
GTEST_TEST(vb6_parser_statements, Call_explicit)
|
||||
{
|
||||
vb6_ast::statements::callStmt st;
|
||||
test_grammar("Call Foo(13)\r\n", vb6_grammar::statements::callexplicitStmt, st);
|
||||
auto [res, sv] = test_grammar("Call Foo(13)\r\n", vb6_grammar::statements::callexplicitStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_TRUE(st.explicit_call);
|
||||
EXPECT_EQ(st.sub_name, "Foo");
|
||||
EXPECT_EQ(st.params.size(), 1);
|
||||
|
||||
test_grammar("Call Foo 13\r\n", vb6_grammar::statements::callexplicitStmt, st, false);
|
||||
{
|
||||
auto [res, sv] = test_grammar("Call Foo 13\r\n", vb6_grammar::statements::callexplicitStmt, st);
|
||||
ASSERT_FALSE(res) << "stopped at: " << sv;
|
||||
//EXPECT_TRUE(sv.empty());
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_statements, Call_implicit)
|
||||
{
|
||||
vb6_ast::statements::callStmt st;
|
||||
test_grammar("Foo \"Sea\", Nothing, False\r\n", vb6_grammar::statements::callimplicitStmt, st);
|
||||
auto [res, sv] = test_grammar("Foo \"Sea\", Nothing, False\r\n", vb6_grammar::statements::callimplicitStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_FALSE(st.explicit_call);
|
||||
EXPECT_EQ(st.sub_name, "Foo");
|
||||
@@ -194,14 +238,16 @@ GTEST_TEST(vb6_parser_statements, Call_implicit)
|
||||
GTEST_TEST(vb6_parser_statements, RaiseEvent)
|
||||
{
|
||||
vb6_ast::statements::raiseeventStmt st;
|
||||
test_grammar("RaiseEvent OnChange(\"hi!\")\r\n",
|
||||
auto [res, sv] = test_grammar("RaiseEvent OnChange(\"hi!\")\r\n",
|
||||
vb6_grammar::statements::raiseeventStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_statements, statement_block)
|
||||
{
|
||||
vb6_ast::statements::statement_block st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Set var1 = " ciao"
|
||||
Let var2 = 54.7
|
||||
var3 = Func("descr", 54.7)
|
||||
@@ -218,8 +264,10 @@ GTEST_TEST(vb6_parser_statements, statement_block)
|
||||
Foo "Sea", Nothing, False
|
||||
RaiseEvent OnChange("hi!")
|
||||
)vb", vb6_grammar::statements::statement_block, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.size(), 15);
|
||||
ASSERT_EQ(st.size(), 15);
|
||||
EXPECT_EQ(st[0].get().type(), typeid(vb6_ast::statements::assignStmt));
|
||||
EXPECT_EQ(st[1].get().type(), typeid(vb6_ast::statements::assignStmt));
|
||||
EXPECT_EQ(st[2].get().type(), typeid(vb6_ast::statements::assignStmt));
|
||||
@@ -240,12 +288,14 @@ GTEST_TEST(vb6_parser_statements, statement_block)
|
||||
GTEST_TEST(vb6_parser_compound_statements, With)
|
||||
{
|
||||
vb6_ast::statements::withStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(With obj
|
||||
'Call Module1.foo(True, .Name)
|
||||
Call foo(True, .Name)
|
||||
End With
|
||||
)vb", vb6_grammar::statements::withStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_FALSE(st.with_variable.ctx.leading_dot);
|
||||
EXPECT_TRUE(st.with_variable.ctx.elements.empty());
|
||||
@@ -256,12 +306,15 @@ GTEST_TEST(vb6_parser_compound_statements, With)
|
||||
GTEST_TEST(vb6_parser_compound_statements, While)
|
||||
{
|
||||
vb6_ast::statements::whileStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(While cond(34, i)
|
||||
Print str
|
||||
Wend
|
||||
)vb",
|
||||
vb6_grammar::statements::whileStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(st.condition.get()).get();
|
||||
EXPECT_EQ(tmp.func_name, "cond");
|
||||
EXPECT_EQ(tmp.params.size(), 2);
|
||||
@@ -271,24 +324,30 @@ GTEST_TEST(vb6_parser_compound_statements, While)
|
||||
GTEST_TEST(vb6_parser_compound_statements, Do)
|
||||
{
|
||||
vb6_ast::statements::doStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Do
|
||||
Print str
|
||||
Loop
|
||||
)vb",
|
||||
vb6_grammar::statements::doStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.block.size(), 1);
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_compound_statements, DoWhile)
|
||||
{
|
||||
vb6_ast::statements::dowhileStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Do While cond(34, i)
|
||||
Print str
|
||||
Loop
|
||||
)vb",
|
||||
vb6_grammar::statements::dowhileStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(st.condition.get()).get();
|
||||
EXPECT_EQ(tmp.func_name, "cond");
|
||||
EXPECT_EQ(tmp.params.size(), 2);
|
||||
@@ -298,12 +357,15 @@ GTEST_TEST(vb6_parser_compound_statements, DoWhile)
|
||||
GTEST_TEST(vb6_parser_compound_statements, LoopWhile)
|
||||
{
|
||||
vb6_ast::statements::loopwhileStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Do
|
||||
Print str
|
||||
Loop While cond(34, i)
|
||||
)vb",
|
||||
vb6_grammar::statements::loopwhileStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(st.condition.get()).get();
|
||||
EXPECT_EQ(tmp.func_name, "cond");
|
||||
EXPECT_EQ(tmp.params.size(), 2);
|
||||
@@ -313,12 +375,15 @@ GTEST_TEST(vb6_parser_compound_statements, LoopWhile)
|
||||
GTEST_TEST(vb6_parser_compound_statements, DoUntil)
|
||||
{
|
||||
vb6_ast::statements::dountilStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Do Until cond(34, i)
|
||||
Print str
|
||||
Loop
|
||||
)vb",
|
||||
vb6_grammar::statements::dountilStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(st.condition.get()).get();
|
||||
EXPECT_EQ(tmp.func_name, "cond");
|
||||
EXPECT_EQ(tmp.params.size(), 2);
|
||||
@@ -328,12 +393,15 @@ GTEST_TEST(vb6_parser_compound_statements, DoUntil)
|
||||
GTEST_TEST(vb6_parser_compound_statements, LoopUntil)
|
||||
{
|
||||
vb6_ast::statements::loopuntilStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Do
|
||||
Print str
|
||||
Loop Until cond(34, i)
|
||||
)vb",
|
||||
vb6_grammar::statements::loopuntilStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp = boost::get<x3::forward_ast<vb6_ast::func_call>>(st.condition.get()).get();
|
||||
EXPECT_EQ(tmp.func_name, "cond");
|
||||
EXPECT_EQ(tmp.params.size(), 2);
|
||||
@@ -343,7 +411,7 @@ GTEST_TEST(vb6_parser_compound_statements, LoopUntil)
|
||||
GTEST_TEST(vb6_parser_compound_statements, For)
|
||||
{
|
||||
vb6_ast::statements::forStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(For i = 1 To 100 Step 2
|
||||
Dim str As String
|
||||
str = CStr(i)
|
||||
@@ -351,6 +419,9 @@ GTEST_TEST(vb6_parser_compound_statements, For)
|
||||
Next i
|
||||
)vb",
|
||||
vb6_grammar::statements::forStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.for_variable.var, "i");
|
||||
EXPECT_FALSE(st.for_variable.ctx.leading_dot);
|
||||
EXPECT_TRUE(st.for_variable.ctx.elements.empty());
|
||||
@@ -369,12 +440,15 @@ GTEST_TEST(vb6_parser_compound_statements, For)
|
||||
GTEST_TEST(vb6_parser_compound_statements, ForEach)
|
||||
{
|
||||
vb6_ast::statements::foreachStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(For Each el In Items
|
||||
Call Print(el)
|
||||
Next el
|
||||
)vb",
|
||||
vb6_grammar::statements::foreachStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(st.for_variable.var, "el");
|
||||
EXPECT_FALSE(st.for_variable.ctx.leading_dot);
|
||||
EXPECT_TRUE(st.for_variable.ctx.elements.empty());
|
||||
@@ -389,49 +463,59 @@ GTEST_TEST(vb6_parser_compound_statements, ForEach)
|
||||
|
||||
GTEST_TEST(vb6_parser_compound_statements, IfElse_substatements)
|
||||
{
|
||||
vb6_ast::statements::if_branch ast1;
|
||||
test_grammar(
|
||||
R"vb(If cond1 Then
|
||||
Dim str As String
|
||||
str = CStr(i)
|
||||
Print str
|
||||
)vb",
|
||||
vb6_grammar::statements::ifBranch, ast1);
|
||||
{
|
||||
vb6_ast::statements::if_branch ast1;
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(If cond1 Then
|
||||
Dim str As String
|
||||
str = CStr(i)
|
||||
Print str
|
||||
)vb",
|
||||
vb6_grammar::statements::ifBranch, ast1);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
auto& tmp1 = boost::get<vb6_ast::decorated_variable>(ast1.condition.get());
|
||||
auto& tmp1 = boost::get<vb6_ast::decorated_variable>(ast1.condition.get());
|
||||
|
||||
EXPECT_EQ(tmp1.var, "cond1");
|
||||
EXPECT_EQ(ast1.block.size(), 3);
|
||||
EXPECT_EQ(tmp1.var, "cond1");
|
||||
EXPECT_EQ(ast1.block.size(), 3);
|
||||
}
|
||||
{
|
||||
vb6_ast::statements::if_branch ast2;
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(ElseIf cond2 Then
|
||||
Dim str As String
|
||||
str = CStr(i)
|
||||
Print str
|
||||
)vb",
|
||||
vb6_grammar::statements::elsifBranch, ast2);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
vb6_ast::statements::if_branch ast2;
|
||||
test_grammar(
|
||||
R"vb(ElseIf cond2 Then
|
||||
Dim str As String
|
||||
str = CStr(i)
|
||||
Print str
|
||||
)vb",
|
||||
vb6_grammar::statements::elsifBranch, ast2);
|
||||
auto& tmp2 = boost::get<vb6_ast::decorated_variable>(ast2.condition.get());
|
||||
|
||||
auto& tmp2 = boost::get<vb6_ast::decorated_variable>(ast2.condition.get());
|
||||
EXPECT_EQ(tmp2.var, "cond2");
|
||||
EXPECT_EQ(ast2.block.size(), 3);
|
||||
}
|
||||
{
|
||||
vb6_ast::statements::statement_block ast3;
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Else
|
||||
Print str
|
||||
'End If
|
||||
)vb",
|
||||
vb6_grammar::statements::elseBranch, ast3);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
EXPECT_EQ(tmp2.var, "cond2");
|
||||
EXPECT_EQ(ast2.block.size(), 3);
|
||||
|
||||
vb6_ast::statements::statement_block ast3;
|
||||
test_grammar(
|
||||
R"vb(Else
|
||||
Print str
|
||||
'End If
|
||||
)vb",
|
||||
vb6_grammar::statements::elseBranch, ast3);
|
||||
|
||||
EXPECT_EQ(ast3.size(), 2);
|
||||
EXPECT_EQ(ast3.size(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_TEST(vb6_parser_compound_statements, IfElse)
|
||||
{
|
||||
vb6_ast::statements::ifelseStmt ast;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(If cond1 Then
|
||||
Print "1"
|
||||
ElseIf cond2 Then
|
||||
@@ -443,6 +527,8 @@ GTEST_TEST(vb6_parser_compound_statements, IfElse)
|
||||
End If
|
||||
)vb",
|
||||
vb6_grammar::statements::ifelseStmt, ast);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
#ifdef SIMPLE_IF_STATEMENT
|
||||
EXPECT_EQ(ast.first_branch.block.size(), 5);
|
||||
@@ -471,7 +557,7 @@ GTEST_TEST(vb6_parser_compound_statements, IfElse)
|
||||
GTEST_TEST(vb6_parser_compound_statements, Select)
|
||||
{
|
||||
vb6_ast::statements::selectStmt st;
|
||||
test_grammar(
|
||||
auto [res, sv] = test_grammar(
|
||||
R"vb(Select Case frm.Type
|
||||
Case 0
|
||||
Dim str As String
|
||||
@@ -485,6 +571,8 @@ GTEST_TEST(vb6_parser_compound_statements, Select)
|
||||
' Print "Default"
|
||||
End Select
|
||||
)vb", vb6_grammar::statements::selectStmt, st);
|
||||
ASSERT_TRUE(res) << "stopped at: " << sv;
|
||||
EXPECT_TRUE(sv.empty());
|
||||
|
||||
ASSERT_EQ(st.condition.get().type(), typeid(vb6_ast::decorated_variable));
|
||||
EXPECT_EQ(boost::get<vb6_ast::decorated_variable>(st.condition.get()).var, "Type");
|
||||
Reference in New Issue
Block a user