Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 40333702 authored by Volker Krause's avatar Volker Krause

Implement <break> rule to allow interrupting iterations

parent c66a96ae
......@@ -58,7 +58,7 @@ static bool isEmptyObject(const QJsonObject &obj)
return obj.size() <= 1 && obj.contains(QLatin1String("@type"));
}
void ExtractorEngine::executeContext(ExtractorContext *context)
ExtractorEngine::Result ExtractorEngine::executeContext(ExtractorContext *context)
{
while (!context->rules().isEmpty()) {
QVector<ExtractorRule *> repeatingRules;
......@@ -66,29 +66,42 @@ void ExtractorEngine::executeContext(ExtractorContext *context)
if (!(*it)->match(context)) {
continue;
}
auto classRule = dynamic_cast<ExtractorClassRule *>(*it);
if ((*it)->hasSubRules() || classRule) {
qCDebug(SEMANTIC_LOG) << (*it)->type() << (*it)->name();
ExtractorContext subContext(this, context);
subContext.setRules((*it)->rules());
if (classRule) {
subContext.setProperty(QLatin1String("@type"), classRule->type());
}
subContext.setOffset(context->offset());
executeContext(&subContext);
if (classRule && !isEmptyObject(subContext.object())) {
if ((*it)->name().isEmpty()) {
m_result.push_back(subContext.object());
} else {
context->setProperty(classRule->name(), subContext.object());
}
qCDebug(SEMANTIC_LOG) << (*it)->ruleType() << (*it)->dataType() << (*it)->name();
ExtractorContext subContext(this, context);
subContext.setRules((*it)->rules());
subContext.setOffset(context->offset());
switch ((*it)->ruleType()) {
case ExtractorRule::Class:
subContext.setProperty(QLatin1String("@type"), (*it)->dataType());
break;
case ExtractorRule::Break:
return Result::Break;
default:
break;
}
const auto subResult = executeContext(&subContext);
if (subResult == Result::Break) {
return (*it)->repeats() ? Result::Return : Result::Break;
}
if ((*it)->ruleType() == ExtractorRule::Class && !isEmptyObject(subContext.object())) {
if ((*it)->name().isEmpty()) {
m_result.push_back(subContext.object());
} else {
context->setProperty((*it)->name(), subContext.object());
}
context->setOffset(subContext.offset());
}
context->setOffset(subContext.offset());
if ((*it)->repeats()) {
repeatingRules.push_back(*it);
}
}
context->setRules(repeatingRules);
}
return Result::Return;
}
......@@ -43,7 +43,11 @@ public:
QJsonArray extract();
private:
void executeContext(ExtractorContext *context);
enum class Result {
Return,
Break
};
Result executeContext(ExtractorContext *context);
const Extractor *m_extractor = nullptr;
QString m_text;
......
......@@ -27,11 +27,21 @@
#include <memory>
ExtractorRule::ExtractorRule(ExtractorRule::Type type)
: m_ruleType(type)
{
}
ExtractorRule::~ExtractorRule()
{
qDeleteAll(m_rules);
}
ExtractorRule::Type ExtractorRule::ruleType() const
{
return m_ruleType;
}
bool ExtractorRule::hasSubRules() const
{
return !m_rules.empty();
......@@ -47,9 +57,9 @@ QString ExtractorRule::name() const
return m_name;
}
QString ExtractorRule::type() const
QString ExtractorRule::dataType() const
{
return m_type;
return m_dataType;
}
bool ExtractorRule::repeats() const
......@@ -92,7 +102,7 @@ QLocale ExtractorRule::locale() const
bool ExtractorRule::load(QXmlStreamReader &reader)
{
m_name = reader.attributes().value(QLatin1String("name")).toString();
m_type = reader.attributes().value(QLatin1String("type")).toString();
m_dataType = reader.attributes().value(QLatin1String("type")).toString();
m_value = reader.attributes().value(QLatin1String("value")).toString();
m_format = reader.attributes().value(QLatin1String("format")).toString();
m_repeat = reader.attributes().value(QLatin1String("repeat")) == QLatin1String("true");
......@@ -132,6 +142,8 @@ ExtractorRule *ExtractorRule::fromXml(QXmlStreamReader &reader)
rule.reset(new ExtractorClassRule);
} else if (readerName == QLatin1String("property")) {
rule.reset(new ExtractorPropertyRule);
} else if (readerName == QLatin1String("break")) {
rule.reset(new ExtractorBreakRule);
} else {
return nullptr;
}
......@@ -153,24 +165,44 @@ bool ExtractorRule::match(ExtractorContext *context) const
return res.hasMatch();
}
void ExtractorRule::processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const
{
Q_UNUSED(match);
Q_UNUSED(context);
}
ExtractorVariableRule::ExtractorVariableRule()
: ExtractorRule(ExtractorRule::Variable)
{
}
void ExtractorVariableRule::processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const
{
context->setVariable(name(), value(match, context));
}
void ExtractorClassRule::processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const
ExtractorClassRule::ExtractorClassRule()
: ExtractorRule(ExtractorRule::Class)
{
}
ExtractorPropertyRule::ExtractorPropertyRule()
: ExtractorRule(ExtractorRule::Property)
{
Q_UNUSED(match);
Q_UNUSED(context);
}
void ExtractorPropertyRule::processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const
{
auto val = value(match, context);
if (type() == QLatin1String("dateTime") && !format().isEmpty()) {
if (dataType() == QLatin1String("dateTime") && !format().isEmpty()) {
const auto dt = locale().toDateTime(val, format());
val = dt.toString(Qt::ISODate);
}
context->setProperty(name(), val);
}
ExtractorBreakRule::ExtractorBreakRule()
: ExtractorRule(ExtractorRule::Break)
{
}
......@@ -35,17 +35,26 @@ public:
virtual ~ExtractorRule();
bool match(ExtractorContext *context) const;
enum Type {
Variable,
Class,
Property,
Break
};
Type ruleType() const;
bool hasSubRules() const;
QVector<ExtractorRule *> rules() const;
QString name() const;
QString type() const;
QString dataType() const;
bool repeats() const;
static ExtractorRule *fromXml(QXmlStreamReader &reader);
protected:
explicit ExtractorRule(Type type);
bool load(QXmlStreamReader &reader);
virtual void processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const = 0;
virtual void processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const;
QString value(const QRegularExpressionMatch &match, ExtractorContext *context) const;
QString format() const;
QLocale locale() const;
......@@ -55,29 +64,38 @@ protected:
private:
QVector<ExtractorRule *> m_rules;
QString m_name;
QString m_type;
QString m_dataType;
QString m_value;
QString m_format;
QLocale m_locale;
Type m_ruleType;
bool m_repeat = false;
};
class ExtractorVariableRule : public ExtractorRule
{
public:
ExtractorVariableRule();
void processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const override;
};
class ExtractorClassRule : public ExtractorRule
{
public:
void processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const override;
ExtractorClassRule();
};
class ExtractorPropertyRule : public ExtractorRule
{
public:
ExtractorPropertyRule();
void processMatch(const QRegularExpressionMatch &match, ExtractorContext *context) const override;
};
class ExtractorBreakRule : public ExtractorRule
{
public:
ExtractorBreakRule();
};
#endif // EXTRACTORRULE_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment