-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathxparser.cpp
133 lines (119 loc) · 4.55 KB
/
xparser.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/************************************************************************************
* Copyright (c) 2023, xeus-cpp contributors *
* Copyright (c) 2023, Johan Mabille, Loic Gouarin, Sylvain Corlay, Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
************************************************************************************/
#include "xparser.hpp"
#include <cstddef>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
namespace xcpp
{
std::string trim(const std::string& str)
{
if (str.empty())
{
return str;
}
std::size_t firstScan = str.find_first_not_of(' ');
std::size_t first = firstScan == std::string::npos ? str.length() : firstScan;
std::size_t last = str.find_last_not_of(' ');
return str.substr(first, last - first + 1);
}
std::vector<std::string>
split_line(const std::string& input, const std::string& delims, std::size_t cursor_pos)
{
// passing -1 as the submatch index parameter performs splitting
std::vector<std::string> result;
std::stringstream ss;
ss << "[";
for (auto c : delims)
{
ss << "\\" << c;
}
ss << "]";
std::regex re(ss.str());
std::copy(
std::sregex_token_iterator(input.begin(), input.begin() + cursor_pos + 1, re, -1),
std::sregex_token_iterator(),
std::back_inserter(result)
);
return result;
}
std::vector<std::string> get_lines(const std::string& input)
{
std::vector<std::string> lines;
std::regex re("\\n");
std::copy(
std::sregex_token_iterator(input.begin(), input.end(), re, -1),
std::sregex_token_iterator(),
std::back_inserter(lines)
);
return lines;
}
std::vector<std::string> split_from_includes(const std::string& input)
{
// this function split the input into part where we have only #include.
// split input into lines
std::vector<std::string> lines = get_lines(input);
// check if each line contains #include and concatenate the result in the good part of the result
std::regex incl_re("\\#include.*");
std::regex magic_re("^\\%\\w+");
std::vector<std::string> result;
result.push_back("");
std::size_t current = 0; // 0 include, 1 other
std::size_t rindex = 0; // current index of result vector
for (std::size_t i = 0; i < lines.size(); ++i)
{
if (!lines[i].empty())
{
if (std::regex_search(lines[i], magic_re))
{
result.push_back(lines[i] + "\n");
result.push_back("");
rindex += 2;
}
else
{
if (std::regex_match(lines[i], incl_re))
{
// if we have #include in this line
// but the current item of result vector contains
// other things
if (current != 0)
{
current = 0;
result.push_back("");
rindex++;
}
}
else
{
// if we don't have #include in this line
// but the current item of result vector contains
// the include parts
if (current != 1)
{
current = 1;
result.push_back("");
rindex++;
}
}
// if we have multiple lines, we add a semicolon at the end of the lines that not contain
// #include keyword (except for the last line)
result[rindex] += lines[i];
if (i != lines.size() - 1)
{
result[rindex] += "\n";
}
}
}
}
return result;
}
}