You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.5 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020-2022 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. #include <board_item.h>
  24. #include <reporter.h>
  25. #include <drc/drc_rule_condition.h>
  26. #include <pcbexpr_evaluator.h>
  27. DRC_RULE_CONDITION::DRC_RULE_CONDITION( const wxString& aExpression ) :
  28. m_expression( aExpression ),
  29. m_ucode ( nullptr )
  30. {
  31. }
  32. DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
  33. {
  34. }
  35. bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
  36. int aConstraint, PCB_LAYER_ID aLayer, REPORTER* aReporter )
  37. {
  38. if( GetExpression().IsEmpty() )
  39. return true;
  40. if( !m_ucode )
  41. {
  42. if( aReporter )
  43. aReporter->Report( _( "ERROR in expression." ) );
  44. return false;
  45. }
  46. PCBEXPR_CONTEXT ctx( aConstraint, aLayer );
  47. if( aReporter )
  48. {
  49. ctx.SetErrorCallback(
  50. [&]( const wxString& aMessage, int aOffset )
  51. {
  52. aReporter->Report( _( "ERROR:" ) + wxS( " " ) + aMessage );
  53. } );
  54. }
  55. BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
  56. BOARD_ITEM* b = const_cast<BOARD_ITEM*>( aItemB );
  57. ctx.SetItems( a, b );
  58. if( m_ucode->Run( &ctx )->AsDouble() != 0.0 )
  59. {
  60. return true;
  61. }
  62. else if( aItemB ) // Conditions are commutative
  63. {
  64. ctx.SetItems( b, a );
  65. if( m_ucode->Run( &ctx )->AsDouble() != 0.0 )
  66. return true;
  67. }
  68. return false;
  69. }
  70. bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
  71. {
  72. PCBEXPR_COMPILER compiler( new PCBEXPR_UNIT_RESOLVER() );
  73. if( aReporter )
  74. {
  75. compiler.SetErrorCallback(
  76. [&]( const wxString& aMessage, int aOffset )
  77. {
  78. wxString rest;
  79. wxString first = aMessage.BeforeFirst( '|', &rest );
  80. wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
  81. aSourceLine,
  82. aSourceOffset + aOffset,
  83. first,
  84. rest );
  85. aReporter->Report( msg, RPT_SEVERITY_ERROR );
  86. } );
  87. }
  88. m_ucode = std::make_unique<PCBEXPR_UCODE>();
  89. PCBEXPR_CONTEXT preflightContext( 0, F_Cu );
  90. bool ok = compiler.Compile( GetExpression().ToUTF8().data(), m_ucode.get(), &preflightContext );
  91. return ok;
  92. }