code-debug icon indicating copy to clipboard operation
code-debug copied to clipboard

solve the problem of failed parsing of STL containers

Open HenryRiley0 opened this issue 1 year ago • 12 comments

2024-07-22_161812_149 2024-07-22_174619_782

solve the problem of failed parsing of STL containers

HenryRiley0 avatar Jul 22 '24 09:07 HenryRiley0

As the next entry in that loop is the parsing of primitives and that cannot include text I suggest to not check for std:: but instead for indexOf(" = {"), this should also work with derived container classes. What do you think?

I do wonder what the output of a container containing containers look like. Can you please test?

Can you try to replace "" by the part before the = { like "std::vector of length 4, capacity 6" as well?

In any case please add the Changelog entry.

GitMensch avatar Aug 22 '24 13:08 GitMensch

I do wonder what the output of a container containing containers look like. Can you please test? like below, and it works fine:

18-data-evaluate-expression "vecOfVecs"
GDB -> App: {"output":"","token":18,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::vector of length 4, capacity 6 = {std::vector of length 3, capacity 3 = {1, 2, 3}, std::vector of length 3, capacity 3 = {4, 5, 6}, std::vector of length 3, capacity 3 = {7, 8, 9}, std::vector of length 4, capacity 4 = {1, 2, 3, 4}}"]]}}
19-data-evaluate-expression "deqOfDeqs"
GDB -> App: {"output":"","token":19,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::deque with 3 elements = {std::deque with 2 elements = {10, 20}, std::deque with 2 elements = {30, 40}, std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}}"]]}}
20-data-evaluate-expression "listOfLists"
GDB -> App: {"output":"","token":20,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::__cxx11::list = {[0] = std::__cxx11::list = {[0] = 11, [1] = 12}, [1] = std::__cxx11::list = {[0] = 13, [1] = 14}, [2] = std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}}"]]}}

image

HenryRiley0 avatar Aug 23 '24 03:08 HenryRiley0

As the next entry in that loop is the parsing of primitives and that cannot include text I suggest to not check for std:: but instead for indexOf(" = {"), this should also work with derived container classes. What do you think?

it seems check for indexOf(" = {") may hit an object, in the middle or back of an value string

HenryRiley0 avatar Aug 23 '24 06:08 HenryRiley0

You're right.

if (value.match(/^[^=]* = /) {
    const eqPos = valuie.indexOf("="):
    value = value.substring(eqPos + 2)):
    return parseValue():
}

should fix that and drop the trim.

GitMensch avatar Aug 23 '24 06:08 GitMensch

Please rebase, so that we have only one (squashed) or two commits (which I'd use the "merge squashed" operation for) and a clearer diff.

GitMensch avatar Aug 23 '24 07:08 GitMensch

You're right.

if (value.match(/^[^=]* = /) {
    const eqPos = valuie.indexOf("="):
    value = value.substring(eqPos + 2)):
    return parseValue():
}

should fix that and drop the trim.

18-data-evaluate-expression "vec"
GDB -> App: {"token":18,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::vector of length 4, capacity 6 = {1, 2, 3, 4}"]]}}
19-data-evaluate-expression "deq"
GDB -> App: {"token":19,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}"]]}}
20-data-evaluate-expression "myList"
GDB -> App: {"token":20,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}"]]}}
21-data-evaluate-expression "vecOfVecs"
GDB -> App: {"token":21,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::vector of length 4, capacity 6 = {std::vector of length 3, capacity 3 = {1, 2, 3}, std::vector of length 3, capacity 3 = {4, 5, 6}, std::vector of length 3, capacity 3 = {7, 8, 9}, std::vector of length 4, capacity 4 = {1, 2, 3, 4}}"]]}}
22-data-evaluate-expression "deqOfDeqs"
GDB -> App: {"token":22,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::deque with 3 elements = {std::deque with 2 elements = {10, 20}, std::deque with 2 elements = {30, 40}, std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}}"]]}}

i tested only vec and deq works, myList、vecOfVecs、deqOfDeqs parse fail. image

HenryRiley0 avatar Aug 23 '24 07:08 HenryRiley0

i tested only vec and deq works, myList、vecOfVecs、deqOfDeqs parse fail.

What is the mi2 output which fails to parse?

Does it work (at least as good as the current version) when replacing the std:: check with (value.match(/^[^=]* = /) {

GitMensch avatar Aug 23 '24 09:08 GitMensch

it's strange

sucess

		else if(value.startsWith("std::")){
			const eqPos = value.indexOf("=");
			value = value.substring(eqPos + 2);
			return parseValue();
		}

image

fail

		else if(value.match(/^[^=]* = /)){
			const eqPos = value.indexOf("=");
			value = value.substring(eqPos + 2);
			return parseValue();
		}

image

test code:, break point 139

#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <forward_list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stack>
#include <queue>
#include <bitset>
#include <array>
#include <memory>
#include <atomic>
#include <fstream>
#include <sstream>
#include <regex>
#include <algorithm>
#include <mutex>

void testSTLContainers() {
    // std::vector
    std::vector<int> vec = {1, 2, 3};
    vec.push_back(4);

    // std::deque
    std::deque<int> deq = {1, 2, 3, 4, 5};
    deq.push_front(0);
    deq.push_back(6);

    // std::list
    std::list<int> myList = {7, 8, 9};
    myList.push_back(10);
    myList.push_front(6);

    std::vector<std::vector<int>> vecOfVecs = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    vecOfVecs.push_back(vec);

    std::deque<std::deque<int>> deqOfDeqs = {{10, 20}, {30, 40}};
    deqOfDeqs.push_back(deq);

    std::list<std::list<int>> listOfLists = {{11, 12}, {13, 14}};
    listOfLists.push_back(myList);

    // std::forward_list
    std::forward_list<int> fwdList = {1, 2, 3};
    fwdList.push_front(0);

    // std::set
    std::set<int> mySet = {4, 1, 3, 2};
    mySet.insert(5);

    // std::multiset
    std::multiset<int> myMultiSet = {1, 2, 2, 3, 4};
    myMultiSet.insert(2);

    // std::map
    std::map<int, std::string> myMap = {{1, "one"}, {2, "two"}};
    myMap[3] = "three";

    // std::multimap
    std::multimap<int, std::string> myMultiMap = {{1, "one"}, {2, "two"}, {2, "another two"}};

    // std::unordered_set
    std::unordered_set<int> myUnorderedSet = {4, 1, 3, 2};
    myUnorderedSet.insert(5);

    // std::unordered_multiset
    std::unordered_multiset<int> myUnorderedMultiSet = {1, 2, 2, 3, 4};
    myUnorderedMultiSet.insert(2);

    // std::unordered_map
    std::unordered_map<int, std::string> myUnorderedMap = {{1, "one"}, {2, "two"}};
    myUnorderedMap[3] = "three";

    // std::unordered_multimap
    std::unordered_multimap<int, std::string> myUnorderedMultiMap = {{1, "one"}, {2, "two"}, {2, "another two"}};

    // std::stack (based on std::deque)
    std::stack<int> myStack;
    myStack.push(1);
    myStack.push(2);

    // std::queue (based on std::deque)
    std::queue<int> myQueue;
    myQueue.push(1);
    myQueue.push(2);

    // std::priority_queue (max heap)
    std::priority_queue<int> myMaxHeap;
    myMaxHeap.push(3);
    myMaxHeap.push(1);
    myMaxHeap.push(4);

    // std::bitset
    std::bitset<8> bits("11010101");

    // std::array
    std::array<int, 3> myArray = {1, 2, 3};

    // std::unique_ptr
    std::unique_ptr<int> uniquePtr(new int(42));

    std::unique_ptr<int[]> uniquePtr1(new int[2]);

    uniquePtr1[0] = 10; 
    uniquePtr1[1] = 20; 

    // std::shared_ptr
    std::shared_ptr<int> sharedPtr = std::make_shared<int>(10);

    // std::weak_ptr
    std::weak_ptr<int> weakPtr = sharedPtr;

    // std::atomic
    std::atomic<int> atomicInt(0);

    // std::mutex
    std::mutex mtx;

    // std::ofstream
    std::ofstream file("example.txt");
    file << "Hello, world!";
    file.close();

    // std::stringstream
    std::stringstream ss;
    ss << "The answer is: " << 42;
    std::string result = ss.str();

    // std::regex
    std::regex pattern("\\d+");
    std::string text = "Hello 123 world";
    std::smatch match;
    std::regex_search(text, match, pattern);

    // Output results
    std::cout << "Vector elements: ";
    for (const auto& v : vec) {
        std::cout << v << " ";
    }
    std::cout << std::endl;

    std::cout << "Deque elements: ";
    for (const auto& d : deq) {
        std::cout << d << " ";
    }
    std::cout << std::endl;

    std::cout << "List elements: ";
    for (const auto& l : myList) {
        std::cout << l << " ";
    }
    std::cout << std::endl;

    std::cout << "Forward List elements: ";
    for (const auto& fl : fwdList) {
        std::cout << fl << " ";
    }
    std::cout << std::endl;

    std::cout << "Set elements: ";
    for (const auto& s : mySet) {
        std::cout << s << " ";
    }
    std::cout << std::endl;

    std::cout << "MultiSet elements: ";
    for (const auto& ms : myMultiSet) {
        std::cout << ms << " ";
    }
    std::cout << std::endl;

    std::cout << "Map elements: ";
    for (const auto& m : myMap) {
        std::cout << "{" << m.first << ": " << m.second << "} ";
    }
    std::cout << std::endl;

    std::cout << "MultiMap elements: ";
    for (const auto& mm : myMultiMap) {
        std::cout << "{" << mm.first << ": " << mm.second << "} ";
    }
    std::cout << std::endl;

    std::cout << "Unordered Set elements: ";
    for (const auto& us : myUnorderedSet) {
        std::cout << us << " ";
    }
    std::cout << std::endl;

    std::cout << "Unordered MultiSet elements: ";
    for (const auto& ums : myUnorderedMultiSet) {
        std::cout << ums << " ";
    }
    std::cout << std::endl;

    std::cout << "Unordered Map elements: ";
    for (const auto& um : myUnorderedMap) {
        std::cout << "{" << um.first << ": " << um.second << "} ";
    }
    std::cout << std::endl;

    std::cout << "Unordered MultiMap elements: ";
    for (const auto& umm : myUnorderedMultiMap) {
        std::cout << "{" << umm.first << ": " << umm.second << "} ";
    }
    std::cout << std::endl;

    std::cout << "Stack elements: ";
    while (!myStack.empty()) {
        std::cout << myStack.top() << " ";
        myStack.pop();
    }
    std::cout << std::endl;

    std::cout << "Queue elements: ";
    while (!myQueue.empty()) {
        std::cout << myQueue.front() << " ";
        myQueue.pop();
    }
    std::cout << std::endl;

    std::cout << "Priority Queue elements (max heap): ";
    while (!myMaxHeap.empty()) {
        std::cout << myMaxHeap.top() << " ";
        myMaxHeap.pop();
    }
    std::cout << std::endl;

    std::cout << "Bitset value: " << bits << std::endl;

    std::cout << "Array elements: ";
    for (const auto& a : myArray) {
        std::cout << a << " ";
    }
    std::cout << std::endl;

    std::cout << "Unique pointer value: " << *uniquePtr << std::endl;
    std::cout << "Shared pointer value: " << *sharedPtr << std::endl;
    std::cout << "Atomic integer value: " << atomicInt << std::endl;
    std::cout << "Regex match: " << match[0] << std::endl;
}

int main() {
    testSTLContainers();
    return 0;
}

HenryRiley0 avatar Aug 23 '24 10:08 HenryRiley0

pls dont merge, there is still a bug. i will fix next week.

HenryRiley0 avatar Aug 23 '24 10:08 HenryRiley0

work fine:

GDB -> App: {"token":18,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}"]]}}
19-data-evaluate-expression "vec"
GDB -> App: {"token":19,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::vector of length 4, capacity 6 = {1, 2, 3, 4}"]]}}
20-data-evaluate-expression "myList"
GDB -> App: {"token":20,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}"]]}}
21-data-evaluate-expression "vecOfVecs"
GDB -> App: {"token":21,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::vector of length 4, capacity 6 = {std::vector of length 3, capacity 3 = {1, 2, 3}, std::vector of length 3, capacity 3 = {4, 5, 6}, std::vector of length 3, capacity 3 = {7, 8, 9}, std::vector of length 4, capacity 4 = {1, 2, 3, 4}}"]]}}
22-data-evaluate-expression "deqOfDeqs"
GDB -> App: {"token":22,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["value","std::deque with 3 elements = {std::deque with 2 elements = {10, 20}, std::deque with 2 elements = {30, 40}, std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}}"]]}}

image

HenryRiley0 avatar Aug 26 '24 06:08 HenryRiley0

Do you have any idea what's wrong with if (value.match(/^[^=]* = /)) {?

GitMensch avatar Aug 26 '24 13:08 GitMensch

Do you have any idea what's wrong with if (value.match(/^[^=]* = /)) {?

image

std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}

[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}

value.match(/^[^=]* = /) works fine for std, but "[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}" will be match

HenryRiley0 avatar Aug 27 '24 02:08 HenryRiley0

Sounds like if (value.match(/^[^ =]* = /)) (= stopping at the first space) would be a better match. The reason for this pickiness here is that we'd like to also handle non-std containers correctly.

GitMensch avatar Sep 13 '24 21:09 GitMensch

Sounds like if (value.match(/^[^ =]* = /)) (= stopping at the first space) would be a better match. The reason for this pickiness here is that we'd like to also handle non-std containers correctly.

Yes, I have tried it. The "value.match(/^[^ =]* = /)" matches "std::* =", but it also matches other strings, such as _M_elems = {1, 2, 3} and [0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10, etc. In the test example, [["value","{_M_elems = {1, 2, 3}}"]], the match of "_M_elems = {1, 2, 3}" results in [0] = {1, 2, 3}; The match of "[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10" in std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10} results in [0] = 10. There are also other errors that prevent value.startsWith("std::") from being directly replaced with value.match(/^[^ =]* = /), because value.match(/^[^ =]* = /) broadens the scope and can lead to some logical errors.

HenryRiley0 avatar Sep 14 '24 03:09 HenryRiley0

Can you please add a Changelog entry and squash the commits to one?

GitMensch avatar Sep 18 '24 09:09 GitMensch

Can you please add a Changelog entry and squash the commits to one?

Of course, I will handle it right away.

HenryRiley0 avatar Sep 18 '24 09:09 HenryRiley0

Nice work! On to the next issue :-)

GitMensch avatar Sep 19 '24 09:09 GitMensch