LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
line.cpp
Go to the documentation of this file.
1// Copyright 2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#include <sstream>
7#include <iostream>
8#include <limits>
9
10#include "line.h"
11
12using namespace std;
13
14namespace deeplima
15{
16namespace CoNLLU
17{
18#define RESERVE_FIELDS 16
19
20void Line::read(const std::string& buf, char sep)
21{
22 reserve(RESERVE_FIELDS);
23 size_t eol_pos = buf.find_first_of("\r\n");
24 size_t pos = 0, sep_pos = buf.find(sep, pos+1);
25
26 while (string::npos != sep_pos)
27 {
28 push_back(buf.substr(pos, sep_pos - pos));
29 pos = sep_pos + 1;
30 sep_pos = buf.find(sep, pos);
31 }
32
33 sep_pos = eol_pos;
34 push_back(buf.substr(pos, sep_pos - pos));
35}
36
37string Line::write(char sep) const
38{
39 string rv;
40
41 for (auto s : *this)
42 {
43 if (rv.size() > 0)
44 {
45 rv = rv + sep;
46 }
47 rv += s;
48 }
49
50 return rv;
51}
52
53string CoNLLULine::write(char sep) const
54{
55 if (is_empty_line())
56 {
57 return "";
58 }
59
60 if (is_comment_line())
61 {
62 return _comment;
63 }
64
65 Line l;
66 l.resize(10);
67
68 l[0] = _idx.serialize();
69 l[1] = serialize_string(_form);
71 l[3] = serialize_string(_upos);
72 l[4] = serialize_string(_xpos);
73 l[5] = serialize_feats();
74 l[6] = (std::numeric_limits<idx_t::base_int_t>::max() == _head._first) ? "_" : _head.serialize();
76 l[8] = serialize_deps();
77 l[9] = serialize_misc();
78
79 return l.write(sep);
80}
81
82void CoNLLULine::init_impl(const Line& line)
83{
84 // 1. ID
85 if (!_idx.parse(line[0]))
86 {
87 throw logic_error("Can't parse ID field \"" + line[0] + "\" in line \"" + line.write() + "\"");
88 }
89
90 // 2. FORM
91 if (!parse_string_field(line[1], _form, true))
92 {
93 throw logic_error("Can't parse FORM field \"" + line[1] + "\" in line \"" + line.write() + "\"");
94 }
95
96 // 3. LEMMA
97 if (!parse_string_field(line[2], _lemma))
98 {
99 throw logic_error("Can't parse LEMMA field \"" + line[2] + "\" in line \"" + line.write() + "\"");
100 }
101
102 // 4. UPOS
103 if (!parse_string_field(line[3], _upos))
104 {
105 throw logic_error("Can't parse UPOS field \"" + line[3] + "\" in line \"" + line.write() + "\"");
106 }
107
108 // 5. XPOS
109 if (!parse_string_field(line[4], _xpos))
110 {
111 throw logic_error("Can't parse XPOS field \"" + line[4] + "\" in line \"" + line.write() + "\"");
112 }
113
114 // 6. FEATS
115 if (!parse_feats(line[5]))
116 {
117 throw logic_error("Can't parse FEATS field \"" + line[5] + "\" in line \"" + line.write() + "\"");
118 }
119
120 // 7. HEAD
121 _head = (line[6] == "_") ? idx_t(std::numeric_limits<idx_t::base_int_t>::max()) : idx_t(line[6]);
122
123 // 8. DEPREL
124 if (!parse_string_field(line[7], _deprel)) // TODO: check result and remaining part of the string
125 {
126 throw logic_error("Can't parse DEPREL field \"" + line[7] + "\" in line \"" + line.write() + "\"");
127 }
128
129 // 9. DEPS
130 if (!parse_deps(line[8]))
131 {
132 throw logic_error("Can't parse DEPS field \"" + line[8] + "\" in line \"" + line.write() + "\"");
133 }
134
135 // 10. MISC
136 if (!parse_misc(line[9]))
137 {
138 throw logic_error("Can't parse MISC field \"" + line[9] + "\" in line \"" + line.write() + "\"");
139 }
140}
141
142bool CoNLLULine::parse_feats(const std::string& s, std::map<std::string, std::set<std::string>>& _feats)
143{
144 if ("_" == s)
145 {
146 return true;
147 }
148
149 Line l(s, '|');
150
151 for (const string& f : l)
152 {
153 size_t pos = f.find('=');
154 if (string::npos == pos)
155 {
156 throw logic_error("Wrong format of FEAT field: \"" + s + "\"");
157 }
158
159 string k = f.substr(0, pos);
160 string v = f.substr(pos + 1);
161 _feats[k].insert(v);
162 }
163
164 return true;
165}
166
167bool CoNLLULine::parse_feats(const std::string& s)
168{
169 return parse_feats(s, _feats);
170}
171
172bool CoNLLULine::parse_deps(const std::string& s)
173{
174 if ("_" == s)
175 {
176 return true;
177 }
178
179 Line l(s, '|');
180
181 for (const string& f : l)
182 {
183 size_t pos = f.find(':');
184 if (string::npos == pos)
185 {
186 throw logic_error("Wrong format of DEPS field: \"" + s + "\"");
187 }
188
189 idx_t head;
190 head.parse(f.substr(0, pos));
191 string deprel = f.substr(pos + 1);
192 _deps.push_back(dep_t(head, deprel));
193 }
194
195 return true;
196}
197
198bool CoNLLULine::parse_misc(const std::string& s)
199{
200 if ("_" == s)
201 {
202 return true;
203 }
204
205 Line l(s, '|');
206
207 for (const string& f : l)
208 {
209 if ("_" == f)
210 {
211 _misc["_"] = ""; // TODO: I don't understand what does it mean.
212 // Happens in en_ewt-ud-train.conllu
213 }
214 else
215 {
216 size_t pos = f.find('=');
217 if (string::npos == pos)
218 {
219 pos = f.find(':');
220 if (string::npos == pos)
221 {
222 //throw logic_error("Wrong format of MISC field: \"" + s + "\"");
223 std::cerr << "Wrong format of MISC field: \"" << s << "\"" << std::endl;
224 }
225 }
226
227 string k = f.substr(0, pos);
228 string v = f.substr(pos + 1);
229 _misc[k] = v;
230 }
231 }
232
233 return true;
234}
235
236bool CoNLLULine::parse_string_field(const string& s, string& out, bool raw)
237{
238 if (!raw && "_" == s)
239 {
240 out = "";
241 }
242 else
243 {
244 out = s;
245 }
246
247 return true;
248}
249
251{
252 if (_feats.size() == 0)
253 {
254 return "_";
255 }
256
257 Line l;
258 l.reserve(_feats.size());
259
260 for (auto& kv : _feats)
261 {
262 l.push_back(feature_t(kv.first, kv.second).serialize());
263 }
264
265 return l.write('|');
266}
267
269{
270 if (_deps.size() == 0)
271 {
272 return "_";
273 }
274
275 Line l;
276 l.reserve(_deps.size());
277
278 for (auto& d : _deps)
279 {
280 l.push_back(d.serialize());
281 }
282
283 return l.write('|');
284}
285
287{
288 if (_misc.size() == 0)
289 {
290 return "_";
291 }
292
293 Line l;
294 l.reserve(_misc.size());
295
296 for (auto& kv : _misc)
297 {
298 l.push_back(feature_t(kv.first, kv.second).serialize());
299 }
300
301 return l.write('|');
302}
303
304string CoNLLULine::serialize_string(const string& s) const
305{
306 if (s.size() == 0)
307 {
308 return "_";
309 }
310
311 return s;
312}
313
315{
316 if ("_" == _key)
317 {
318 return "_";
319 }
320
321 string serialized_values;
322
323 for (auto& s : _values)
324 {
325 if (serialized_values.size() > 0)
326 {
327 serialized_values += string(",");
328 }
329
330 serialized_values += s;
331 }
332
333 return _key + "=" + serialized_values;
334}
335
337{
338 return _head.serialize() + ":" + _deprel;
339}
340
341} // namespace CoNLLU
342} // namespace deeplima
343
bool parse_deps(const std::string &s)
Definition line.cpp:172
bool is_empty_line() const
Definition line.h:138
std::string serialize_string(const std::string &s) const
Definition line.cpp:304
std::map< std::string, std::string > _misc
Definition line.h:280
std::vector< dep_t > _deps
Definition line.h:277
const idx_t & head() const
Definition line.h:188
const std::string & deprel() const
Definition line.h:173
virtual std::string write(char sep='\t') const
Definition line.cpp:53
bool is_comment_line() const
Definition line.h:133
bool parse_misc(const std::string &s)
Definition line.cpp:198
bool parse_string_field(const std::string &s, std::string &out, bool raw=false)
Definition line.cpp:236
std::string serialize_misc() const
Definition line.cpp:286
std::string serialize_feats() const
Definition line.cpp:250
std::map< std::string, std::set< std::string > > _feats
Definition line.h:268
void init_impl(const Line &line)
Definition line.cpp:82
static bool parse_feats(const std::string &s, std::map< std::string, std::set< std::string > > &_feats)
Definition line.cpp:142
std::string serialize_deps() const
Definition line.cpp:268
virtual void read(const std::string &buf, char sep='\t')
Definition line.cpp:20
virtual std::string write(char sep='\t') const
Definition line.cpp:37
#define RESERVE_FIELDS
Definition line.cpp:18
STL namespace.
std::string serialize() const
Definition line.cpp:336
std::set< std::string > _values
Definition line.h:112
base_int_t _first
Definition line.h:30
bool parse(const std::string &s)
Definition treebank.cpp:385
std::string serialize() const
Definition treebank.cpp:420