Yes indeed, those are 2 separate parsers. Probably not so easy to merge both because they are targeting close but still different things.adrianinsaval wrote: ↑Tue Jun 21, 2022 8:12 pm does this use a completely separate parser from the expression engine? can't we reuse a subset of the expression parser for this?
Dimension Parser Help
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
Be nice to others! Read the FreeCAD code of conduct!
Re: Dimension Parser Help
- adrianinsaval
- Veteran
- Posts: 5553
- Joined: Thu Apr 05, 2018 5:15 pm
Re: Dimension Parser Help
yes but it would be nice if we can separate the part of that parser that handles units and math and skip all about object references.
-
- Posts: 24
- Joined: Sun May 09, 2021 3:38 am
Re: Dimension Parser Help
I was thinking it should pass whatever string that is typed in the box to the expression parser, units, references and all. Evaluate it down to a number and just use that. That way the parsers are identical, no need to artificially restrict the input.adrianinsaval wrote: ↑Wed Jun 22, 2022 1:09 pm yes but it would be nice if we can separate the part of that parser that handles units and math and skip all about object references.
Its possible this could be done entirely in GUI land, and just use Sketch.setExpression("Constraint[?], u"number/units here"), that way all the dimensions and expressions are handled the same way. (Not sure about this though).
This would also need to evaluate whether the expression is parsable or not and reject if not; just like the expression box.
- adrianinsaval
- Veteran
- Posts: 5553
- Joined: Thu Apr 05, 2018 5:15 pm
Re: Dimension Parser Help
IMO it's not a good idea to parse object references there as it might give users the wrong impression that they have set an expression
-
- Posts: 24
- Joined: Sun May 09, 2021 3:38 am
Re: Dimension Parser Help
Here's my hack and slash proof of concept for this:
It pre parses the input with the Expression Parser before the Quantity Parser parses it.
It allows for inputs of 1mm + 1in -> 26.4mm
It also can do 1mm + Spreadsheet.Value -> Expected value (I agree with adrianinsaval, not sure why anyone would do this but it works)
Needed to disable the auto update of input text to parsed text to avoid parsing:
1mm + 1m
when you were just not finished typing:
1mm + 1mm
Let me know if y'all have any comments.
I'd like to carve out the Quantity Parser from this input entirely, but I haven't investigated how reasonable that is.
It pre parses the input with the Expression Parser before the Quantity Parser parses it.
It allows for inputs of 1mm + 1in -> 26.4mm
It also can do 1mm + Spreadsheet.Value -> Expected value (I agree with adrianinsaval, not sure why anyone would do this but it works)
Needed to disable the auto update of input text to parsed text to avoid parsing:
1mm + 1m
when you were just not finished typing:
1mm + 1mm
Let me know if y'all have any comments.
I'd like to carve out the Quantity Parser from this input entirely, but I haven't investigated how reasonable that is.
Code: Select all
diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp
index 096b7d4b01..65de752617 100644
--- a/src/Gui/QuantitySpinBox.cpp
+++ b/src/Gui/QuantitySpinBox.cpp
@@ -43,13 +43,14 @@
#include <Base/Exception.h>
#include <Base/UnitsApi.h>
#include <Base/Tools.h>
+#include <App/ExpressionParser.h>
#include "QuantitySpinBox.h"
#include "QuantitySpinBox_p.h"
#include "Command.h"
#include "DlgExpressionInput.h"
#include "Tools.h"
-
+#include <App/DocumentObject.h>
using namespace Gui;
using namespace App;
@@ -84,7 +85,7 @@ public:
return text;
}
- bool validate(QString& input, Base::Quantity& result) const
+ bool validate(QString& input, Base::Quantity& result, const App::ObjectIdentifier& path) const
{
Q_Q(const QuantitySpinBox);
@@ -99,7 +100,7 @@ public:
auto validateInput = [&](QString& tmp) -> QValidator::State {
int pos = 0;
QValidator::State state;
- Base::Quantity res = validateAndInterpret(tmp, pos, state);
+ Base::Quantity res = validateAndInterpret(tmp, pos, state, path);
res.setFormat(quantity.getFormat());
if (state == QValidator::Acceptable) {
success = true;
@@ -149,7 +150,7 @@ public:
return false;
}
}
- Base::Quantity validateAndInterpret(QString& input, int& pos, QValidator::State& state) const
+ Base::Quantity validateAndInterpret(QString& input, int& pos, QValidator::State& state, const App::ObjectIdentifier& path) const
{
Base::Quantity res;
const double max = this->maximum;
@@ -157,6 +158,23 @@ public:
QString copy = input;
+ try{
+ std::shared_ptr<Expression> expr(ExpressionParser::parse(path.getDocumentObject(), input.toUtf8().constData()));
+
+ if (expr) {
+ std::unique_ptr<Expression> result(expr->eval());
+ NumberExpression * n = Base::freecad_dynamic_cast<NumberExpression>(result.get());
+ Base::Quantity value = n->getQuantity();
+ QString msg = value.getUserString();
+ //input = msg;
+ copy = msg;
+
+ }
+ }
+ catch(...){
+ qDebug() << "Expression Parse Failed:";
+ }
+
int len = copy.size();
const bool plus = max >= 0;
@@ -286,7 +304,7 @@ end:
res.setValue(max > 0 ? min : max);
}
- input = copy;
+ //input = copy;
return res;
}
@@ -482,7 +500,8 @@ void QuantitySpinBox::validateInput()
int pos = 0;
QValidator::State state;
QString text = lineEdit()->text();
- d->validateAndInterpret(text, pos, state);
+ const App::ObjectIdentifier & path = getPath();
+ d->validateAndInterpret(text, pos, state, path);
if (state != QValidator::Acceptable) {
lineEdit()->setText(d->validStr);
}
@@ -538,7 +557,8 @@ void QuantitySpinBox::userInput(const QString & text)
QString tmp = text;
Base::Quantity res;
- if (d->validate(tmp, res)) {
+ const App::ObjectIdentifier & path = getPath();
+ if (d->validate(tmp, res, path)) {
d->validStr = tmp;
d->validInput = true;
}
@@ -990,10 +1010,11 @@ Base::Quantity QuantitySpinBox::valueFromText(const QString &text) const
QString copy = text;
int pos = lineEdit()->cursorPosition();
QValidator::State state = QValidator::Acceptable;
- Base::Quantity quant = d->validateAndInterpret(copy, pos, state);
+ const App::ObjectIdentifier & path = getPath();
+ Base::Quantity quant = d->validateAndInterpret(copy, pos, state, path);
if (state != QValidator::Acceptable) {
fixup(copy);
- quant = d->validateAndInterpret(copy, pos, state);
+ quant = d->validateAndInterpret(copy, pos, state, path);
}
return quant;
@@ -1004,7 +1025,8 @@ QValidator::State QuantitySpinBox::validate(QString &text, int &pos) const
Q_D(const QuantitySpinBox);
QValidator::State state;
- d->validateAndInterpret(text, pos, state);
+ const App::ObjectIdentifier & path = getPath();
+ d->validateAndInterpret(text, pos, state, path);
return state;
}
- adrianinsaval
- Veteran
- Posts: 5553
- Joined: Thu Apr 05, 2018 5:15 pm
Re: Dimension Parser Help
Good news, the PR for this was merged: git commit 7cd01505fc6e1cddbf5ec39b5474f55c782d1753 so the next weekly builds should exhibit better behavior. Anyone volunteers to add this to Release_notes_1.0? @ChemicalCoal
is there documentation somewhere else that needs to be updated?
is there documentation somewhere else that needs to be updated?
-
- Posts: 24
- Joined: Sun May 09, 2021 3:38 am
Re: Dimension Parser Help
@adrianinsaval I can add this to the release notes once my Wiki account is created,
For documentation I can add a short note, but I don't see a great place to put it,
Maybe here somewhere https://wiki.freecadweb.org/Expressions
or here https://wiki.freecadweb.org/Sketcher_Workbench under Dimensional constraints
Thoughts?
For documentation I can add a short note, but I don't see a great place to put it,
Maybe here somewhere https://wiki.freecadweb.org/Expressions
or here https://wiki.freecadweb.org/Sketcher_Workbench under Dimensional constraints
Thoughts?