| 3783 | } |
| 3784 | |
| 3785 | std::unique_ptr<UnitExpression> ExpressionParser::parseUnit( |
| 3786 | const App::DocumentObject* owner, |
| 3787 | const char* buffer |
| 3788 | ) |
| 3789 | { |
| 3790 | // parse from buffer |
| 3791 | ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer); |
| 3792 | ExpressionParser::StringBufferCleaner cleaner(my_string_buffer); |
| 3793 | |
| 3794 | initParser(owner); |
| 3795 | |
| 3796 | // run the parser |
| 3797 | int result = ExpressionParser::ExpressionParser_yyparse (); |
| 3798 | |
| 3799 | if (result != 0) |
| 3800 | throw ParserError("Failed to parse expression."); |
| 3801 | |
| 3802 | if (!ScanResult) |
| 3803 | throw ParserError("Unknown error in expression"); |
| 3804 | |
| 3805 | // Simplify expression |
| 3806 | ExpressionPtr simplified = ScanResult->simplify(); |
| 3807 | |
| 3808 | if (!unitExpression) { |
| 3809 | auto* fraction = freecad_cast<OperatorExpression*>(ScanResult.get()); |
| 3810 | |
| 3811 | if (fraction && fraction->getOperator() == OperatorExpression::DIV) { |
| 3812 | NumberExpression * nom = freecad_cast<NumberExpression*>(fraction->getLeft()); |
| 3813 | UnitExpression * denom = freecad_cast<UnitExpression*>(fraction->getRight()); |
| 3814 | |
| 3815 | // If not initially a unit expression, but value is equal to 1, it means the expression is something like 1/unit |
| 3816 | if (denom && nom && essentiallyEqual(nom->getValue(), 1.0)) |
| 3817 | unitExpression = true; |
| 3818 | } |
| 3819 | } |
| 3820 | ScanResult.reset(); |
| 3821 | |
| 3822 | if (!unitExpression) { |
| 3823 | throw Expression::Exception("Expression is not a unit."); |
| 3824 | } |
| 3825 | |
| 3826 | if (auto num = freecad_cast<NumberExpression*>(simplified.get()); num) { |
| 3827 | return std::make_unique<UnitExpression>(num->getOwner(), num->getQuantity()); |
| 3828 | } |
| 3829 | return std::unique_ptr<UnitExpression>(freecad_cast<UnitExpression*>(simplified.release())); |
| 3830 | } |
| 3831 | |
| 3832 | namespace { |
| 3833 | std::tuple<int, int> getTokenAndStatus(const std::string & str) |
nothing calls this directly
no test coverage detected