LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
constraint.cpp
Go to the documentation of this file.
1// Copyright 2002-2013 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6/************************************************************************
7*
8* File : constraint.cpp
9* Author : Besancon Romaric (besanconr@zoe.cea.fr)
10* Created on : Tue Nov 26 2002
11* Copyright : (c) 2002 by CEA
12* Version : $Id$
13*
14************************************************************************/
15
16#include "constraint.h"
18#include "transitionUnit.h"
22#include <iostream>
23
24using namespace std;
26
27namespace Lima {
28namespace LinguisticProcessing {
29namespace Automaton {
30
31/***********************************************************************/
32// defines
33/***********************************************************************/
34//internal text format of constraints
35#define CHAR_SEP_CONSTRAINT_INTERNAL '/'
36#define CHAR_BEGIN_CONSTRAINT_INTERNAL '+'
37#define CHAR_NEGATIVE_CONSTRAINT_INTERNAL '!'
38
39/***********************************************************************/
40// constructors
41/***********************************************************************/
43m_index(0),
44m_functionAddr(0),
45m_action(NONE),
46m_negative(false)
47{
48}
49
50Constraint::Constraint(const uint64_t i,
51 const std::string& functionName,
52 const ConstraintAction a,
53 MediaId language,
54 const LimaString& complement,
55 const bool negative):
56m_index(i),
57m_functionAddr(0),
58m_action(a),
59m_negative(negative)
60{
62 getConstraintFunction(functionName,language,complement);
63}
64
66m_index(c.m_index),
67m_functionAddr(c.m_functionAddr),
68m_action(c.m_action),
69m_negative(c.m_negative)
70{
71}
72
73/***********************************************************************/
74// destructor
75/***********************************************************************/
77
79 m_index=0;
80 m_functionAddr=0;
81 m_action=NONE;
82 m_negative=false;
83}
84
85/***********************************************************************/
86// copy
87/***********************************************************************/
89 if (this != &c) {
90 m_index = c.index();
91 m_functionAddr = c.m_functionAddr;
92 m_action = c.m_action;
93 m_negative = c.m_negative;
94 }
95 return (*this);
96}
97
98std::string Constraint::functionName() const {
99 string functionName;
100 LimaString complement;
101
103 getFunctionName(m_functionAddr,
105 complement)) {
106 return functionName;
107 }
108 else {
109 AULOGINIT;
110 LERROR << "constraint function "
111 << m_functionAddr << " not available";
112 return "";
113 }
114}
115
116/***********************************************************************/
117// check constraint according to a checklist
118/***********************************************************************/
120checkConstraint(const AnalysisGraph& graph,
121 const LinguisticGraphVertex& vertex,
122 AnalysisContent& analysis,
123 ConstraintCheckList& constraintCheckList) const
124{
125/*
126 Critical Function : comment logging message
127*/
128// AULOGINIT;
129
130 // if the action is STORE, store the value in the checklist,
131 // else compare the value with the value stored in the checklist
132 // using the constraint function
133
134// LDEBUG << checkStringDebug(graph,vertex);
135
136 bool success(false);
137 bool compare(false);
139 firstVertex(0),
140 secondVertex(vertex);
141
142 // first get the value from the token
143 switch(m_action) {
144 case STORE: {
145 constraintCheckList[m_index].store(vertex);
146 return true;
147 }
148 case PUSH: {
149 constraintCheckList[m_index].push(vertex);
150 return true;
151 }
152 case COMPARE: {
153 firstVertex=constraintCheckList[m_index].getValueStored();
154 compare=true;
155 break;
156 }
157 case COMPARE_REVERSE: {
158 // same but reverse order of arguments
159 firstVertex=vertex;
160 secondVertex=constraintCheckList[m_index].getValueStored();
161 compare=true;
162 break;
163 }
164 case COMPARE_STACK: {
165 firstVertex=constraintCheckList[m_index].getValueStack();
166 compare=true;
167 break;
168 }
170 // same but reverse order of arguments
171 firstVertex=vertex;
172 secondVertex=constraintCheckList[m_index].getValueStack();
173 compare=true;
174 break;
175 }
176 case TEST: {
177 success=(*m_functionAddr)(graph,vertex,analysis);
178 break;
179 }
184 AULOGINIT;
185 LERROR << "Constraint: cannot call checkConstraint with EXECUTE type"
186 << "(function " << functionName() << ")";
187 return false;
188 }
189 default: {
190 AULOGINIT;
191 LERROR << "Constraint: no action specified "
192 << "(function " << functionName() << ")";
193 return false;
194 }
195 }
196
197 if (compare) {
198 if (firstVertex == ConstraintCheckListElement::novalue ||
199 secondVertex == ConstraintCheckListElement::novalue) {
200 success=false;
201 }
202 else {
203 success=(*m_functionAddr)(graph,firstVertex,secondVertex,analysis);
204 }
205 }
206
207// LDEBUG << " -> " << success << " => "
208// << (m_negative?(!success):success) ;
209 return (m_negative?(!success):success);
210}
211
213 AnalysisContent& analysis,
214 ConstraintCheckList& constraintCheckList,
215 const bool success,
216 RecognizerMatch* result) const
217{
218/*
219 Critical function : comment logging messages
220*/
221// bool reverse(false);
222 switch (m_action) {
223 case EXECUTE_IF_FAILURE: {
224 if (success) { return true; } // not applied but normal behaviour
225 break;
226 }
228 if (success) { return true; }
229// reverse=true;
230 break;
231 }
232 case EXECUTE_IF_SUCCESS: {
233 if (! success) { return true; }
234 break;
235 }
237 if (! success) { return true; }
238// reverse=true;
239 break;
240 }
241 default: {
242 AULOGINIT;
243 LERROR << "cannot apply an action if not type EXECUTE "
244 << "(function " << functionName()
245 << ")";
246 return false;
247 }
248 }
249
250// AULOGINIT;
251// LDEBUG << "case passed";
252 bool res(false);
253 if (m_index==Constraint::noindex) { // no argument
254// LDEBUG << applyStringDebug();
255
256 if ((*m_functionAddr).actionNeedsRecognizedExpression()) {
257 res=(*m_functionAddr)(*result,analysis);
258 }
259 else {
260 res=(*m_functionAddr)(analysis);
261 }
262 }
263 else {
264 LinguisticGraphVertex firstArg=
265 constraintCheckList[m_index].getValueStack();
266
267 if (firstArg == ConstraintCheckListElement::novalue) {
268// LDEBUG << "Action: first argument is not set";
269 res=false;
270 }
271 else {
272 constraintCheckList[m_index].pop();
273 if (constraintCheckList[m_index].empty()) { // only one argument
274// LDEBUG << applyStringDebug(firstArg);
275 res=(*m_functionAddr)(graph,
276 firstArg,
277 analysis);
278 }
279 else {
280 LinguisticGraphVertex secondArg=
281 constraintCheckList[m_index].getValueStack();
282
283 if (secondArg == ConstraintCheckListElement::novalue) {
284// LDEBUG << "Action: second argument is not set";
285 res=false;
286 }
287 else {
288// LDEBUG << applyStringDebug(firstArg,secondArg);
289 res=(*m_functionAddr)(graph,
290 firstArg,
291 secondArg,
292 analysis);
293 }
294 }
295 }
296 }
297 //LDEBUG << " -> " << res << " => " << (m_negative?(!res):res) ;
298 return (m_negative?(!res):res);
299}
300
301/***********************************************************************/
302// equality test between constraints
303/***********************************************************************/
304bool operator == (const Constraint& c1,const Constraint& c2) {
305 if (c1.m_index != c2.m_index) { return false; }
306 if (c1.m_functionAddr != c2.m_functionAddr) { return false; }
307 if (c1.m_action != c2.m_action) { return false; }
308 if (c1.m_negative != c2.m_negative) { return false; }
309 return true;
310}
311
312/***********************************************************************/
313// output
314/***********************************************************************/
316 string functionName;
317 LimaString complement;
319 getFunctionName(m_functionAddr,
321 complement)) {
322 AULOGINIT;
323 LERROR << "constraint function "
324 << m_functionAddr << " not availale";
325 }
326
327 ostringstream oss;
328 oss << (unsigned char)CHAR_BEGIN_CONSTRAINT_INTERNAL << m_index
329 << (unsigned char)CHAR_SEP_CONSTRAINT_INTERNAL
330 << static_cast<uint64_t>(m_action)
331 << (unsigned char)CHAR_SEP_CONSTRAINT_INTERNAL;
332 if (m_negative) {
334 }
335 oss << functionName;
336 if (! complement.isEmpty()) {
337 oss << (unsigned char)CHAR_SEP_CONSTRAINT_INTERNAL
339 }
341}
342
343std::string Constraint::
344checkStringDebug(const AnalysisGraph& graph,
345 const LinguisticGraphVertex vertex) const {
346 string functionName;
347 LimaString complement;
348
350 getFunctionName(m_functionAddr,
352 complement)) {
353 AULOGINIT;
354 LERROR << "constraint function "
355 << m_functionAddr << " not availale";
356 }
357
358 ostringstream oss;
359 oss << "Constraint:" << actionString()
360 << " vertex " << vertex
361 << " (" << Common::Misc::limastring2utf8stdstring((get(vertex_token,*(graph.getGraph()),vertex))->stringForm()) << ")"
362 << " in constraint " << m_index
363 << ",compl="
365 << "\", using function " << functionName;
366 return oss.str();
367}
368
369std::string Constraint::
370applyStringDebug(const LinguisticGraphVertex firstArg,
371 const LinguisticGraphVertex secondArg) const {
372 string functionName;
373 LimaString complement;
374
376 getFunctionName(m_functionAddr,
378 complement)) {
379 AULOGINIT;
380 LERROR << "constraint function "
381 << m_functionAddr << " not availale";
382 }
383
384 ostringstream oss;
385 oss << "Constraint: executing action "
386 << functionName ;
387 if (firstArg!=0 && secondArg!=0) {
388 oss << " on vertices "<< firstArg
389 << "," << secondArg;
390 }
391 else if (firstArg!=0) {
392 oss << " on vertex " << firstArg;
393 }
394 else {
395 oss << " (no args)";
396 }
397 oss << " with complement=" << Common::Misc::limastring2utf8stdstring(complement);
398 return oss.str();
399}
400
401std::string Constraint::
402actionString() const {
403 switch(m_action) {
404 case NONE: return "NONE";
405 case STORE: return "STORE";
406 case COMPARE: return "COMPARE";
407 case PUSH: return "PUSH";
408 case COMPARE_STACK: return "COMPARE_STACK";
409 case TEST: return "TEST";
410 case COMPARE_REVERSE: return "COMPARE_REVERSE";
411 case COMPARE_STACK_REVERSE: return "COMPARE_STACK_REVERSE";
412 case PUSH_EXECUTE: return "PUSH_EXECUTE";
413 case EXECUTE_IF_SUCCESS: return "EXECUTE_IF_SUCCESS";
414 case EXECUTE_IF_SUCCESS_REVERSE: return "EXECUTE_IF_SUCCESS_REVERSE";
415 case EXECUTE_IF_FAILURE: return "EXECUTE_IF_FAILURE";
416 case EXECUTE_IF_FAILURE_REVERSE: return "EXECUTE_IF_FAILURE_REVERSE";
417 }
418 return "UNKNOWN_ACTION";
419}
420
421
422ostream& operator << (ostream& os, const Constraint& c) {
423 string functionName;
424 LimaString complement;
426 getFunctionName(c.m_functionAddr,
427 functionName,
428 complement)) {
429 AULOGINIT;
430 LERROR << "constraint function "
431 << c.m_functionAddr << " not availale";
432 }
433 switch (c.action()) {
435 case EXECUTE_IF_SUCCESS_REVERSE: os << "=>"; break;
437 case EXECUTE_IF_FAILURE_REVERSE: os << "=<"; break;
438 default: os << "+"; break;
439 }
440 if (c.index() == Constraint::noindex) {
441 os << "[";
442 }
443 else {
444 os << "[" << c.index()<< ",";
445 }
446 if (c.m_negative) {
447 os << "!";
448 }
449 os << functionName << "," << c.actionString();
450 if (! complement.isEmpty()) {
451 os << "," << Common::Misc::limastring2utf8stdstring(complement);
452 }
453 os << "]";
454 return os;
455}
456
457QDebug& operator << (QDebug& os, const Constraint& c) {
458 string functionName;
459 LimaString complement;
460 if (! ConstraintFunctionManager::single().getFunctionName(c.m_functionAddr,
461 functionName,
462 complement))
463 {
464 AULOGINIT;
465 LERROR << "constraint function "
466 << c.m_functionAddr << " not availale";
467 }
468 switch (c.action()) {
470 case EXECUTE_IF_SUCCESS_REVERSE: os << "=>"; break;
472 case EXECUTE_IF_FAILURE_REVERSE: os << "=<"; break;
473 default: os << "+"; break;
474 }
475 if (c.index() == Constraint::noindex) {
476 os << "[";
477 }
478 else {
479 os << "[" << c.index()<< ",";
480 }
481 if (c.m_negative)
482 {
483 os << "!";
484 }
485 os << functionName << "," << c.actionString();
486 if (! complement.isEmpty()) {
487 os << "," << Common::Misc::limastring2utf8stdstring(complement);
488 }
489 os << "]";
490 return os;
491}
492
493} // end namespace
494} // end namespace
495} // end namespace
#define LERROR
Definition LimaCommon.h:161
@ vertex_token
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
#define AULOGINIT
Holds all data that pass through the ProcessUnits Analysis data are shared pointers,...
Constraint & operator=(const Constraint &)
bool apply(const LinguisticAnalysisStructure::AnalysisGraph &graph, AnalysisContent &analysis, ConstraintCheckList &constraintCheckList, const bool success, RecognizerMatch *result) const
apply an action (only for EXECUTE type of action)
bool checkConstraint(const LinguisticAnalysisStructure::AnalysisGraph &graph, const LinguisticGraphVertex &vertex, AnalysisContent &analysis, ConstraintCheckList &constraintCheckList) const
check a constraint
An AnalysisData containing a LinguisticGraph with a language and an id.
const LinguisticGraph * getGraph(void) const
Returns the underlying graph structure.
static const ConstraintFunctionManager & single()
const singleton accessor
Definition Singleton.h:51
static ConstraintFunctionManager & changeable()
singleton accessor
Definition Singleton.h:71
#define CHAR_BEGIN_CONSTRAINT_INTERNAL
#define CHAR_NEGATIVE_CONSTRAINT_INTERNAL
#define CHAR_SEP_CONSTRAINT_INTERNAL
std::string limastring2utf8stdstring(const Lima::LimaString &phrase, uint32_t size0)
Convert a wide string to a string , in dest up to size bytes.
LimaString utf8stdstring2limastring(const std::string &src)
std::ostream & operator<<(std::ostream &os, const DFFSPos &x)
bool operator==(const Constraint &c1, const Constraint &c2)
std::vector< ConstraintCheckListElement > ConstraintCheckList
NAUTITIA.
QString LimaString
Definition LimaString.h:33
STL namespace.