Add expression eval to constraint min/max/opt values.

Also adds error reporting for above.
This commit is contained in:
Jeff Young 2020-07-21 16:49:55 +01:00
parent 7cbd166df7
commit c52df811ae
6 changed files with 48 additions and 34 deletions

View File

@ -262,7 +262,7 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
" (condition \"A.netclass == 'HV'\"))\r" " (condition \"A.netclass == 'HV'\"))\r"
"\r" "\r"
"(rule HV_HV\r" "(rule HV_HV\r"
" (constraint clearance (min 2.0mm))\r" " (constraint clearance (min \"1.5mm + 2.0mm\"))\r"
" (condition \"A.netclass == 'HV' && B.netclass == 'HV'\"))\r" " (condition \"A.netclass == 'HV' && B.netclass == 'HV'\"))\r"
"</pre>"; "</pre>";

View File

@ -27,6 +27,7 @@
#include <drc_rules_lexer.h> #include <drc_rules_lexer.h>
#include <class_board.h> #include <class_board.h>
#include <class_board_item.h> #include <class_board_item.h>
#include <pcb_expr_evaluator.h>
using namespace DRCRULE_T; using namespace DRCRULE_T;
@ -195,7 +196,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
{ {
case T_min: case T_min:
NextTok(); NextTok();
value = parseValue( token ); parseValueWithUnits( FromUTF8(), value );
switch( constraintType ) switch( constraintType )
{ {
@ -210,7 +211,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
case T_max: case T_max:
NextTok(); NextTok();
value = parseValue( token ); parseValueWithUnits( FromUTF8(), value );
switch( constraintType ) switch( constraintType )
{ {
@ -224,7 +225,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
case T_opt: case T_opt:
NextTok(); NextTok();
value = parseValue( token ); parseValueWithUnits( FromUTF8(), value );
switch( constraintType ) switch( constraintType )
{ {
@ -243,7 +244,18 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
} }
int DRC_RULES_PARSER::parseValue( DRCRULE_T::T aToken ) void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult )
{ {
return (int) ValueFromString( EDA_UNITS::MILLIMETRES, CurText(), true ); PCB_EXPR_EVALUATOR evaluator;
}
bool ok = evaluator.Evaluate( aExpr );
if( !ok )
{
LIBEVAL::ERROR_STATUS error = evaluator.GetErrorStatus();
THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
CurOffset() + error.srcPos );
}
aResult = evaluator.Result();
};

View File

@ -51,7 +51,7 @@ private:
DRC_RULE* parseDRC_RULE(); DRC_RULE* parseDRC_RULE();
void parseConstraint( DRC_RULE* aRule ); void parseConstraint( DRC_RULE* aRule );
int parseValue( DRCRULE_T::T aToken ); void parseValueWithUnits( const wxString& aExpr, int& aResult );
private: private:
BOARD* m_board; BOARD* m_board;

View File

@ -24,6 +24,7 @@
#include <cstdio> #include <cstdio>
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include <memory>
#include "class_board.h" #include "class_board.h"
#include "pcb_expr_evaluator.h" #include "pcb_expr_evaluator.h"
@ -249,13 +250,14 @@ public:
PCB_EXPR_COMPILER::PCB_EXPR_COMPILER() PCB_EXPR_COMPILER::PCB_EXPR_COMPILER()
{ {
m_unitResolver.reset( new PCB_UNIT_RESOLVER ); m_unitResolver = std::make_unique<PCB_UNIT_RESOLVER>();
} }
PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR() PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR()
{ {
m_error = false; m_result = NAN;
m_errorStatus.pendingError = false;
} }
PCB_EXPR_EVALUATOR::~PCB_EXPR_EVALUATOR() PCB_EXPR_EVALUATOR::~PCB_EXPR_EVALUATOR()
@ -266,10 +268,15 @@ PCB_EXPR_EVALUATOR::~PCB_EXPR_EVALUATOR()
bool PCB_EXPR_EVALUATOR::Evaluate( const wxString& aExpr ) bool PCB_EXPR_EVALUATOR::Evaluate( const wxString& aExpr )
{ {
PCB_EXPR_UCODE ucode; PCB_EXPR_UCODE ucode;
if( !m_compiler.Compile( (const char*) aExpr.c_str(), &ucode ) )
return false;
auto result = ucode.Run(); if( !m_compiler.Compile( (const char*) aExpr.c_str(), &ucode ) )
{
m_errorStatus = m_compiler.GetErrorStatus();
return false;
}
// fixme: handle error conditions
LIBEVAL::VALUE* result = ucode.Run();
if( result->GetType() == LIBEVAL::VT_NUMERIC ) if( result->GetType() == LIBEVAL::VT_NUMERIC )
m_result = KiROUND( result->AsDouble() ); m_result = KiROUND( result->AsDouble() );
@ -277,8 +284,3 @@ bool PCB_EXPR_EVALUATOR::Evaluate( const wxString& aExpr )
return true; return true;
} }
wxString PCB_EXPR_EVALUATOR::GetErrorString()
{
wxString errMsg;
return errMsg;
}

View File

@ -118,14 +118,16 @@ public:
bool Evaluate( const wxString& aExpr ); bool Evaluate( const wxString& aExpr );
int Result() const { return m_result; } int Result() const { return m_result; }
wxString GetErrorString();
LIBEVAL::ERROR_STATUS GetErrorStatus() { return m_errorStatus; }
private: private:
bool m_error;
int m_result; int m_result;
PCB_EXPR_COMPILER m_compiler; PCB_EXPR_COMPILER m_compiler;
PCB_EXPR_UCODE m_ucode; PCB_EXPR_UCODE m_ucode;
LIBEVAL::ERROR_STATUS m_errorStatus;
}; };
#endif #endif

View File

@ -156,7 +156,7 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
{ {
DRC_RULE* rule = new DRC_RULE(); DRC_RULE* rule = new DRC_RULE();
T token = NextTok(); T token = NextTok();
int val; int value;
if( !IsSymbol( token ) ) if( !IsSymbol( token ) )
Expecting( "rule name" ); Expecting( "rule name" );
@ -181,20 +181,20 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
case T_min: case T_min:
NeedSYMBOL(); NeedSYMBOL();
parseValueWithUnits ( FromUTF8(), val ); parseValueWithUnits( FromUTF8(), value );
rule->m_Constraint.m_Value.SetMin( val ); rule->m_Constraint.m_Value.SetMin( value );
break; break;
case T_opt: case T_opt:
NeedSYMBOL(); NeedSYMBOL();
parseValueWithUnits ( FromUTF8(), val ); parseValueWithUnits( FromUTF8(), value );
rule->m_Constraint.m_Value.SetOpt( val ); rule->m_Constraint.m_Value.SetOpt( value );
break; break;
case T_max: case T_max:
NeedSYMBOL(); NeedSYMBOL();
parseValueWithUnits ( FromUTF8(), val ); parseValueWithUnits( FromUTF8(), value );
rule->m_Constraint.m_Value.SetMax( val ); rule->m_Constraint.m_Value.SetMax( value );
break; break;
case T_allow: case T_allow:
@ -246,12 +246,10 @@ void test::DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aR
if( !ok ) if( !ok )
{ {
auto err = evaluator.GetErrorString(); LIBEVAL::ERROR_STATUS error = evaluator.GetErrorStatus();
//printf( "eval error: '%s'\n", (const char*) err.c_str() ); THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
// fixme: message CurOffset() + error.srcPos );
THROW_PARSE_ERROR( err, "", "", 0, 0 );
} }
aResult = evaluator.Result(); aResult = evaluator.Result();
//printf("parseValueWithUnits: value %d\n", aResult );
}; };