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;
2333 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2335 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2350 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2354 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2355 field->SetText( value );
2358 field->SetPrivate( is_private );
2360 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2362 if( token != T_LEFT )
2363 Expecting( T_LEFT );
2375 field->SetPosition(
parseXY() );
2393 field->SetNameShown( show );
2397 case T_do_not_autoplace:
2400 field->SetCanAutoplace( !doNotAutoplace );
2405 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2409 return field.release();
2415 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2416 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2417 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2419 T token = NextTok();
2421 if( !IsSymbol( token ) )
2423 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2427 wxString
name = FromUTF8();
2429 if(
name.IsEmpty() )
2431 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2435 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2447 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2450 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2452 if( token != T_LEFT )
2453 Expecting( T_LEFT );
2461 sheetPin->SetPosition(
parseXY() );
2463 double angle =
parseDouble(
"sheet pin angle (side)" );
2467 else if( angle == 90.0 )
2469 else if( angle == 180.0 )
2471 else if( angle == 270.0 )
2474 Expecting(
"0, 90, 180, or 270" );
2491 Expecting(
"at, uuid or effects" );
2495 return sheetPin.release();
2501 wxCHECK_RET( CurTok() == T_sheet_instances,
2502 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2503 wxCHECK( aScreen, );
2507 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2509 if( token != T_LEFT )
2510 Expecting( T_LEFT );
2528 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2530 if( token != T_LEFT )
2531 Expecting( T_LEFT );
2535 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2538 size_t numReplacements = 0;
2556 for(
const wxString& ch : whitespaces )
2557 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2562 if( numReplacements > 0 )
2569 Expecting(
"path or page" );
2574 && ( instance.
m_Path.empty() ) )
2590 Expecting(
"path" );
2598 wxCHECK_RET( CurTok() == T_symbol_instances,
2599 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2600 wxCHECK( aScreen, );
2605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2607 if( token != T_LEFT )
2608 Expecting( T_LEFT );
2625 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2627 if( token != T_LEFT )
2628 Expecting( T_LEFT );
2649 instance.
m_Value = wxEmptyString;
2651 instance.
m_Value = FromUTF8();
2668 Expecting(
"path, unit, value or footprint" );
2677 Expecting(
"path" );
2686 wxCHECK( aSheet !=
nullptr, );
2690 wxCHECK( screen !=
nullptr, );
2693 m_maxError = schematic->Settings().m_MaxError;
2695 if( aIsCopyableOnly )
2698 bool fileHasUuid =
false;
2712 if( !aIsCopyableOnly )
2717 if( CurTok() != T_kicad_sch )
2718 Expecting(
"kicad_sch" );
2737 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2739 if( aIsCopyableOnly && token == T_EOF )
2742 if( token != T_LEFT )
2743 Expecting( T_LEFT );
2777 case T_generator_version:
2803 if( aIsCopyableOnly )
2804 Unexpected( T_paper );
2814 if( aIsCopyableOnly )
2815 Unexpected( T_page );
2819 NeedSYMBOLorNUMBER();
2820 NeedSYMBOLorNUMBER();
2827 if( aIsCopyableOnly )
2828 Unexpected( T_title_block );
2842 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2844 if( token != T_LEFT )
2845 Expecting( T_LEFT );
2857 Expecting(
"symbol" );
2958 case T_netclass_flag:
2963 case T_global_label:
2964 case T_hierarchical_label:
2965 case T_directive_label:
2977 case T_sheet_instances:
2981 case T_symbol_instances:
2986 if( aIsCopyableOnly )
2987 Unexpected( T_bus_alias );
2992 case T_embedded_fonts:
2998 CurLineNumber(), CurOffset() );
3005 case T_embedded_files:
3011 CurLineNumber(), CurOffset() );
3014 embeddedFilesParser.SyncLineReaderWith( *
this );
3022 wxLogError( e.
What() );
3025 SyncLineReaderWith( embeddedFilesParser );
3031 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3032 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3033 "sheet, symbol, symbol_instances, text, title_block" );
3054 CurLineNumber(), CurOffset() );
3058 std::vector<std::string> fontNames;
3059 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3069 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3070 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3075 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3077 std::set<int> fieldIDsRead;
3082 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3084 if( token != T_LEFT )
3085 Expecting( T_LEFT );
3097 if( !IsSymbol( token ) )
3100 CurLineNumber(), CurOffset() );
3103 libName = FromUTF8();
3107 libName.Replace(
"{slash}",
"/" );
3117 if( !IsSymbol( token ) && token != T_NUMBER )
3118 Expecting(
"symbol|number" );
3121 wxString
name = FromUTF8();
3125 name.Replace(
"{slash}",
"/" );
3131 if(
static_cast<int>(
name.size() ) > bad_pos )
3133 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3141 CurLineNumber(), CurOffset() );
3144 symbol->SetLibId( libId );
3150 symbol->SetPosition(
parseXY() );
3152 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3155 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3156 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3157 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3158 default: Expecting(
"0, 90, 180, or 270" );
3161 symbol->SetTransform( transform );
3170 else if( token == T_y )
3173 Expecting(
"x or y" );
3179 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3185 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3189 case T_exclude_from_sim:
3190 symbol->SetExcludedFromSim(
parseBool() );
3195 symbol->SetExcludedFromBOM( !
parseBool() );
3200 symbol->SetExcludedFromBoard( !
parseBool() );
3209 case T_fields_autoplaced:
3221 case T_default_instance:
3225 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3227 if( token != T_LEFT )
3228 Expecting( T_LEFT );
3249 symbol->SetValueFieldText( wxEmptyString );
3251 symbol->SetValueFieldText( FromUTF8() );
3260 symbol->SetFootprintFieldText( wxEmptyString );
3262 symbol->SetFootprintFieldText( FromUTF8() );
3268 Expecting(
"reference, unit, value or footprint" );
3277 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3279 if( token != T_LEFT )
3280 Expecting( T_LEFT );
3284 if( token != T_project )
3285 Expecting(
"project" );
3289 wxString projectName = FromUTF8();
3291 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3293 if( token != T_LEFT )
3294 Expecting( T_LEFT );
3298 if( token != T_path )
3299 Expecting(
"path" );
3308 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3310 if( token != T_LEFT )
3311 Expecting( T_LEFT );
3332 symbol->SetValueFieldText( wxEmptyString );
3334 symbol->SetValueFieldText( FromUTF8() );
3343 symbol->SetFootprintFieldText( wxEmptyString );
3345 symbol->SetFootprintFieldText( FromUTF8() );
3351 Expecting(
"reference, unit, value or footprint" );
3354 symbol->AddHierarchicalReference( instance );
3371 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3378 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3385 existing = symbol->GetField( field->
GetId() );
3387 existing = symbol->GetField( field->
GetName() );
3392 symbol->AddField( *field );
3395 symbol->UpdatePrefix();
3408 number = FromUTF8();
3410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3412 if( token != T_LEFT )
3413 Expecting( T_LEFT );
3437 Expecting(
"alternate or uuid" );
3441 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3447 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3448 "default_instance, property, pin, or instances" );
3452 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3453 symbol->SetSchSymbolLibraryName( libName );
3456 symbol->ClearFlags();
3458 return symbol.release();
3464 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3465 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3468 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3471 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3473 if( token != T_LEFT )
3474 Expecting( T_LEFT );
3481 bitmap->SetPosition(
parseXY() );
3507 data.reserve( 1 << 17 );
3509 while( token != T_RIGHT )
3511 if( !IsSymbol( token ) )
3512 Expecting(
"base64 image data" );
3518 wxMemoryBuffer buffer = wxBase64Decode( data );
3527 Expecting(
"at, scale, uuid or data" );
3540 return bitmap.release();
3546 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3547 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3553 std::vector<SCH_FIELD> fields;
3554 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3555 std::set<int> fieldIDsRead;
3560 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3562 if( token != T_LEFT )
3563 Expecting( T_LEFT );
3570 sheet->SetPosition(
parseXY() );
3579 sheet->SetSize( size );
3584 case T_exclude_from_sim:
3585 sheet->SetExcludedFromSim(
parseBool() );
3590 sheet->SetExcludedFromBOM( !
parseBool() );
3595 sheet->SetExcludedFromBoard( !
parseBool() );
3604 case T_fields_autoplaced:
3612 sheet->SetBorderWidth( stroke.
GetWidth() );
3613 sheet->SetBorderColor( stroke.
GetColor() );
3618 sheet->SetBackgroundColor( fill.
m_Color );
3635 if( fields.empty() )
3641 fields.emplace_back( *field );
3652 std::vector<SCH_SHEET_INSTANCE> instances;
3654 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3656 if( token != T_LEFT )
3657 Expecting( T_LEFT );
3661 if( token != T_project )
3662 Expecting(
"project" );
3666 wxString projectName = FromUTF8();
3668 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3670 if( token != T_LEFT )
3671 Expecting( T_LEFT );
3675 if( token != T_path )
3676 Expecting(
"path" );
3685 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3687 if( token != T_LEFT )
3688 Expecting( T_LEFT );
3708 static std::vector<wxString> whitespaces =
3714 for( wxString ch : whitespaces )
3723 Expecting(
"page" );
3727 instances.emplace_back( instance );
3731 sheet->setInstances( instances );
3736 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3740 sheet->SetFields( fields );
3742 return sheet.release();
3748 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3749 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3752 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3754 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3756 if( token != T_LEFT )
3757 Expecting( T_LEFT );
3764 junction->SetPosition(
parseXY() );
3782 junction->SetColor(
color );
3794 Expecting(
"at, diameter, color or uuid" );
3798 return junction.release();
3804 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3805 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3808 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3810 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3812 if( token != T_LEFT )
3813 Expecting( T_LEFT );
3820 no_connect->SetPosition(
parseXY() );
3831 Expecting(
"at or uuid" );
3835 return no_connect.release();
3841 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3842 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3846 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3848 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3850 if( token != T_LEFT )
3851 Expecting( T_LEFT );
3858 busEntry->SetPosition(
parseXY() );
3868 busEntry->SetSize( size );
3875 busEntry->SetStroke( stroke );
3885 Expecting(
"at, size, uuid or stroke" );
3889 return busEntry.release();
3911 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3913 if( token != T_LEFT )
3914 Expecting( T_LEFT );
3921 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3923 if( token != T_LEFT )
3924 Expecting( T_LEFT );
3931 polyline->AddPoint(
parseXY() );
3944 polyline->SetStroke( stroke );
3950 polyline->SetFillColor( fill.
m_Color );
3961 Expecting(
"pts, uuid, stroke, or fill" );
3965 return polyline.release();
3984 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3987 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3989 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3991 if( token != T_LEFT )
3992 Expecting( T_LEFT );
4005 line->SetStartPoint(
parseXY() );
4013 line->SetEndPoint(
parseXY() );
4020 line->SetStroke( stroke );
4030 Expecting(
"at, uuid or stroke" );
4034 return line.release();
4040 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4041 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4049 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4051 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4053 if( token != T_LEFT )
4054 Expecting( T_LEFT );
4077 arc->SetStroke( stroke );
4083 arc->SetFillColor( fill.
m_Color );
4089 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4094 Expecting(
"start, mid, end, stroke, fill or uuid" );
4098 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4100 return arc.release();
4106 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4107 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4116 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4118 if( token != T_LEFT )
4119 Expecting( T_LEFT );
4137 circle->SetStroke( stroke );
4154 Expecting(
"center, radius, stroke, fill or uuid" );
4167 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4168 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4173 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4175 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4177 if( token != T_LEFT )
4178 Expecting( T_LEFT );
4185 rectangle->SetPosition(
parseXY() );
4190 rectangle->SetEnd(
parseXY() );
4201 rectangle->SetStroke( stroke );
4207 rectangle->SetFillColor( fill.
m_Color );
4213 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4218 Expecting(
"start, end, stroke, fill or uuid" );
4222 return rectangle.release();
4228 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4229 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4234 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4236 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4238 if( token != T_LEFT )
4239 Expecting( T_LEFT );
4253 ruleArea->SetPolyShape( sch_rule_poly );
4255 ruleArea->SetStroke( poly->GetStroke() );
4256 ruleArea->SetFillMode( poly->GetFillMode() );
4257 ruleArea->SetFillColor( poly->GetFillColor() );
4260 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4264 case T_exclude_from_sim:
4265 ruleArea->SetExcludedFromSim(
parseBool() );
4270 ruleArea->SetExcludedFromBOM( !
parseBool() );
4275 ruleArea->SetExcludedFromBoard( !
parseBool() );
4285 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4289 return ruleArea.release();
4295 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4296 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4301 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4303 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4305 if( token != T_LEFT )
4306 Expecting( T_LEFT );
4316 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4318 if( token != T_LEFT )
4319 Expecting( T_LEFT );
4328 case 0: bezier->SetStart(
parseXY() );
break;
4329 case 1: bezier->SetBezierC1(
parseXY() );
break;
4330 case 2: bezier->SetBezierC2(
parseXY() );
break;
4331 case 3: bezier->SetEnd(
parseXY() );
break;
4332 default: Unexpected(
"control point" );
break;
4342 bezier->SetStroke( stroke );
4348 bezier->SetFillColor( fill.
m_Color );
4354 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4359 Expecting(
"pts, stroke, fill or uuid" );
4363 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4365 return bezier.release();
4372 std::unique_ptr<SCH_TEXT>
text;
4376 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4377 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4378 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4379 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4380 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4381 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4383 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4391 text->SetText( FromUTF8() );
4393 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4395 if( token != T_LEFT )
4396 Expecting( T_LEFT );
4402 case T_exclude_from_sim:
4413 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4429 Unexpected( T_shape );
4447 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4458 Unexpected( T_length );
4467 case T_fields_autoplaced:
4477 text->SetVisible(
true );
4502 Unexpected( T_property );
4522 Expecting(
"at, shape, iref, uuid or effects" );
4528 if( label && label->
GetFields().empty() )
4531 return text.release();
4537 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4538 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4540 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4544 return textBox.release();
4550 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4551 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4553 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4557 return cell.release();
4573 bool foundEnd =
false;
4574 bool foundSize =
false;
4575 bool foundMargins =
false;
4579 aTextBox->
SetText( FromUTF8() );
4581 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4583 if( token != T_LEFT )
4584 Expecting( T_LEFT );
4590 case T_exclude_from_sim:
4621 cell->SetColSpan(
parseInt(
"column span" ) );
4622 cell->SetRowSpan(
parseInt(
"row span" ) );
4626 Expecting(
"at, size, stroke, fill, effects or uuid" );
4650 foundMargins =
true;
4666 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4668 Expecting(
"at, size, stroke, fill, effects or uuid" );
4676 else if( foundSize )
4677 aTextBox->
SetEnd( pos + size );
4679 Expecting(
"size" );
4694 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4695 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4701 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4703 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4705 if( token != T_LEFT )
4706 Expecting( T_LEFT );
4712 case T_column_count:
4717 case T_column_widths:
4721 while( ( token = NextTok() ) != T_RIGHT )
4731 while( ( token = NextTok() ) != T_RIGHT )
4738 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4740 if( token != T_LEFT )
4741 Expecting( T_LEFT );
4745 if( token != T_table_cell )
4746 Expecting(
"table_cell" );
4754 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4756 if( token != T_LEFT )
4757 Expecting( T_LEFT );
4775 table->SetBorderStroke( borderStroke );
4779 Expecting(
"external, header or stroke" );
4787 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4789 if( token != T_LEFT )
4790 Expecting( T_LEFT );
4808 table->SetSeparatorsStroke( separatorsStroke );
4812 Expecting(
"rows, cols, or stroke" );
4826 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
4830 return table.release();
4836 wxCHECK_RET( CurTok() == T_bus_alias,
4837 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4838 wxCHECK( aScreen, );
4841 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4852 busAlias->SetName( alias );
4857 if( token != T_members )
4858 Expecting(
"members" );
4862 while( token != T_RIGHT )
4864 if( !IsSymbol( token ) )
4865 Expecting(
"quoted string" );
4867 member = FromUTF8();
4872 busAlias->Members().emplace_back( member );
4887 while( ( token = NextTok() ) != T_RIGHT )
4892 KIID uuid( CurStr() );
4900 wxCHECK_RET( CurTok() == T_group,
4901 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
4908 while( ( token = NextTok() ) != T_LEFT )
4910 if( token == T_STRING )
4911 groupInfo.
name = FromUTF8();
4913 Expecting(
"group name or locked" );
4916 for( ; token != T_RIGHT; token = NextTok() )
4918 if( token != T_LEFT )
4919 Expecting( T_LEFT );
4935 if( !IsSymbol( token ) && token != T_NUMBER )
4936 Expecting(
"symbol|number" );
4939 wxString
name = FromUTF8();
4943 name.Replace(
"{slash}",
"/" );
4949 if(
static_cast<int>(
name.size() ) > bad_pos )
4951 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
4957 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
4971 Expecting(
"uuid, lib_id, members" );
4983 [&](
const KIID& aId )
4989 if( item->m_Uuid == aId )
5008 group->SetName( groupInfo.name );
5010 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5012 if( groupInfo.libId.IsValid() )
5013 group->SetDesignBlockLibId( groupInfo.libId );
5024 for(
const KIID& aUuid : groupInfo.memberUuids )
5026 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5027 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 (and transfers ownership of the pointer).
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.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetMarginTop(int aTop)
void SetExcludedFromSim(bool aExclude) override
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.
#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.
A simple container for schematic symbol instance information.
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