317 const std::set<DRC_CONSTRAINT_T>& aClaimedConstraints )
323 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
324 data->SetRuleName( aRule.
m_Name );
325 data->SetConstraintCode(
"via_style" );
352 if( expr.Contains( wxS(
"'Micro'" ) ) )
354 else if( expr.Contains( wxS(
"'Through'" ) ) )
356 else if( expr.Contains( wxS(
"'Blind'" ) ) )
358 else if( expr.Contains( wxS(
"'Buried'" ) ) )
362 wxString cleanedCondition = expr;
363 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Micro'" ), wxS(
"" ) );
364 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Through'" ), wxS(
"" ) );
365 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Blind'" ), wxS(
"" ) );
366 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Buried'" ), wxS(
"" ) );
385 auto data = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
386 data->SetRuleName( aRule.
m_Name );
387 data->SetConstraintCode(
"diff_pair_gap" );
394 data->SetOptWidth( opt );
395 data->SetWidthTolerance( opt - min );
403 data->SetOptGap( opt );
404 data->SetGapTolerance( opt - min );
417 auto data = std::make_shared<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>();
418 data->SetRuleName( aRule.
m_Name );
419 data->SetConstraintCode(
"text_height" );
440 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
441 data->SetRuleName( aRule.
m_Name );
442 data->SetConstraintCode(
"track_width" );
449 data->SetOptWidth( opt );
450 data->SetWidthTolerance( opt - min );
463 auto data = std::make_shared<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>();
464 data->SetRuleName( aRule.
m_Name );
465 data->SetConstraintCode(
"length" );
471 auto convert = [&](
int aValue )
473 return timeDomain ?
toPS( aValue ) :
toMM( aValue );
482 data->SetTimeDomain( timeDomain );
483 data->SetOptimumLength( opt );
484 data->SetTolerance( ( max - min ) / 2.0 );
497 auto data = std::make_shared<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>();
498 data->SetRuleName( aRule.
m_Name );
499 data->SetConstraintCode(
"length" );
507 data->SetOptimumLength( optMM );
508 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
524 auto data = std::make_shared<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>();
525 data->SetRuleName( aRule.
m_Name );
529 if( constraint && constraint->
m_Test )
533 data->SetTopLayerEnabled( expr.Contains( wxS(
"F.Cu" ) ) );
534 data->SetBottomLayerEnabled( expr.Contains( wxS(
"B.Cu" ) ) );
537 wxString remaining = expr;
538 remaining.Replace( wxS(
"A.Layer == 'F.Cu'" ), wxS(
"" ) );
539 remaining.Replace( wxS(
"A.Layer == 'B.Cu'" ), wxS(
"" ) );
541 if( remaining.Contains( wxS(
"A.Layer" ) ) )
544 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
545 customData->SetRuleName( aRule.
m_Name );
555 auto data = std::make_shared<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>();
556 data->SetRuleName( aRule.
m_Name );
557 data->SetConstraintCode( wxS(
"allowed_orientation" ) );
561 if( constraint && constraint->
m_Test )
565 data->SetIsZeroDegreesAllowed( expr.Contains( wxS(
"== 0 deg" ) ) );
566 data->SetIsNinetyDegreesAllowed( expr.Contains( wxS(
"== 90 deg" ) ) );
567 data->SetIsOneEightyDegreesAllowed( expr.Contains( wxS(
"== 180 deg" ) ) );
568 data->SetIsTwoSeventyDegreesAllowed( expr.Contains( wxS(
"== 270 deg" ) ) );
570 if( data->GetIsZeroDegreesAllowed() && data->GetIsNinetyDegreesAllowed()
571 && data->GetIsOneEightyDegreesAllowed() && data->GetIsTwoSeventyDegreesAllowed() )
573 data->SetIsAllDegreesAllowed(
true );
577 if( data->GetIsZeroDegreesAllowed() || data->GetIsNinetyDegreesAllowed()
578 || data->GetIsOneEightyDegreesAllowed() || data->GetIsTwoSeventyDegreesAllowed() )
585 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
586 customData->SetRuleName( aRule.
m_Name );
591 data->SetIsAllDegreesAllowed(
true );
599 auto data = std::make_shared<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>();
600 data->SetRuleName( aRule.
m_Name );
601 data->SetConstraintCode( wxS(
"disallow_via" ) );
618 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
619 data->SetRuleName( aRule.
m_Name );
629 data->SetRuleName( aRule.
m_Name );
632 data->SetConstraintCode( code );
642 data->SetNumericInputValue( constraint->
GetValue().
Max() );
644 data->SetNumericInputValue( constraint->
GetValue().
Max() / 1000.0 );
646 data->SetNumericInputValue( constraint->
GetValue().
Min() );
658 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
659 data->SetRuleName( aRule.
m_Name );
667 const wxString& aOriginalText )
669 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
678 bool fitsStructuredPanels =
true;
685 fitsStructuredPanels =
false;
691 std::vector<DRC_PANEL_MATCH> matches;
693 if( fitsStructuredPanels )
702 if( assertion && assertion->
m_Test )
706 if( expr.Contains( wxS(
"Orientation" ) ) && !expr.Contains( wxS(
"Layer" ) ) )
713 if( !condition.IsEmpty()
714 && ( condition.Contains( wxS(
"L == 'F.Mask'" ) ) || condition.Contains( wxS(
"L == 'B.Mask'" ) ) ) )
718 else if( !condition.IsEmpty() && !condition.Contains( wxS(
"L == 'F.SilkS'" ) )
719 && !condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
727 if( !constraintData )
732 auto customFallback = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( constraintData );
734 if( customFallback && match.panelType !=
CUSTOM_RULE )
741 wxString cleanedCondition = condition;
744 bool hasBothSides = condition.Contains( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ) );
749 constraintData->SetLayerSource( wxS(
"" ) );
751 cleanedCondition.Replace( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ), wxS(
"" ) );
755 bool isFront = condition.Contains( wxS(
"F.Mask" ) );
757 constraintData->SetLayers( { layer } );
758 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
760 cleanedCondition.Replace( wxS(
"L == 'F.Mask'" ), wxS(
"" ) );
761 cleanedCondition.Replace( wxS(
"L == 'B.Mask'" ), wxS(
"" ) );
769 wxString cleanedCondition = condition;
771 bool hasBothSides = condition.Contains( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
776 constraintData->SetLayerSource( wxS(
"" ) );
778 cleanedCondition.Replace( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ), wxS(
"" ) );
780 else if( condition.Contains( wxS(
"L == 'F.SilkS'" ) ) || condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
782 bool isFront = condition.Contains( wxS(
"F.SilkS" ) );
784 constraintData->SetLayers( { layer } );
785 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
787 cleanedCondition.Replace( wxS(
"L == 'F.SilkS'" ), wxS(
"" ) );
788 cleanedCondition.Replace( wxS(
"L == 'B.SilkS'" ), wxS(
"" ) );
796 wxString cleanedCondition = condition;
798 cleanedCondition.Replace( wxS(
"A.Pad_Type == 'SMD'" ), wxS(
"" ) );
799 cleanedCondition.Replace( wxS(
"B.Pad_Type == 'SMD'" ), wxS(
"" ) );
804 if( match.panelType ==
CUSTOM_RULE && customFallback )
811 constraintData->SetRuleCondition( condition );
818 if(
source.StartsWith( wxS(
"'" ) ) &&
source.EndsWith( wxS(
"'" ) ) )
823 if( !comment.IsEmpty() )
824 constraintData->SetComment( comment );
827 if( entries.empty() )
830 entries.push_back( std::move( entry ) );
834 if( entries.empty() )
836 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
837 customData->SetRuleName( aRule.
m_Name );
838 customData->SetRuleCondition( condition );
841 if( !comment.IsEmpty() )
842 customData->SetComment( comment );
849 if(
source.StartsWith( wxS(
"'" ) ) &&
source.EndsWith( wxS(
"'" ) ) )
853 entries.push_back( std::move( entry ) );
857 entry.originalEntryCount =
static_cast<int>( entries.size() );
865 std::vector<DRC_RE_LOADED_PANEL_ENTRY> allEntries;
866 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
870 wxString rulesText = aRulesText;
875 rulesText.Prepend(
"(version 2)\n" );
882 parser.
Parse( parsedRules,
nullptr );
896 for(
const auto& rule : parsedRules )
898 wxString originalText;
899 wxString leadingTrivia;
903 if( start != wxString::npos )
905 originalText = rulesText.Mid( start,
end - start );
906 leadingTrivia = rulesText.Mid( pos, start - pos );
912 std::vector<DRC_RE_LOADED_PANEL_ENTRY> ruleEntries =
LoadRule( *rule, originalText );
914 for(
auto& entry : ruleEntries )
916 entry.sourceRule = ruleIndex;
917 allEntries.push_back( std::move( entry ) );
935 wxString quotedSearch = wxString::Format( wxS(
"(rule \"%s\"" ), aRuleName );
936 wxString unquotedSearch = wxString::Format( wxS(
"(rule %s" ), aRuleName );
938 size_t startPos = aContent.find( quotedSearch );
940 if( startPos == wxString::npos )
944 while( ( pos = aContent.find( unquotedSearch, pos ) ) != wxString::npos )
946 size_t afterMatch = pos + unquotedSearch.length();
948 if( afterMatch >= aContent.length()
949 || aContent[afterMatch] ==
')'
950 || aContent[afterMatch] ==
' '
951 || aContent[afterMatch] ==
'\n'
952 || aContent[afterMatch] ==
'\r'
953 || aContent[afterMatch] ==
'\t' )
963 if( startPos == wxString::npos )
964 return wxEmptyString;
968 if( endPos == wxString::npos )
969 return wxEmptyString;
971 return aContent.Mid( startPos, endPos - startPos + 1 );
Represents a rule loaded from a .kicad_dru file and mapped to a panel.
wxString layerSource
Original layer text: "inner", "outer", or layer name.