LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
XmlSyntagmaticMatrixFileReader.cpp
Go to the documentation of this file.
1// Copyright 2002-2022 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
12// ---------------------------------------------------------------------------
13// Includes
14// ---------------------------------------------------------------------------
18
20
21#include <QXmlStreamReader>
22
23#include<boost/tokenizer.hpp>
24
25#include <sstream>
26#include <iostream>
27
28using namespace std;
29
30using namespace Lima::Common::Misc;
31using namespace Lima::Common::MediaticData;
33
34namespace Lima {
35namespace LinguisticProcessing {
36namespace SyntacticAnalysis {
37
39{
41public:
42 // -----------------------------------------------------------------------
43 // Constructors
44 // -----------------------------------------------------------------------
45 XmlSyntagmaticMatrixFileReaderPrivate(SyntagmDefStruct& theMatrices, MediaId language);
47
48 bool parse(QIODevice *device);
50 void readChain();
51 void readFilter();
52 void readName();
53 void readAttribute();
54 void readCategory();
55 void readMatrix();
56 void readLine();
57 void readSucc();
58 void readBeginnings();
59 void readEndings();
60
61 QString errorString() const;
62
63 QXmlStreamReader m_reader;
68
70 std::map< Common::MediaticData::ChainsType, std::map< std::string, TokenFilter > > m_tokenFilters;
71
72 std::string m_currentElement;
73 std::string m_currentFilterId;
75 std::set< StringsPoolIndex > m_currentFilterAttributes;
76 std::set< LinguisticCode > m_currentFilterCategories;
80 MediaId m_language;
81};
82
83// ---------------------------------------------------------------------------
84// XMLSyntagmaticMatrixFileHandler: Constructors and Destructor
85// ---------------------------------------------------------------------------
87 MediaId language) :
88 m_matrices(matrices),
89 m_language(language)
90{
91}
92
97
99{
100 return m_d->parse(device);
101}
102
103// <?xml version="1.0" encoding="UTF-8" ?>
104// <!DOCTYPE matrice_precedence SYSTEM "recochaines.dtd">
105// <matrice_precedence>
106// …
107// </matrice_precedence>
109{
111 LTRACE << "parse";
112 m_reader.setDevice(device);
113 if (m_reader.readNextStartElement())
114 {
115 if (m_reader.name() == QLatin1String("matrice_precedence"))
116 {
118 }
119 else
120 {
121 m_reader.raiseError(QObject::tr("The file is not a LIMA XML precedence matrix file."));
122 }
123 }
124 return !m_reader.error();
125}
126
127// <matrice_precedence>
128// <chaine type="nominale">
129// …
130// </chaine>
131// <matrice type="nominale">
132// …
133// </matrice>
134// …
135// </matrice_precedence>
137{
138 SALOGINIT;
139 LTRACE << "readPrecedenceMatrix";
140 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("matrice_precedence"));
141
142 while (m_reader.readNextStartElement())
143 {
144 if (m_reader.name() == QLatin1String("chaine"))
145 readChain();
146 else if (m_reader.name() == QLatin1String("matrice"))
147 readMatrix();
148 else
149 m_reader.raiseError(QObject::tr("Expected a chaine or matrice but got a %1.").arg(m_reader.name()));
150 }
151}
152
153// <chaine type="nominale">
154// <filtre ID="FN1">
155// …
156// </filtre>
157// …
158// </chaine>
160{
161 SALOGINIT;
162 LTRACE << "readChain";
163 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("chaine"));
164
165 std::string currentChainType = (m_reader.attributes().value("type")).toUtf8().data();
166 if (currentChainType == "nominale") m_currentChainType = NOMINAL;
167 else if (currentChainType == "verbale") m_currentChainType = VERBAL;
169// std::cerr << m_currentChainType << std::endl;
170 while (m_reader.readNextStartElement())
171 {
172 if (m_reader.name() == QLatin1String("filtre"))
173 readFilter();
174 else
175 m_reader.raiseError(QObject::tr("Expected a filtre but got a %1.").arg(m_reader.name()));
176 }
179}
180
181// <filtre ID="FN1">
182// <nom>DET-ART-CON</nom>
183// <categorie>DETDES</categorie>
184// …
185// <attribut>…</categorie>
186// …
187// </filtre>
189{
190 SALOGINIT;
191 LTRACE << "readChain";
192 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("filtre"));
193
194 m_currentFilterId = (m_reader.attributes().value("ID")).toUtf8().data();
195 m_currentFilterAttributes = std::set< StringsPoolIndex >();
196 m_currentFilterCategories = std::set< LinguisticCode >();
197// std::cerr << m_currentFilterId << std::endl;
198 while (m_reader.readNextStartElement())
199 {
200 if (m_reader.name() == QLatin1String("nom"))
201 readName();
202 else if (m_reader.name() == QLatin1String("categorie"))
203 readCategory();
204 else if (m_reader.name() == QLatin1String("attribut"))
206 else
207 m_reader.raiseError(QObject::tr("Expected a nom, a categorie or a attribut but got a %1.").arg(m_reader.name()));
208 }
210// std::cerr << "New Filter is: " << *filter << std::endl;
214 m_currentFilterAttributes = std::set< StringsPoolIndex >();
215 m_currentFilterCategories = std::set< LinguisticCode >();
216}
217
218// <nom>DET-ART-CON</nom>
220{
221 SALOGINIT;
222 LTRACE << "readChain";
223 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("nom"));
224// <!ELEMENT nom (#PCDATA ) >
225 m_currentFilterName = m_reader.readElementText().toStdString();
226// std::cerr << "Current filter name is: " << m_currentFilterName << std::endl;
227}
228
229// <attribut>…</attribut>
231{
232 SALOGINIT;
233 LTRACE << "readChain";
234 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("attribut"));
235
236// <!ELEMENT attribut (#PCDATA ) >
237
239 m_reader.readElementText()]);
240}
241
242// <categorie>DETDES</categorie>
244{
245 SALOGINIT;
246 LTRACE << "readChain";
247 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("categorie"));
248
249// <!ELEMENT categorie (#PCDATA ) >
250
251 LinguisticCode filterCategory;
252 auto text = m_reader.readElementText();
253 if (text[0].isDigit())
254 {
255 filterCategory = LinguisticCode::fromString(text.toStdString());
256 }
257 else
258 {
259 filterCategory = static_cast<const Common::MediaticData::LanguageData&>(
260 MediaticData::single().mediaData(m_matrices.language())).getPropertyCodeManager()
261 .getPropertyManager("MICRO").getPropertyValue(text.toStdString());
262 }
263 m_currentFilterCategories.insert(filterCategory);
264// std::cerr << "Current category is: " << filterCategory << std::endl;
265}
266
267// <matrice type="nominale">
268// <ligne REF="FN1">
269// <succ REF="FN3 FN8 FN12 FN13 PREF"/>
270// </ligne>
271// …
272// <debuts REF="FV1 FV4 FV5 FV6 FV8 FV9 FV11 FV12 FV13 FV14 FV17 FV18 FV19 FV20 FV22 FV23 FV26 FV31 FV34"/>
273// …
274// <fins REF="FV1 FV2 FV4 FV5 FV6 FV8 FV9 FV10 FV15 FV19 FV21 FV24 FV28 FV29 FV30 FV33"/>
275// …
276// </matrice>
278{
279 SALOGINIT;
280 LTRACE << "readChain";
281 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("matrice"));
282
283 auto currentMatrixType = m_reader.attributes().value("type").toString();
284 if (currentMatrixType == "nominale") m_currentMatrixType = NOMINAL;
285 else if (currentMatrixType == "verbale") m_currentMatrixType = VERBAL;
287
288 while (m_reader.readNextStartElement())
289 {
290 if (m_reader.name() == QLatin1String("ligne"))
291 readLine();
292 else if (m_reader.name() == QLatin1String("debuts"))
294 else if (m_reader.name() == QLatin1String("fins"))
295 readEndings();
296 else
297 m_reader.raiseError(QObject::tr("Expected a ligne, a debuts or a fins but got a %1.").arg(m_reader.name()));
298 }
300}
301
302// <ligne REF="FN1">
303// <succ REF="FN3 FN8 FN12 FN13 PREF"/>
304// </ligne>
306{
307 SALOGINIT;
308 LTRACE << "readChain";
309 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("ligne"));
310
311 m_currentMatrixLineId = m_reader.attributes().value("REF").toUtf8().data();
312 while (m_reader.readNextStartElement())
313 {
314 if (m_reader.name() == QLatin1String("succ"))
315 readSucc();
316 else
317 m_reader.raiseError(QObject::tr("Expected a succ but got a %1.").arg(m_reader.name()));
318 }
319}
320
321// <succ REF="FN3 FN8 FN12 FN13 PREF"/>
323{
324 SALOGINIT;
325 LTRACE << "readChain";
326 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("succ"));
327// std::cerr << "Creating new succ for " << m_currentMatrixLineId << " (" << m_currentMatrixType << ")" << std::endl;
328 using namespace boost;
329 std::string successorsStr = (m_reader.attributes().value("REF")).toUtf8().data();
330 std::set< std::string > successors;
331
332 tokenizer<> tok(successorsStr);
333 copy(tok.begin(), tok.end(),
334 std::insert_iterator< std::set< std::string > >(successors, successors.end()));
335
337 std::set< std::string >::iterator it = successors.begin();
338 for (; it != successors.end(); it++)
339 {
340// std::cerr << "Inserting " << (*it) << " / " << *(m_tokenFilters[m_currentMatrixType][(*it)]) << " in row " << std::endl;
341 row.m_filters.insert(m_tokenFilters[m_currentMatrixType][(*it)]);
342 }
343// std::cerr << "New row is " << row << std::endl;
345// std::cerr << "Filter is " << filter << std::endl;
347 m_matrices.nominal().filters().insert(std::make_pair(filter, row));
348 else if (m_currentMatrixType == VERBAL)
349 m_matrices.verbal().filters().insert(std::make_pair(filter, row));
350 m_reader.skipCurrentElement();
351}
352
353// <debuts REF="FV1 FV4 FV5 FV6 FV8 FV9 FV11 FV12 FV13 FV14 FV17 FV18 FV19 FV20 FV22 FV23 FV26 FV31 FV34"/>
355{
356 SALOGINIT;
357 LTRACE << "readChain";
358 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("debuts"));
359 using namespace boost;
360 std::string beginningsStr = (m_reader.attributes().value("REF")).toUtf8().data();
361 std::set< std::string > beginnings;
362
363 tokenizer<> tok(beginningsStr);
364 copy(tok.begin(), tok.end(),
365 std::insert_iterator< std::set< std::string > >(beginnings, beginnings.end()));
366
368 std::set< std::string >::iterator it = beginnings.begin();
369 for (; it != beginnings.end(); it++)
370 {
371 row.m_filters.insert(m_tokenFilters[m_currentMatrixType][(*it)]);
372 }
374 {
375 m_matrices.nominalBegin() = row;
376// std::cerr << "New debuts is " << m_matrices.nominalBegin() << std::endl;
377 }
378 else if (m_currentMatrixType == VERBAL)
379 {
380 m_matrices.verbalBegin() = row;
381// std::cerr << "New debuts is " << m_matrices.verbalBegin() << std::endl;
382 }
383 m_reader.skipCurrentElement();
384}
385
386// <fins REF="FV1 FV2 FV4 FV5 FV6 FV8 FV9 FV10 FV15 FV19 FV21 FV24 FV28 FV29 FV30 FV33"/>
388{
389 SALOGINIT;
390 LTRACE << "readChain";
391 Q_ASSERT(m_reader.isStartElement() && m_reader.name() == QLatin1String("fins"));
392// std::cerr << "Creating new fins" << std::endl;
393 using namespace boost;
394 std::string endingsStr = (m_reader.attributes().value("REF")).toUtf8().data();
395 std::set< std::string > endings;
396
397 tokenizer<> tok(endingsStr);
398 copy(tok.begin(), tok.end(),
399 std::insert_iterator< std::set< std::string > >(endings, endings.end()));
400
402 std::set< std::string >::iterator it = endings.begin();
403 for (; it != endings.end(); it++)
404 {
405 row.m_filters.insert(m_tokenFilters[m_currentMatrixType][(*it)]);
406 }
407// std::cerr << "New fins is " << row << std::endl;
409 m_matrices.nominalEnd() = row;
410 else if (m_currentMatrixType == VERBAL)
411 m_matrices.verbalEnd() = row;
412 m_reader.skipCurrentElement();
413}
414
416{
418 auto errorStr = QObject::tr("%1, Line %2, column %3")
419 .arg(m_d->m_reader.errorString())
420 .arg(m_d->m_reader.lineNumber())
421 .arg(m_d->m_reader.columnNumber());
422 LERROR << errorStr;
423 return errorStr;
424}
425
426} // closing namespace SyntacticAnalysis
427} // closing namespace LinguisticProcessing
428} // closing namespace Lima
#define XMLCFGLOGINIT
Definition LimaCommon.h:217
#define LTRACE
Definition LimaCommon.h:156
#define LERROR
Definition LimaCommon.h:161
#define SALOGINIT
Holds linguistic data for one language.
static LinguisticCode fromString(const std::string &str)
Definition StdBitset.h:89
std::map< Common::MediaticData::ChainsType, std::map< std::string, TokenFilter > > m_tokenFilters
This map stores the associations between the filters and their IDs.
static MediaticData & changeable()
singleton accessor
Definition Singleton.h:71
ChainsType
syntactic chains type
NAUTITIA.
STL namespace.