29#include <drc_rules_lexer.h> 
   34using namespace DRCRULE_T;
 
   38        DRC_RULES_LEXER( aSource.ToStdString(), aSourceDescr ),
 
 
   49    wxString first = aMessage.BeforeFirst( 
'|', &rest );
 
   53        wxString msg = wxString::Format( 
_( 
"ERROR: <a href='%d:%d'>%s</a>%s" ),
 
   55                                         CurOffset() + aOffset,
 
   63        wxString msg = wxString::Format( 
_( 
"ERROR: %s%s" ), first, rest );
 
   65        THROW_PARSE_ERROR( msg, CurSource(), CurLine(), CurLineNumber(), CurOffset() + aOffset );
 
 
   74        wxString msg = wxString::Format( 
_( 
"The '%s' keyword has been deprecated.  " 
   75                                            "Please use '%s' instead." ),
 
 
   86    size_t pos = curText.find( 
"${" );
 
   88    if( pos == std::string::npos )
 
   91    reportError( 
_( 
"Unresolved text variable" ), (
int) pos );
 
 
  100    for( 
T token = NextTok();  token != T_EOF;  token = NextTok() )
 
  102        if( token == T_LEFT )
 
  105        if( token == T_RIGHT )
 
 
  118    if( curText.starts_with( 
"${" ) )
 
  119        msg.Printf( 
_( 
"Unresolved text variable." ) );
 
  121        msg.Printf( 
_( 
"Unrecognized item '%s'.| Expected %s." ), FromUTF8(), expectedTokens );
 
 
  133    for( 
T token = NextTok();  token != T_EOF;  token = NextTok() )
 
  135        if( token == T_LEFT )
 
  138        if( token == T_RIGHT )
 
  144        if( !expr.IsEmpty() )
 
  145            expr += CurSeparator();
 
 
  157    bool     haveVersion = 
false;
 
  162    for( 
T token = NextTok(); token != T_EOF; token = NextTok() )
 
  167        if( token != T_LEFT )
 
  172        if( !haveVersion && token != T_version )
 
  212            expected( wxT( 
"rule or version" ) );
 
 
  224        std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>>& aRules, 
REPORTER* aReporter )
 
  226    bool     haveVersion = 
false;
 
  231    for( 
T token = NextTok(); token != T_EOF; token = NextTok() )
 
  233        if( token != T_LEFT )
 
  238        if( !haveVersion && token != T_version )
 
  269        case T_assign_component_class:
 
  278            expected( wxT( 
"assign_component_class or version" ) );
 
 
  291    std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
 
  296    if( !IsSymbol( token ) )
 
  300    rule->m_Name = FromUTF8();
 
  302    for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() )
 
  307        if( token != T_LEFT )
 
  325            else if( IsSymbol( token ) )
 
  330                if( !rule->m_Condition->Compile( 
m_reporter, CurLineNumber(), CurOffset() ) )
 
  331                    reportError( wxString::Format( 
_( 
"Could not parse expression '%s'." ), FromUTF8() ) );
 
  347            rule->m_LayerCondition = 
parseLayer( &rule->m_LayerSource );
 
  359            expected( wxT( 
"constraint, condition, or disallow" ) );
 
 
  372    std::shared_ptr<DRC_RULE_CONDITION> condition;
 
  377    if( !IsSymbol( token ) )
 
  381    wxString componentClass = FromUTF8();
 
  383    for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() )
 
  385        if( token != T_LEFT )
 
  399            else if( IsSymbol( token ) )
 
  402                condition = std::make_shared<DRC_RULE_CONDITION>( FromUTF8() );
 
  404                if( !condition->Compile( 
m_reporter, CurLineNumber(), CurOffset() ) )
 
  405                    reportError( wxString::Format( 
_( 
"Could not parse expression '%s'." ), FromUTF8() ) );
 
  429    return std::make_shared<COMPONENT_CLASS_ASSIGNMENT_RULE>( componentClass, std::move( condition ) );
 
 
  440    bool           allowsTimeDomain = 
false;
 
  442    auto validateAndSetValueWithUnits =
 
  443            [
this, &allowsTimeDomain, &
unitsType, &c]( 
int aValue, 
const EDA_UNITS aUnits, 
auto aSetter )
 
  448                    reportError( 
_( 
"Time based units not allowed for constraint type." ) );
 
  453                    reportError( 
_( 
"Mixed units for constraint values." ) );
 
  459                if( allowsTimeDomain )
 
  479    if( token == T_mechanical_clearance )
 
  482        token = T_physical_clearance;
 
  484    else if( token == T_mechanical_hole_clearance )
 
  486        reportDeprecation( wxT( 
"mechanical_hole_clearance" ), wxT( 
"physical_hole_clearance" ) );
 
  487        token = T_physical_hole_clearance;
 
  489    else if( token == T_hole )
 
  494    else if( (
int) token == 
DSN_RIGHT || token == T_EOF )
 
  496        msg.Printf( 
_( 
"Missing constraint type.|  Expected %s." ),
 
  497                    wxT( 
"assertion, clearance, hole_clearance, edge_clearance, physical_clearance, " 
  498                         "physical_hole_clearance, courtyard_clearance, silk_clearance, hole_size, " 
  499                         "hole_to_hole, track_width, track_angle, track_segment_length, annular_width, " 
  500                         "disallow, zone_connection, thermal_relief_gap, thermal_spoke_width, " 
  501                         "min_resolved_spokes, solder_mask_expansion, solder_paste_abs_margin, " 
  502                         "solder_paste_rel_margin, length, skew, via_count, via_dangling, via_diameter, " 
  503                         "diff_pair_gap or diff_pair_uncoupled" ) );
 
  546        expected( wxT( 
"assertion, clearance, hole_clearance, edge_clearance, physical_clearance, " 
  547                       "physical_hole_clearance, courtyard_clearance, silk_clearance, hole_size, " 
  548                       "hole_to_hole, track_width, track_angle, track_segment_length, annular_width, " 
  549                       "disallow, zone_connection, thermal_relief_gap, thermal_spoke_width, " 
  550                       "min_resolved_spokes, solder_mask_expansion, solder_paste_abs_margin, " 
  551                       "solder_paste_rel_margin, length, skew, via_count, via_dangling, via_diameter, " 
  552                       "diff_pair_gap, diff_pair_uncoupled or bridged_mask" ) );
 
  558        msg.Printf( 
_( 
"Rule already has a '%s' constraint." ), FromUTF8() );
 
  572        for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
 
  575                token = GetCurStrAsToken();
 
  600                expected( wxT( 
"track, via, through_via, blind_via, micro_via, buried_via, pad, zone, text, " 
  601                               "graphic, hole, or footprint." ) );
 
  617            token = GetCurStrAsToken();
 
  630            expected( wxT( 
"solid, thermal_reliefs or none." ) );
 
  651            value = (int) strtol( CurText(), 
nullptr, 10 );
 
  672        if( IsSymbol( token ) )
 
  689    for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() )
 
  691        if( token != T_LEFT )
 
  698        case T_within_diff_pairs:
 
  702                reportError( 
_( 
"within_diff_pairs option invalid for constraint type." ) );
 
  711            size_t   offset = CurOffset() + GetTokenString( token ).length();
 
  721            validateAndSetValueWithUnits( value, units,
 
  722                                          [&c]( 
const int aValue )
 
  732            size_t   offset = CurOffset() + GetTokenString( token ).length();
 
  742            validateAndSetValueWithUnits( value, units,
 
  743                                          [&c]( 
const int aValue )
 
  753            size_t   offset = CurOffset() + GetTokenString( token ).length();
 
  763            validateAndSetValueWithUnits( value, units,
 
  764                                          [&c]( 
const int aValue )
 
  777            expected( wxT( 
"min, max, opt, or within_diff_pairs" ) );
 
 
  792            [&]( 
const wxString& message, 
int offset )
 
  795                wxString first = message.BeforeFirst( 
'|', &rest );
 
  799                    wxString msg = wxString::Format( 
_( 
"ERROR: <a href='%d:%d'>%s</a>%s" ),
 
  809                    wxString msg = wxString::Format( 
_( 
"ERROR: %s%s" ), first, rest );
 
  812                                       CurOffset() + aOffset );
 
  822        aResult = evaluator.
Result();
 
  823        aUnits = evaluator.
Units();
 
 
  831    int  token = NextTok();
 
  838    else if( token == T_outer )
 
  840        *aSource = GetTokenString( token );
 
  843    else if( token == T_inner )
 
  845        *aSource = GetTokenString( token );
 
  850        wxString     layerName = FromUTF8();
 
  853        for( 
unsigned ii = 0; ii < layerMap.GetCount(); ++ii )
 
  855            wxPGChoiceEntry& entry = layerMap[ii];
 
  857            if( entry.GetText().Matches( layerName ) )
 
  859                *aSource = layerName;
 
  867                reportError( wxString::Format( 
_( 
"Unrecognized layer '%s'." ), layerName ) );
 
 
  887    if( (
int) token == 
DSN_RIGHT || token == T_EOF )
 
  901        expected( wxT( 
"ignore, warning, error, or exclusion" ) );
 
 
BASE_SET & set(size_t pos)
 
DRC_RULE_CONDITION * m_Test
 
void SetOption(OPTIONS option)
 
ZONE_CONNECTION m_ZoneConnection
 
void ClearOption(OPTIONS option)
 
wxString parseExpression()
 
std::shared_ptr< COMPONENT_CLASS_ASSIGNMENT_RULE > parseComponentClassAssignment()
 
void reportDeprecation(const wxString &oldToken, const wxString &newToken)
 
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
 
void reportError(const wxString &aMessage, int aOffset=0)
 
void parseValueWithUnits(int aOffset, const wxString &aExpr, int &aResult, EDA_UNITS &aUnits, bool aUnitless=false)
 
void ParseComponentClassAssignmentRules(std::vector< std::shared_ptr< COMPONENT_CLASS_ASSIGNMENT_RULE > > &aRules, REPORTER *aReporter)
 
void expected(const wxString &expectedTokens)
 
bool checkUnresolvedTextVariable()
 
std::shared_ptr< DRC_RULE > parseDRC_RULE()
 
LSET parseLayer(wxString *aSource)
 
void parseConstraint(DRC_RULE *aRule)
 
DRC_RULES_PARSER(const wxString &aSource, const wxString &aSourceDescr)
 
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
 
void AddConstraint(DRC_CONSTRAINT &aConstraint)
 
std::optional< DRC_CONSTRAINT > FindConstraint(DRC_CONSTRAINT_T aType)
 
static ENUM_MAP< T > & Instance()
 
LSET is a set of PCB_LAYER_IDs.
 
static const LSET & ExternalCuMask()
Return a mask holding the Front and Bottom layers.
 
static const LSET & AllLayersMask()
 
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
 
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
 
bool Evaluate(const wxString &aExpr)
 
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
 
A pure virtual class used to derive REPORTER objects from.
 
static EDA_DATA_TYPE GetTypeFromUnits(const EDA_UNITS aUnits)
Gets the inferred type from the given units.
 
@ DRC_DISALLOW_BURIED_VIAS
 
@ DRC_DISALLOW_BLIND_VIAS
 
@ DRC_DISALLOW_THROUGH_VIAS
 
@ DRC_DISALLOW_FOOTPRINTS
 
@ DRC_DISALLOW_MICRO_VIAS
 
@ ANNULAR_WIDTH_CONSTRAINT
 
@ BRIDGED_MASK_CONSTRAINT
 
@ COURTYARD_CLEARANCE_CONSTRAINT
 
@ VIA_DIAMETER_CONSTRAINT
 
@ ZONE_CONNECTION_CONSTRAINT
 
@ DIFF_PAIR_GAP_CONSTRAINT
 
@ VIA_DANGLING_CONSTRAINT
 
@ SILK_CLEARANCE_CONSTRAINT
 
@ EDGE_CLEARANCE_CONSTRAINT
 
@ MIN_RESOLVED_SPOKES_CONSTRAINT
 
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
 
@ TEXT_THICKNESS_CONSTRAINT
 
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
 
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
 
@ CONNECTION_WIDTH_CONSTRAINT
 
@ THERMAL_RELIEF_GAP_CONSTRAINT
 
@ MAX_UNCOUPLED_CONSTRAINT
 
@ HOLE_CLEARANCE_CONSTRAINT
 
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
 
@ SOLDER_MASK_EXPANSION_CONSTRAINT
 
@ PHYSICAL_CLEARANCE_CONSTRAINT
 
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
 
@ HOLE_TO_HOLE_CONSTRAINT
 
#define DRC_RULE_FILE_VERSION
 
EDA_DATA_TYPE
The type of unit.
 
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
 
PCB_LAYER_ID ToLAYER_ID(int aLayer)
 
VECTOR3I expected(15, 30, 45)
 
@ THERMAL
Use thermal relief for pads.
 
@ NONE
Pads are not covered.
 
@ FULL
pads are covered by copper