31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
73using namespace TSCHEMATIC_T;
78 unsigned aLineCount,
SCH_SHEET* aRootSheet,
80 SCHEMATIC_LEXER( aLineReader ),
97 const unsigned PROGRESS_DELTA = 500;
119 KIID id( FromUTF8() );
136 else if( token == T_no )
139 Expecting(
"yes or no" );
150 bool ret = aDefaultValue;
152 if( PrevTok() == T_LEFT )
157 if(
static_cast<int>( token ) ==
DSN_RIGHT )
158 return aDefaultValue;
162 else if( token == T_no )
165 Expecting(
"yes or no" );
172 return aDefaultValue;
190 bool versionChecked =
false;
201 versionChecked =
true;
204 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
206 if( token != T_LEFT )
232 case T_generator_version:
252 aSymbolLibMap[symbol->
GetName()] = symbol;
257 Expecting(
"symbol, generator, or generator_version" );
271 if( CurTok() == T_LEFT )
275 if( CurTok() == T_symbol )
280 const std::vector<wxString>* embeddedFonts =
287 textItem->ResolveFont( embeddedFonts );
293 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
294 GetTokenString( CurTok() ) );
305 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
306 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
313 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
315 symbol->SetUnitCount( 1,
true );
319 if( !IsSymbol( token ) )
320 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
327 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
334 if(
static_cast<int>(
name.size() ) > bad_pos )
336 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
345 CurLineNumber(), CurOffset() );
350 symbol->SetLibId(
id );
352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
354 if( token != T_LEFT )
362 symbol->SetGlobalPower();
365 if( token == T_RIGHT )
368 if( token == T_local )
369 symbol->SetLocalPower();
370 else if( token != T_global )
371 Expecting(
"global or local" );
388 case T_exclude_from_sim:
389 symbol->SetExcludedFromSim(
parseBool() );
394 symbol->SetExcludedFromBOM( !
parseBool() );
399 symbol->SetExcludedFromBoard( !
parseBool() );
403 case T_duplicate_pin_numbers_are_jumpers:
404 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
408 case T_jumper_pin_groups:
411 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
412 std::set<wxString>* currentGroup =
nullptr;
414 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
416 switch(
static_cast<int>( token ) )
419 currentGroup = &groups.emplace_back();
423 currentGroup->insert( FromUTF8() );
427 currentGroup =
nullptr;
431 Expecting(
"list of pin names" );
446 if( !IsSymbol( token ) )
449 CurLineNumber(), CurOffset() );
457 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
459 auto it = aSymbolLibMap.find(
name );
461 if( it == aSymbolLibMap.end() )
463 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
464 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
467 symbol->SetParent( it->second );
476 if( !IsSymbol( token ) )
479 CurLineNumber(), CurOffset() );
487 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
491 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
492 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
497 wxStringTokenizer tokenizer(
name,
"_" );
499 if( tokenizer.CountTokens() != 2 )
501 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
502 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
505 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
507 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
508 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
511 m_unit =
static_cast<int>( tmp );
513 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
515 error.Printf(
_(
"Invalid symbol body style number %s" ),
name.c_str() );
516 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
522 symbol->SetBodyStyleCount(
m_bodyStyle,
false,
false );
524 if(
m_unit > symbol->GetUnitCount() )
525 symbol->SetUnitCount(
m_unit,
false );
527 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
529 if( token != T_LEFT )
539 if( IsSymbol( token ) )
540 symbol->GetUnitDisplayNames()[
m_unit] = FromUTF8();
555 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
558 symbol->AddDrawItem( item,
false );
562 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
581 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
584 symbol->AddDrawItem( item,
false );
587 case T_embedded_fonts:
589 symbol->SetAreFontsEmbedded(
parseBool() );
594 case T_embedded_files:
597 embeddedFilesParser.SyncLineReaderWith( *
this );
601 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
605 wxLogError( e.
What() );
608 SyncLineReaderWith( embeddedFilesParser );
613 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
614 "rectangle, or text" );
618 symbol->GetDrawItems().sort();
621 const std::vector<wxString>* embeddedFonts = symbol->GetEmbeddedFiles()->UpdateFontFiles();
623 symbol->RunOnChildren(
627 textItem->ResolveFont( embeddedFonts );
634 symbol->SetHasDeMorganBodyStyles( symbol->HasLegacyAlternateBodyStyle() );
636 return symbol.release();
652 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
666 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
668 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
676 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
678 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
685 strokeParser.SyncLineReaderWith( *
this );
688 SyncLineReaderWith( strokeParser );
694 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
701 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
703 if( token != T_LEFT )
723 default: Expecting(
"none, outline, hatch, reverse_hatch, "
724 "cross_hatch, color or background" );
745 Expecting(
"type or color" );
752 bool aEnforceMinTextSize )
754 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
755 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
772 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
774 if( token == T_LEFT )
780 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
782 if( token == T_LEFT )
833 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
840 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
849 case T_mirror:
break;
850 default: Expecting(
"left, right, top, bottom, or mirror" );
859 wxString hyperlink = FromUTF8();
864 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
883 Expecting(
"font, justify, hide or href" );
891 wxCHECK_RET( CurTok() == aHeaderType,
892 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
898 if( tok == T_version )
912 wxCHECK_RET( CurTok() == T_body_styles,
913 "Cannot parse " + GetTokenString( CurTok() ) +
" as a body_styles token." );
915 std::vector<wxString> names;
917 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
919 if( token == T_demorgan )
921 aSymbol->SetHasDeMorganBodyStyles(
true );
924 else if( !IsSymbol( token ) )
926 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
930 names.push_back( FromUTF8() );
934 aSymbol->SetBodyStyleNames( names );
940 wxCHECK_RET( CurTok() == T_pin_names,
941 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
951 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
954 if( token == T_hide )
956 aSymbol->SetShowPinNames(
false );
960 if( token != T_LEFT )
975 aSymbol->SetShowPinNames( !
parseBool() );
980 Expecting(
"offset or hide" );
988 wxCHECK_RET( CurTok() == T_pin_numbers,
989 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
998 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
1001 if( token == T_hide )
1003 aSymbol->SetShowPinNumbers(
false );
1007 if( token != T_LEFT )
1009 Expecting( T_LEFT );
1017 aSymbol->SetShowPinNumbers( !
parseBool() );
1022 Expecting(
"hide" );
1031 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1032 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
1033 wxCHECK( aSymbol,
nullptr );
1038 bool isPrivate =
false;
1039 bool isVisible =
true;
1041 T token = NextTok();
1043 if( token == T_private )
1049 if( !IsSymbol( token ) )
1051 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1057 if(
name.IsEmpty() )
1059 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1073 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1074 field->SetPrivate( isPrivate );
1075 field->SetVisible( isVisible );
1079 if( !IsSymbol( token ) )
1081 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1088 value = wxEmptyString;
1092 field->SetText( value );
1094 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1096 if( token != T_LEFT )
1097 Expecting( T_LEFT );
1109 field->SetPosition(
parseXY(
true ) );
1127 field->SetNameShown( show );
1131 case T_do_not_autoplace:
1134 field->SetCanAutoplace( !doNotAutoplace );
1139 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1145 if( field->IsMandatory() )
1147 existingField = aSymbol->GetField( field->GetId() );
1149 *existingField = *field;
1150 return existingField;
1152 else if(
name ==
"ki_keywords" )
1155 aSymbol->SetKeyWords( value );
1159 else if(
name ==
"ki_description" )
1161 aSymbol->SetDescription( value );
1164 else if(
name ==
"ki_fp_filters" )
1167 wxArrayString filters;
1168 wxStringTokenizer tokenizer( value,
" \t\r\n", wxTOKEN_STRTOK );
1170 while( tokenizer.HasMoreTokens() )
1172 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1173 filters.Add( curr_token );
1176 aSymbol->SetFPFilters( filters );
1179 else if(
name ==
"ki_locked" )
1183 aSymbol->LockUnits(
true );
1189 existingField = aSymbol->GetField( field->GetCanonicalName() );
1197 wxString base_name = field->GetCanonicalName();
1200 for(
int ii = 1; ii < 10 && existingField; ii++ )
1202 wxString newname = base_name;
1203 newname <<
'_' << ii;
1205 existingField = aSymbol->GetField( newname );
1207 if( !existingField )
1208 field->SetName( newname );
1212 if( !existingField )
1214 aSymbol->AddDrawItem( field.get(),
false );
1215 return field.release();
1228 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1229 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1235 bool hasMidPoint =
false;
1243 bool hasAngles =
false;
1252 if( token == T_private )
1254 arc->SetPrivate(
true );
1258 for( ; token != T_RIGHT; token = NextTok() )
1260 if( token != T_LEFT )
1261 Expecting( T_LEFT );
1284 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1286 if( token != T_LEFT )
1287 Expecting( T_LEFT );
1315 Expecting(
"at, length, or angles" );
1323 arc->SetStroke( stroke );
1329 arc->SetFillColor( fill.
m_Color );
1333 Expecting(
"start, mid, end, radius, stroke, or fill" );
1339 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1350 EDA_ANGLE arc_start, arc_end, arc_angle;
1351 arc->CalcArcAngles( arc_start, arc_end );
1352 arc_angle = arc_end - arc_start;
1357 arc->SetStart( endPoint );
1358 arc->SetEnd( startPoint );
1361 arc->SetCenter( new_center );
1367 arc->SetCenter( new_center );
1371 else if( hasAngles )
1373 arc->SetCenter(
center );
1379 arc->SetStart( endPoint );
1380 arc->SetEnd( startPoint );
1384 EDA_ANGLE arc_start, arc_end, arc_angle;
1385 arc->CalcArcAngles( arc_start, arc_end );
1386 arc_angle = arc_end - arc_start;
1392 arc->SetStart( startPoint );
1393 arc->SetEnd( endPoint );
1401 arc->SetStart( startPoint );
1402 arc->SetEnd( endPoint );
1406 arc->SetCenter( new_center );
1412 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1415 return arc.release();
1421 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1422 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1430 bezier->SetUnit(
m_unit );
1435 if( token == T_private )
1437 bezier->SetPrivate(
true );
1441 for( ; token != T_RIGHT; token = NextTok() )
1443 if( token != T_LEFT )
1444 Expecting( T_LEFT );
1454 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1456 if( token != T_LEFT )
1457 Expecting( T_LEFT );
1466 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1467 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1468 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1469 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1470 default: Unexpected(
"control point" );
break;
1480 bezier->SetStroke( stroke );
1486 bezier->SetFillColor( fill.
m_Color );
1490 Expecting(
"pts, stroke, or fill" );
1494 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
1496 return bezier.release();
1502 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1503 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1518 if( token == T_private )
1520 circle->SetPrivate(
true );
1524 for( ; token != T_RIGHT; token = NextTok() )
1526 if( token != T_LEFT )
1527 Expecting( T_LEFT );
1545 circle->SetStroke( stroke );
1555 Expecting(
"center, radius, stroke, or fill" );
1588 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1589 "power_in, power_out, open_collector, open_emitter, free or "
1611 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1612 "output_low, edge_clock_high, non_logic" );
1617 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1618 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1621 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1628 pin->SetType( parseType( token ) );
1632 pin->SetShape( parseShape( token ) );
1634 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1637 if( token == T_hide )
1639 pin->SetVisible(
false );
1643 if( token != T_LEFT )
1644 Expecting( T_LEFT );
1653 switch(
parseInt(
"pin orientation" ) )
1659 default: Expecting(
"0, 90, 180, or 270" );
1678 if( !IsSymbol( token ) )
1685 pin->SetName( wxEmptyString );
1689 pin->SetName( FromUTF8() );
1693 if( token != T_RIGHT )
1697 if( token == T_effects )
1704 pin->SetNameTextSize(
text.GetTextHeight() );
1709 Expecting(
"effects" );
1718 if( !IsSymbol( token ) )
1721 CurLineNumber(), CurOffset() );
1725 pin->SetNumber( wxEmptyString );
1729 pin->SetNumber( FromUTF8() );
1733 if( token != T_RIGHT )
1737 if( token == T_effects )
1744 pin->SetNumberTextSize(
text.GetTextHeight() );
1749 Expecting(
"effects" );
1761 if( !IsSymbol( token ) )
1764 CurLineNumber(), CurOffset() );
1770 alt.
m_Type = parseType( token );
1773 alt.
m_Shape = parseShape( token );
1775 pin->GetAlternates()[ alt.
m_Name ] = alt;
1782 Expecting(
"at, name, number, hide, length, or alternate" );
1786 return pin.release();
1792 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1793 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1805 if( token == T_private )
1807 poly->SetPrivate(
true );
1811 for( ; token != T_RIGHT; token = NextTok() )
1813 if( token != T_LEFT )
1814 Expecting( T_LEFT );
1821 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1823 if( token != T_LEFT )
1824 Expecting( T_LEFT );
1831 poly->AddPoint(
parseXY(
true ) );
1840 poly->SetStroke( stroke );
1846 poly->SetFillColor( fill.
m_Color );
1850 Expecting(
"pts, stroke, or fill" );
1854 return poly.release();
1860 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1861 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1868 rectangle->SetUnit(
m_unit );
1873 if( token == T_private )
1875 rectangle->SetPrivate(
true );
1879 for( ; token != T_RIGHT; token = NextTok() )
1881 if( token != T_LEFT )
1882 Expecting( T_LEFT );
1889 rectangle->SetPosition(
parseXY(
true ) );
1894 rectangle->SetEnd(
parseXY(
true ) );
1905 rectangle->SetStroke( stroke );
1911 rectangle->SetFillColor( fill.
m_Color );
1915 Expecting(
"start, end, stroke, or fill" );
1919 return rectangle.release();
1925 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1926 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1929 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1936 if( token == T_private )
1938 text->SetPrivate(
true );
1942 if( !IsSymbol( token ) )
1944 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1948 text->SetText( FromUTF8() );
1950 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1952 if( token != T_LEFT )
1953 Expecting( T_LEFT );
1971 Expecting(
"at or effects" );
1976 if( !
text->IsVisible() )
1979 return text.release();
1985 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1986 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1998 bool foundEnd =
false;
1999 bool foundSize =
false;
2000 bool foundMargins =
false;
2002 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
2004 textBox->SetUnit(
m_unit );
2008 if( token == T_private )
2010 textBox->SetPrivate(
true );
2014 if( !IsSymbol( token ) )
2016 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
2020 textBox->SetText( FromUTF8() );
2022 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2024 if( token != T_LEFT )
2025 Expecting( T_LEFT );
2056 textBox->SetStroke( stroke );
2062 textBox->SetFillColor( fill.
m_Color );
2067 textBox->SetMarginLeft(
left );
2068 textBox->SetMarginTop( top );
2069 textBox->SetMarginRight(
right );
2070 textBox->SetMarginBottom( bottom );
2071 foundMargins =
true;
2080 Expecting(
"at, size, stroke, fill or effects" );
2084 textBox->SetPosition( pos );
2087 textBox->SetEnd(
end );
2088 else if( foundSize )
2089 textBox->SetEnd( pos + size );
2091 Expecting(
"size" );
2095 int margin = textBox->GetLegacyTextMargin();
2096 textBox->SetMarginLeft( margin );
2097 textBox->SetMarginTop( margin );
2098 textBox->SetMarginRight( margin );
2099 textBox->SetMarginBottom( margin );
2102 return textBox.release();
2108 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2109 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2115 wxString pageType = FromUTF8();
2117 if( !aPageInfo.
SetType( pageType ) )
2119 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2146 if( token == T_portrait )
2151 else if( token != T_RIGHT )
2153 Expecting(
"portrait" );
2160 wxCHECK_RET( CurTok() == T_title_block,
2161 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2165 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2167 if( token != T_LEFT )
2168 Expecting( T_LEFT );
2176 aTitleBlock.
SetTitle( FromUTF8() );
2181 aTitleBlock.
SetDate( FromUTF8() );
2196 int commentNumber =
parseInt(
"comment" );
2198 switch( commentNumber )
2247 CurLine(), CurLineNumber(), CurOffset() );
2254 Expecting(
"title, date, rev, company, or comment" );
2264 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2265 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2267 bool is_private =
false;
2269 T token = NextTok();
2271 if( token == T_private )
2277 if( !IsSymbol( token ) )
2279 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2283 wxString
name = FromUTF8();
2285 if(
name.IsEmpty() )
2287 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2293 if( !IsSymbol( token ) )
2295 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2303 value = wxEmptyString;
2335 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2337 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2352 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2356 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2357 field->SetText( value );
2360 field->SetPrivate( is_private );
2362 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2364 if( token != T_LEFT )
2365 Expecting( T_LEFT );
2377 field->SetPosition(
parseXY() );
2395 field->SetNameShown( show );
2399 case T_do_not_autoplace:
2402 field->SetCanAutoplace( !doNotAutoplace );
2407 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2411 return field.release();
2417 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2418 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2419 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2421 T token = NextTok();
2423 if( !IsSymbol( token ) )
2425 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2429 wxString
name = FromUTF8();
2431 if(
name.IsEmpty() )
2433 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2437 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2449 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2452 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2454 if( token != T_LEFT )
2455 Expecting( T_LEFT );
2463 sheetPin->SetPosition(
parseXY() );
2465 double angle =
parseDouble(
"sheet pin angle (side)" );
2469 else if( angle == 90.0 )
2471 else if( angle == 180.0 )
2473 else if( angle == 270.0 )
2476 Expecting(
"0, 90, 180, or 270" );
2493 Expecting(
"at, uuid or effects" );
2497 return sheetPin.release();
2503 wxCHECK_RET( CurTok() == T_sheet_instances,
2504 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2505 wxCHECK( aScreen, );
2509 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2511 if( token != T_LEFT )
2512 Expecting( T_LEFT );
2530 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2532 if( token != T_LEFT )
2533 Expecting( T_LEFT );
2537 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2540 size_t numReplacements = 0;
2558 for(
const wxString& ch : whitespaces )
2559 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2564 if( numReplacements > 0 )
2571 Expecting(
"path or page" );
2576 && ( instance.
m_Path.empty() ) )
2592 Expecting(
"path" );
2600 wxCHECK_RET( CurTok() == T_symbol_instances,
2601 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2602 wxCHECK( aScreen, );
2607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2609 if( token != T_LEFT )
2610 Expecting( T_LEFT );
2627 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2629 if( token != T_LEFT )
2630 Expecting( T_LEFT );
2651 instance.
m_Value = wxEmptyString;
2653 instance.
m_Value = FromUTF8();
2670 Expecting(
"path, unit, value or footprint" );
2679 Expecting(
"path" );
2688 wxCHECK( aSheet !=
nullptr, );
2692 wxCHECK( screen !=
nullptr, );
2695 m_maxError = schematic->Settings().m_MaxError;
2697 if( aIsCopyableOnly )
2700 bool fileHasUuid =
false;
2714 if( !aIsCopyableOnly )
2719 if( CurTok() != T_kicad_sch )
2720 Expecting(
"kicad_sch" );
2739 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2741 if( aIsCopyableOnly && token == T_EOF )
2744 if( token != T_LEFT )
2745 Expecting( T_LEFT );
2779 case T_generator_version:
2805 if( aIsCopyableOnly )
2806 Unexpected( T_paper );
2816 if( aIsCopyableOnly )
2817 Unexpected( T_page );
2821 NeedSYMBOLorNUMBER();
2822 NeedSYMBOLorNUMBER();
2829 if( aIsCopyableOnly )
2830 Unexpected( T_title_block );
2844 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2846 if( token != T_LEFT )
2847 Expecting( T_LEFT );
2859 Expecting(
"symbol" );
2960 case T_netclass_flag:
2965 case T_global_label:
2966 case T_hierarchical_label:
2967 case T_directive_label:
2979 case T_sheet_instances:
2983 case T_symbol_instances:
2988 if( aIsCopyableOnly )
2989 Unexpected( T_bus_alias );
2994 case T_embedded_fonts:
3000 CurLineNumber(), CurOffset() );
3007 case T_embedded_files:
3013 CurLineNumber(), CurOffset() );
3016 embeddedFilesParser.SyncLineReaderWith( *
this );
3024 wxLogError( e.
What() );
3027 SyncLineReaderWith( embeddedFilesParser );
3033 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3034 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3035 "sheet, symbol, symbol_instances, text, title_block" );
3056 CurLineNumber(), CurOffset() );
3060 std::vector<std::string> fontNames;
3061 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3071 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3072 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3077 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3079 std::set<int> fieldIDsRead;
3084 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3086 if( token != T_LEFT )
3087 Expecting( T_LEFT );
3099 if( !IsSymbol( token ) )
3102 CurLineNumber(), CurOffset() );
3105 libName = FromUTF8();
3109 libName.Replace(
"{slash}",
"/" );
3119 if( !IsSymbol( token ) && token != T_NUMBER )
3120 Expecting(
"symbol|number" );
3123 wxString
name = FromUTF8();
3127 name.Replace(
"{slash}",
"/" );
3133 if(
static_cast<int>(
name.size() ) > bad_pos )
3135 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3143 CurLineNumber(), CurOffset() );
3146 symbol->SetLibId( libId );
3152 symbol->SetPosition(
parseXY() );
3154 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3157 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3158 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3159 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3160 default: Expecting(
"0, 90, 180, or 270" );
3163 symbol->SetTransform( transform );
3172 else if( token == T_y )
3175 Expecting(
"x or y" );
3181 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3187 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3191 case T_exclude_from_sim:
3192 symbol->SetExcludedFromSim(
parseBool() );
3197 symbol->SetExcludedFromBOM( !
parseBool() );
3202 symbol->SetExcludedFromBoard( !
parseBool() );
3211 case T_fields_autoplaced:
3223 case T_default_instance:
3227 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3229 if( token != T_LEFT )
3230 Expecting( T_LEFT );
3251 symbol->SetValueFieldText( wxEmptyString );
3253 symbol->SetValueFieldText( FromUTF8() );
3262 symbol->SetFootprintFieldText( wxEmptyString );
3264 symbol->SetFootprintFieldText( FromUTF8() );
3270 Expecting(
"reference, unit, value or footprint" );
3279 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3281 if( token != T_LEFT )
3282 Expecting( T_LEFT );
3286 if( token != T_project )
3287 Expecting(
"project" );
3291 wxString projectName = FromUTF8();
3293 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3295 if( token != T_LEFT )
3296 Expecting( T_LEFT );
3300 if( token != T_path )
3301 Expecting(
"path" );
3310 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3312 if( token != T_LEFT )
3313 Expecting( T_LEFT );
3334 symbol->SetValueFieldText( wxEmptyString );
3336 symbol->SetValueFieldText( FromUTF8() );
3345 symbol->SetFootprintFieldText( wxEmptyString );
3347 symbol->SetFootprintFieldText( FromUTF8() );
3357 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3359 if( token != T_LEFT )
3360 Expecting( T_LEFT );
3368 variant.
m_Name = FromUTF8();
3377 case T_exclude_from_sim:
3390 wxString fieldName = FromUTF8();
3393 wxString fieldValue = FromUTF8();
3395 variant.
m_Fields[fieldName] = fieldValue;
3400 Expecting(
"dnp, exclude_from_sim, field, in_bom, or name" );
3411 Expecting(
"reference, unit, value, footprint, or variant" );
3415 symbol->AddHierarchicalReference( instance );
3431 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3438 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3445 existing = symbol->GetField( field->
GetId() );
3447 existing = symbol->GetField( field->
GetName() );
3452 symbol->AddField( *field );
3455 symbol->UpdatePrefix();
3468 number = FromUTF8();
3470 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3472 if( token != T_LEFT )
3473 Expecting( T_LEFT );
3497 Expecting(
"alternate or uuid" );
3501 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3507 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3508 "default_instance, property, pin, or instances" );
3512 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3513 symbol->SetSchSymbolLibraryName( libName );
3516 symbol->ClearFlags();
3518 return symbol.release();
3524 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3525 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3528 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3531 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3533 if( token != T_LEFT )
3534 Expecting( T_LEFT );
3541 bitmap->SetPosition(
parseXY() );
3567 data.reserve( 1 << 17 );
3569 while( token != T_RIGHT )
3571 if( !IsSymbol( token ) )
3572 Expecting(
"base64 image data" );
3578 wxMemoryBuffer buffer = wxBase64Decode( data );
3587 Expecting(
"at, scale, uuid or data" );
3600 return bitmap.release();
3606 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3607 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3613 std::vector<SCH_FIELD> fields;
3614 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3615 std::set<int> fieldIDsRead;
3620 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3622 if( token != T_LEFT )
3623 Expecting( T_LEFT );
3630 sheet->SetPosition(
parseXY() );
3639 sheet->SetSize( size );
3644 case T_exclude_from_sim:
3645 sheet->SetExcludedFromSim(
parseBool() );
3650 sheet->SetExcludedFromBOM( !
parseBool() );
3655 sheet->SetExcludedFromBoard( !
parseBool() );
3664 case T_fields_autoplaced:
3672 sheet->SetBorderWidth( stroke.
GetWidth() );
3673 sheet->SetBorderColor( stroke.
GetColor() );
3678 sheet->SetBackgroundColor( fill.
m_Color );
3695 if( fields.empty() )
3701 fields.emplace_back( *field );
3712 std::vector<SCH_SHEET_INSTANCE> instances;
3714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3716 if( token != T_LEFT )
3717 Expecting( T_LEFT );
3721 if( token != T_project )
3722 Expecting(
"project" );
3726 wxString projectName = FromUTF8();
3728 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3730 if( token != T_LEFT )
3731 Expecting( T_LEFT );
3735 if( token != T_path )
3736 Expecting(
"path" );
3745 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3747 if( token != T_LEFT )
3748 Expecting( T_LEFT );
3768 static std::vector<wxString> whitespaces =
3774 for( wxString ch : whitespaces )
3786 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3788 if( token != T_LEFT )
3789 Expecting( T_LEFT );
3797 variant.
m_Name = FromUTF8();
3806 case T_exclude_from_sim:
3819 wxString fieldName = FromUTF8();
3822 wxString fieldValue = FromUTF8();
3824 variant.
m_Fields[fieldName] = fieldValue;
3829 Expecting(
"dnp, exclude_from_sim, field, in_bom, or name" );
3840 Expecting(
"page or variant" );
3844 instances.emplace_back( instance );
3848 sheet->setInstances( instances );
3853 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3857 sheet->SetFields( fields );
3859 return sheet.release();
3865 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3866 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3869 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3871 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3873 if( token != T_LEFT )
3874 Expecting( T_LEFT );
3881 junction->SetPosition(
parseXY() );
3899 junction->SetColor(
color );
3911 Expecting(
"at, diameter, color or uuid" );
3915 return junction.release();
3921 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3922 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3925 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3927 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3929 if( token != T_LEFT )
3930 Expecting( T_LEFT );
3937 no_connect->SetPosition(
parseXY() );
3948 Expecting(
"at or uuid" );
3952 return no_connect.release();
3958 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3959 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3963 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3965 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3967 if( token != T_LEFT )
3968 Expecting( T_LEFT );
3975 busEntry->SetPosition(
parseXY() );
3985 busEntry->SetSize( size );
3992 busEntry->SetStroke( stroke );
4002 Expecting(
"at, size, uuid or stroke" );
4006 return busEntry.release();
4028 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4030 if( token != T_LEFT )
4031 Expecting( T_LEFT );
4038 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4040 if( token != T_LEFT )
4041 Expecting( T_LEFT );
4048 polyline->AddPoint(
parseXY() );
4061 polyline->SetStroke( stroke );
4067 polyline->SetFillColor( fill.
m_Color );
4078 Expecting(
"pts, uuid, stroke, or fill" );
4082 return polyline.release();
4101 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4104 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4106 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4108 if( token != T_LEFT )
4109 Expecting( T_LEFT );
4122 line->SetStartPoint(
parseXY() );
4130 line->SetEndPoint(
parseXY() );
4137 line->SetStroke( stroke );
4147 Expecting(
"at, uuid or stroke" );
4151 return line.release();
4157 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4158 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4166 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4168 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4170 if( token != T_LEFT )
4171 Expecting( T_LEFT );
4194 arc->SetStroke( stroke );
4200 arc->SetFillColor( fill.
m_Color );
4206 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4211 Expecting(
"start, mid, end, stroke, fill or uuid" );
4215 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4217 return arc.release();
4223 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4224 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4233 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4235 if( token != T_LEFT )
4236 Expecting( T_LEFT );
4254 circle->SetStroke( stroke );
4271 Expecting(
"center, radius, stroke, fill or uuid" );
4284 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4285 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4290 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4292 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4294 if( token != T_LEFT )
4295 Expecting( T_LEFT );
4302 rectangle->SetPosition(
parseXY() );
4307 rectangle->SetEnd(
parseXY() );
4318 rectangle->SetStroke( stroke );
4324 rectangle->SetFillColor( fill.
m_Color );
4330 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4335 Expecting(
"start, end, stroke, fill or uuid" );
4339 return rectangle.release();
4345 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4346 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4351 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4353 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4355 if( token != T_LEFT )
4356 Expecting( T_LEFT );
4370 ruleArea->SetPolyShape( sch_rule_poly );
4372 ruleArea->SetStroke( poly->GetStroke() );
4373 ruleArea->SetFillMode( poly->GetFillMode() );
4374 ruleArea->SetFillColor( poly->GetFillColor() );
4377 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4381 case T_exclude_from_sim:
4382 ruleArea->SetExcludedFromSim(
parseBool() );
4387 ruleArea->SetExcludedFromBOM( !
parseBool() );
4392 ruleArea->SetExcludedFromBoard( !
parseBool() );
4402 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4406 return ruleArea.release();
4412 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4413 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4418 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4420 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4422 if( token != T_LEFT )
4423 Expecting( T_LEFT );
4433 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4435 if( token != T_LEFT )
4436 Expecting( T_LEFT );
4445 case 0: bezier->SetStart(
parseXY() );
break;
4446 case 1: bezier->SetBezierC1(
parseXY() );
break;
4447 case 2: bezier->SetBezierC2(
parseXY() );
break;
4448 case 3: bezier->SetEnd(
parseXY() );
break;
4449 default: Unexpected(
"control point" );
break;
4459 bezier->SetStroke( stroke );
4465 bezier->SetFillColor( fill.
m_Color );
4471 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4476 Expecting(
"pts, stroke, fill or uuid" );
4480 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4482 return bezier.release();
4489 std::unique_ptr<SCH_TEXT>
text;
4493 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4494 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4495 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4496 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4497 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4498 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4500 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4508 text->SetText( FromUTF8() );
4510 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4512 if( token != T_LEFT )
4513 Expecting( T_LEFT );
4519 case T_exclude_from_sim:
4530 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4546 Unexpected( T_shape );
4564 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4575 Unexpected( T_length );
4584 case T_fields_autoplaced:
4594 text->SetVisible(
true );
4619 Unexpected( T_property );
4639 Expecting(
"at, shape, iref, uuid or effects" );
4645 if( label && label->
GetFields().empty() )
4648 return text.release();
4654 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4655 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4657 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4661 return textBox.release();
4667 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4668 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4670 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4674 return cell.release();
4690 bool foundEnd =
false;
4691 bool foundSize =
false;
4692 bool foundMargins =
false;
4696 aTextBox->
SetText( FromUTF8() );
4698 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4700 if( token != T_LEFT )
4701 Expecting( T_LEFT );
4707 case T_exclude_from_sim:
4738 cell->SetColSpan(
parseInt(
"column span" ) );
4739 cell->SetRowSpan(
parseInt(
"row span" ) );
4743 Expecting(
"at, size, stroke, fill, effects or uuid" );
4767 foundMargins =
true;
4783 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4785 Expecting(
"at, size, stroke, fill, effects or uuid" );
4793 else if( foundSize )
4794 aTextBox->
SetEnd( pos + size );
4796 Expecting(
"size" );
4811 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4812 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4818 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4820 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4822 if( token != T_LEFT )
4823 Expecting( T_LEFT );
4829 case T_column_count:
4834 case T_column_widths:
4838 while( ( token = NextTok() ) != T_RIGHT )
4848 while( ( token = NextTok() ) != T_RIGHT )
4855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4857 if( token != T_LEFT )
4858 Expecting( T_LEFT );
4862 if( token != T_table_cell )
4863 Expecting(
"table_cell" );
4871 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4873 if( token != T_LEFT )
4874 Expecting( T_LEFT );
4892 table->SetBorderStroke( borderStroke );
4896 Expecting(
"external, header or stroke" );
4904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4906 if( token != T_LEFT )
4907 Expecting( T_LEFT );
4925 table->SetSeparatorsStroke( separatorsStroke );
4929 Expecting(
"rows, cols, or stroke" );
4943 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
4947 return table.release();
4953 wxCHECK_RET( CurTok() == T_bus_alias,
4954 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4955 wxCHECK( aScreen, );
4958 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
4969 busAlias->SetName( alias );
4974 if( token != T_members )
4975 Expecting(
"members" );
4979 while( token != T_RIGHT )
4981 if( !IsSymbol( token ) )
4982 Expecting(
"quoted string" );
4984 member = FromUTF8();
4989 busAlias->Members().emplace_back( member );
5004 while( ( token = NextTok() ) != T_RIGHT )
5009 KIID uuid( CurStr() );
5017 wxCHECK_RET( CurTok() == T_group,
5018 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5025 while( ( token = NextTok() ) != T_LEFT )
5027 if( token == T_STRING )
5028 groupInfo.
name = FromUTF8();
5030 Expecting(
"group name or locked" );
5033 for( ; token != T_RIGHT; token = NextTok() )
5035 if( token != T_LEFT )
5036 Expecting( T_LEFT );
5052 if( !IsSymbol( token ) && token != T_NUMBER )
5053 Expecting(
"symbol|number" );
5056 wxString
name = FromUTF8();
5060 name.Replace(
"{slash}",
"/" );
5066 if(
static_cast<int>(
name.size() ) > bad_pos )
5068 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5074 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5088 Expecting(
"uuid, lib_id, members" );
5100 [&](
const KIID& aId )
5106 if( item->m_Uuid == aId )
5125 group->SetName( groupInfo.name );
5127 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5129 if( groupInfo.libId.IsValid() )
5130 group->SetDesignBlockLibId( groupInfo.libId );
5141 for(
const KIID& aUuid : groupInfo.memberUuids )
5143 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5144 group->AddItem( gItem );
constexpr EDA_IU_SCALE schIUScale
constexpr double ARC_LOW_DEF_MM
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
EDA_ITEM * GetParent() const
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
A progress reporter interface for use in multi-threaded environments.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
A set of SCH_ITEMs (i.e., without duplicates).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
SCH_ITEM * parseSymbolText()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseGroupMembers(GROUP_INFO &aGroupInfo)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
void resolveGroups(SCH_SCREEN *aParent)
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
std::vector< GROUP_INFO > m_groupInfos
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseBodyStyles(std::unique_ptr< LIB_SYMBOL > &aSymbol)
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
int m_maxError
Max deviation allowed when approximating bezier curves.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition.
void SetPageSettings(const PAGE_INFO &aPageSettings)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const KIID & GetUuid() const
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Variant information for a schematic sheet.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
Variant information for a schematic symbol.
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetExcludedFromSim(bool aExclude, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void SetMarginTop(int aTop)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
std::map< wxString, wxString > m_Fields
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
Fill with object color.
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_TRISTATE
tri state bus pin
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENEMITTER
pin type open emitter
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
Class to handle a set of SCH_ITEMs.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
void fixupSchFillMode(SCH_SHAPE *aShape)
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
A filename or source description, a problem input line, a line number, a byte offset,...
std::vector< KIID > memberUuids
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
#define SHEET_MANDATORY_FIELDS
#define GLOBALLABEL_MANDATORY_FIELDS
wxString GetCanonicalFieldName(FIELD_T aFieldType)
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
static constexpr double IU_PER_MM
Mock up a conversion function.
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
VECTOR2< int32_t > VECTOR2I