KiCad PCB EDA Suite
drc_rule_condition.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
25 #include <board_item.h>
26 #include <reporter.h>
27 #include <drc/drc_rule_condition.h>
28 #include <pcb_expr_evaluator.h>
29 
30 
31 DRC_RULE_CONDITION::DRC_RULE_CONDITION( const wxString& aExpression ) :
32  m_expression( aExpression ),
33  m_ucode ( nullptr )
34 {
35 }
36 
37 
39 {
40 }
41 
42 
43 bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
44  PCB_LAYER_ID aLayer, REPORTER* aReporter )
45 {
46  if( GetExpression().IsEmpty() )
47  return true;
48 
49  if( !m_ucode )
50  {
51  if( aReporter )
52  aReporter->Report( _( "ERROR in expression." ) );
53 
54  return false;
55  }
56 
57  PCB_EXPR_CONTEXT ctx( aLayer );
58  ctx.SetErrorCallback(
59  [&]( const wxString& aMessage, int aOffset )
60  {
61  if( aReporter )
62  aReporter->Report( _( "ERROR:" ) + wxS( " " )+ aMessage );
63  } );
64 
65  BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
66  BOARD_ITEM* b = const_cast<BOARD_ITEM*>( aItemB );
67 
68  ctx.SetItems( a, b );
69 
70  if( m_ucode->Run( &ctx )->AsDouble() != 0.0 )
71  {
72  return true;
73  }
74  else if( aItemB ) // Conditions are commutative
75  {
76  ctx.SetItems( b, a );
77 
78  if( m_ucode->Run( &ctx )->AsDouble() != 0.0 )
79  return true;
80  }
81 
82  return false;
83 }
84 
85 
86 bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
87 {
88  PCB_EXPR_COMPILER compiler;
89 
90  compiler.SetErrorCallback(
91  [&]( const wxString& aMessage, int aOffset )
92  {
93  if( aReporter )
94  {
95  wxString rest;
96  wxString first = aMessage.BeforeFirst( '|', &rest );
97  wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
98  aSourceLine,
99  aSourceOffset + aOffset,
100  first,
101  rest );
102 
103  aReporter->Report( msg, RPT_SEVERITY_ERROR );
104  }
105  } );
106 
107  m_ucode = std::make_unique<PCB_EXPR_UCODE>();
108 
109  PCB_EXPR_CONTEXT preflightContext( F_Cu );
110 
111  bool ok = compiler.Compile( GetExpression().ToUTF8().data(), m_ucode.get(), &preflightContext );
112  return ok;
113 }
114 
115 
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
DRC_RULE_CONDITION(const wxString &aExpression="")
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
bool Compile(const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
wxString GetExpression() const
PCB_LAYER_ID
A quick note on layer IDs:
std::unique_ptr< PCB_EXPR_UCODE > m_ucode
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
#define _(s)
Definition: 3d_actions.cpp:33
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)