31#include <fmt/format.h>
34#include <wx/mstream.h>
35#include <wx/tokenzr.h>
66using namespace TSCHEMATIC_T;
71 unsigned aLineCount,
SCH_SHEET* aRootSheet,
73 SCHEMATIC_LEXER( aLineReader ),
74 m_requiredVersion( 0 ),
77 m_appending( aIsAppending ),
78 m_progressReporter( aProgressReporter ),
79 m_lineReader( aLineReader ),
80 m_lastProgressLine( 0 ),
81 m_lineCount( aLineCount ),
82 m_rootSheet( aRootSheet )
89 const unsigned PROGRESS_DELTA = 500;
111 KIID id( FromUTF8() );
128 else if( token == T_no )
131 Expecting(
"yes or no" );
142 bool ret = aDefaultValue;
144 if( PrevTok() == T_LEFT )
149 if(
static_cast<int>( token ) ==
DSN_RIGHT )
150 return aDefaultValue;
154 else if( token == T_no )
157 Expecting(
"yes or no" );
164 return aDefaultValue;
179 bool versionChecked =
false;
190 versionChecked =
true;
193 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
195 if( token != T_LEFT )
221 case T_generator_version:
241 aSymbolLibMap[symbol->
GetName()] = symbol;
246 Expecting(
"symbol, generator, or generator_version" );
260 if( CurTok() == T_LEFT )
264 if( CurTok() == T_symbol )
271 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
272 GetTokenString( CurTok() ) );
283 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
284 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
290 wxString unitDisplayName;
292 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
294 symbol->SetUnitCount( 1 );
306 if( !IsSymbol( token ) )
308 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
317 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
324 if(
static_cast<int>(
name.size() ) > bad_pos )
326 wxString msg = wxString::Format(
327 _(
"Symbol %s contains invalid character '%c'" ),
name,
335 CurLineNumber(), CurOffset() );
340 symbol->SetLibId(
id );
342 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
344 if( token != T_LEFT )
363 if( token != T_hide )
366 symbol->SetShowPinNumbers(
false );
370 case T_exclude_from_sim:
371 symbol->SetExcludedFromSim(
parseBool() );
376 symbol->SetExcludedFromBOM( !
parseBool() );
381 symbol->SetExcludedFromBoard( !
parseBool() );
393 if( !IsSymbol( token ) )
396 CurLineNumber(), CurOffset() );
404 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
406 auto it = aSymbolLibMap.find(
name );
408 if( it == aSymbolLibMap.end() )
410 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
411 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
414 symbol->SetParent( it->second );
423 if( !IsSymbol( token ) )
426 CurLineNumber(), CurOffset() );
434 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
438 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
439 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
444 wxStringTokenizer tokenizer(
name,
"_" );
446 if( tokenizer.CountTokens() != 2 )
448 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
449 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
452 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
454 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
455 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
458 m_unit =
static_cast<int>( tmp );
460 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
462 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
463 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
469 symbol->SetHasAlternateBodyStyle(
true,
false );
471 if(
m_unit > symbol->GetUnitCount() )
472 symbol->SetUnitCount(
m_unit,
false );
474 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
476 if( token != T_LEFT )
486 if( IsSymbol( token ) )
488 unitDisplayName = FromUTF8();
489 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
504 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
507 symbol->AddDrawItem( item,
false );
511 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
530 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
533 symbol->AddDrawItem( item,
false );
537 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
538 "rectangle, or text" );
542 symbol->GetDrawItems().sort();
545 return symbol.release();
586 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
600 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
602 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
610 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
612 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
619 strokeParser.SyncLineReaderWith( *
this );
622 SyncLineReaderWith( strokeParser );
628 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
631 aFill.
m_Color = COLOR4D::UNSPECIFIED;
635 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
637 if( token != T_LEFT )
650 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
651 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
652 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
653 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
654 default: Expecting(
"none, outline, color or background" );
675 Expecting(
"type or color" );
682 bool aEnforceMinTextSize )
684 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
685 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
701 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
703 if( token == T_LEFT )
709 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
711 if( token == T_LEFT )
718 faceName = FromUTF8();
766 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
770 if( !faceName.IsEmpty() )
779 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
788 case T_mirror:
break;
789 default: Expecting(
"left, right, top, bottom, or mirror" );
798 wxString hyperlink = FromUTF8();
803 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
822 Expecting(
"font, justify, hide or href" );
830 wxCHECK_RET( CurTok() == aHeaderType,
831 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
837 if( tok == T_version )
851 wxCHECK_RET( CurTok() == T_pin_names,
852 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
856 if( token == T_LEFT )
860 if( token != T_offset )
861 Expecting(
"offset" );
868 if( token == T_hide )
870 aSymbol->SetShowPinNames(
false );
873 else if( token != T_RIGHT )
876 CurLineNumber(), CurOffset() );
883 wxCHECK_MSG( CurTok() == T_property,
nullptr,
884 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
885 wxCHECK( aSymbol,
nullptr );
889 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aSymbol.get(),
894 field->SetVisible(
true );
898 if( !IsSymbol( token ) )
900 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
908 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
912 field->SetName(
name );
927 if( !IsSymbol( token ) )
929 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
936 field->SetText( value );
938 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
940 if( token != T_LEFT )
959 field->SetPosition(
parseXY() );
971 field->SetNameShown( show );
975 case T_do_not_autoplace:
978 field->SetCanAutoplace( !doNotAutoplace );
983 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
992 int nextAvailableId = field->GetId() + 1;
995 nextAvailableId += 1;
997 field->SetId( nextAvailableId );
1002 if( field->IsMandatory() )
1004 existingField = aSymbol->GetFieldById( field->GetId() );
1006 *existingField = *field;
1008 return existingField;
1010 else if(
name ==
"ki_keywords" )
1013 aSymbol->SetKeyWords( value );
1017 else if(
name ==
"ki_description" )
1019 aSymbol->SetDescription( value );
1022 else if(
name ==
"ki_fp_filters" )
1025 wxArrayString filters;
1026 wxStringTokenizer tokenizer( value );
1028 while( tokenizer.HasMoreTokens() )
1030 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1031 filters.Add( curr_token );
1034 aSymbol->SetFPFilters( filters );
1037 else if(
name ==
"ki_locked" )
1041 aSymbol->LockUnits(
true );
1047 existingField = aSymbol->FindField( field->GetCanonicalName() );
1058 for(
int ii = 1; ii < 10 && existingField; ii++ )
1060 wxString newname = base_name;
1061 newname <<
'_' << ii;
1063 existingField = aSymbol->FindField( newname );
1065 if( !existingField )
1066 field->SetName( newname );
1070 if( !existingField )
1072 aSymbol->AddDrawItem( field.get(),
false );
1074 return field.release();
1087 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1088 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1094 bool hasMidPoint =
false;
1102 bool hasAngles =
false;
1104 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1111 if( token == T_private )
1113 arc->SetPrivate(
true );
1117 for( ; token != T_RIGHT; token = NextTok() )
1119 if( token != T_LEFT )
1120 Expecting( T_LEFT );
1143 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1145 if( token != T_LEFT )
1146 Expecting( T_LEFT );
1174 Expecting(
"at, length, or angles" );
1182 arc->SetStroke( stroke );
1188 arc->SetFillColor( fill.
m_Color );
1192 Expecting(
"start, mid, end, radius, stroke, or fill" );
1198 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1209 EDA_ANGLE arc_start, arc_end, arc_angle;
1210 arc->CalcArcAngles( arc_start, arc_end );
1211 arc_angle = arc_end - arc_start;
1216 arc->SetStart( endPoint );
1217 arc->SetEnd( startPoint );
1220 arc->SetCenter( new_center );
1226 arc->SetCenter( new_center );
1230 else if( hasAngles )
1232 arc->SetCenter( center );
1238 arc->SetStart( endPoint );
1239 arc->SetEnd( startPoint );
1243 EDA_ANGLE arc_start, arc_end, arc_angle;
1244 arc->CalcArcAngles( arc_start, arc_end );
1245 arc_angle = arc_end - arc_start;
1251 arc->SetStart( startPoint );
1252 arc->SetEnd( endPoint );
1256 arc->SetStart( startPoint );
1257 arc->SetEnd( endPoint );
1260 arc->SetCenter( new_center );
1265 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1268 return arc.release();
1274 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1275 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1281 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1283 bezier->SetUnit(
m_unit );
1288 if( token == T_private )
1290 bezier->SetPrivate(
true );
1294 for( ; token != T_RIGHT; token = NextTok() )
1296 if( token != T_LEFT )
1297 Expecting( T_LEFT );
1307 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1309 if( token != T_LEFT )
1310 Expecting( T_LEFT );
1319 case 0: bezier->SetStart(
parseXY() );
break;
1320 case 1: bezier->SetBezierC1(
parseXY() );
break;
1321 case 2: bezier->SetBezierC2(
parseXY() );
break;
1322 case 3: bezier->SetEnd(
parseXY() );
break;
1323 default: Unexpected(
"control point" );
break;
1333 bezier->SetStroke( stroke );
1339 bezier->SetFillColor( fill.
m_Color );
1343 Expecting(
"pts, stroke, or fill" );
1347 bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1349 return bezier.release();
1355 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1356 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1364 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1366 circle->SetUnit(
m_unit );
1371 if( token == T_private )
1373 circle->SetPrivate(
true );
1377 for( ; token != T_RIGHT; token = NextTok() )
1379 if( token != T_LEFT )
1380 Expecting( T_LEFT );
1398 circle->SetStroke( stroke );
1404 circle->SetFillColor( fill.
m_Color );
1408 Expecting(
"center, radius, stroke, or fill" );
1412 circle->SetCenter( center );
1413 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1415 return circle.release();
1426 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1427 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1428 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1429 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1430 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1431 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1432 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1433 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1434 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1435 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1437 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1438 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1441 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1442 "power_in, power_out, open_collector, open_emitter, free or "
1444 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1453 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1454 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1455 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1456 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1457 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1458 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1459 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1460 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1461 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1464 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1465 "output_low, edge_clock_high, non_logic" );
1466 return GRAPHIC_PINSHAPE::LINE;
1470 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1471 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1476 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1483 pin->SetType( parseType( token ) );
1487 pin->SetShape( parseShape( token ) );
1489 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1491 if( token == T_hide )
1493 pin->SetVisible(
false );
1497 if( token != T_LEFT )
1498 Expecting( T_LEFT );
1507 switch(
parseInt(
"pin orientation" ) )
1509 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1510 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1511 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1512 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1513 default: Expecting(
"0, 90, 180, or 270" );
1527 if( !IsSymbol( token ) )
1536 pin->SetName( FromUTF8() );
1540 if( token != T_RIGHT )
1544 if( token == T_effects )
1551 pin->SetNameTextSize(
text.GetTextHeight() );
1556 Expecting(
"effects" );
1565 if( !IsSymbol( token ) )
1568 CurLineNumber(), CurOffset() );
1571 pin->SetNumber( FromUTF8() );
1574 if( token != T_RIGHT )
1578 if( token == T_effects )
1585 pin->SetNumberTextSize(
text.GetTextHeight() );
1590 Expecting(
"effects" );
1602 if( !IsSymbol( token ) )
1605 CurLineNumber(), CurOffset() );
1611 alt.
m_Type = parseType( token );
1614 alt.
m_Shape = parseShape( token );
1616 pin->GetAlternates()[ alt.
m_Name ] = alt;
1623 Expecting(
"at, name, number, length, or alternate" );
1627 return pin.release();
1633 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1634 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1639 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1646 if( token == T_private )
1648 poly->SetPrivate(
true );
1652 for( ; token != T_RIGHT; token = NextTok() )
1654 if( token != T_LEFT )
1655 Expecting( T_LEFT );
1662 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1664 if( token != T_LEFT )
1665 Expecting( T_LEFT );
1681 poly->SetStroke( stroke );
1687 poly->SetFillColor( fill.
m_Color );
1691 Expecting(
"pts, stroke, or fill" );
1695 return poly.release();
1701 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1702 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1707 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1709 rectangle->SetUnit(
m_unit );
1714 if( token == T_private )
1716 rectangle->SetPrivate(
true );
1720 for( ; token != T_RIGHT; token = NextTok() )
1722 if( token != T_LEFT )
1723 Expecting( T_LEFT );
1730 rectangle->SetPosition(
parseXY() );
1735 rectangle->SetEnd(
parseXY() );
1741 rectangle->SetStroke( stroke );
1747 rectangle->SetFillColor( fill.
m_Color );
1751 Expecting(
"start, end, stroke, or fill" );
1755 return rectangle.release();
1761 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1762 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1765 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1772 if( token == T_private )
1774 text->SetPrivate(
true );
1778 if( !IsSymbol( token ) )
1780 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1784 text->SetText( FromUTF8() );
1786 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1788 if( token != T_LEFT )
1789 Expecting( T_LEFT );
1807 Expecting(
"at or effects" );
1811 return text.release();
1817 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1818 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1830 bool foundEnd =
false;
1831 bool foundSize =
false;
1832 bool foundMargins =
false;
1834 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1836 textBox->SetUnit(
m_unit );
1840 if( token == T_private )
1842 textBox->SetPrivate(
true );
1846 if( !IsSymbol( token ) )
1848 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1852 textBox->SetText( FromUTF8() );
1854 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1856 if( token != T_LEFT )
1857 Expecting( T_LEFT );
1888 textBox->SetStroke( stroke );
1894 textBox->SetFillColor( fill.
m_Color );
1899 textBox->SetMarginLeft(
left );
1900 textBox->SetMarginTop( top );
1901 textBox->SetMarginRight(
right );
1902 textBox->SetMarginBottom( bottom );
1903 foundMargins =
true;
1912 Expecting(
"at, size, stroke, fill or effects" );
1916 textBox->SetPosition( pos );
1919 textBox->SetEnd( end );
1920 else if( foundSize )
1921 textBox->SetEnd( pos + size );
1923 Expecting(
"size" );
1927 int margin = textBox->GetLegacyTextMargin();
1928 textBox->SetMarginLeft( margin );
1929 textBox->SetMarginTop( margin );
1930 textBox->SetMarginRight( margin );
1931 textBox->SetMarginBottom( margin );
1934 return textBox.release();
1940 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1941 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1947 wxString pageType = FromUTF8();
1949 if( !aPageInfo.
SetType( pageType ) )
1951 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1978 if( token == T_portrait )
1983 else if( token != T_RIGHT )
1985 Expecting(
"portrait" );
1992 wxCHECK_RET( CurTok() == T_title_block,
1993 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
1997 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1999 if( token != T_LEFT )
2000 Expecting( T_LEFT );
2008 aTitleBlock.
SetTitle( FromUTF8() );
2013 aTitleBlock.
SetDate( FromUTF8() );
2028 int commentNumber =
parseInt(
"comment" );
2030 switch( commentNumber )
2079 CurLine(), CurLineNumber(), CurOffset() );
2086 Expecting(
"title, date, rev, company, or comment" );
2096 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2097 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2099 T token = NextTok();
2101 if( !IsSymbol( token ) )
2103 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2107 wxString
name = FromUTF8();
2109 if(
name.IsEmpty() )
2111 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2117 if( !IsSymbol( token ) )
2119 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2124 wxString value = FromUTF8();
2126 int mandatoryFieldCount = 0;
2133 std::unique_ptr<SCH_FIELD> field =
2134 std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), mandatoryFieldCount, aParent,
name );
2135 field->SetText( value );
2136 field->SetVisible(
true );
2161 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2166 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2174 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2176 if( token != T_LEFT )
2177 Expecting( T_LEFT );
2188 if(
id >= mandatoryFieldCount )
2195 field->SetPosition(
parseXY() );
2207 field->SetNameShown( show );
2211 case T_do_not_autoplace:
2214 field->SetCanAutoplace( !doNotAutoplace );
2219 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2223 return field.release();
2229 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2230 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2231 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2233 T token = NextTok();
2235 if( !IsSymbol( token ) )
2237 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2241 wxString
name = FromUTF8();
2243 if(
name.IsEmpty() )
2245 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2249 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2255 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2256 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2257 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2258 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2259 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2261 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2264 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2266 if( token != T_LEFT )
2267 Expecting( T_LEFT );
2275 sheetPin->SetPosition(
parseXY() );
2277 double angle =
parseDouble(
"sheet pin angle (side)" );
2280 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2281 else if( angle == 90.0 )
2282 sheetPin->SetSide( SHEET_SIDE::TOP );
2283 else if( angle == 180.0 )
2284 sheetPin->SetSide( SHEET_SIDE::LEFT );
2285 else if( angle == 270.0 )
2286 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2288 Expecting(
"0, 90, 180, or 270" );
2305 Expecting(
"at, uuid or effects" );
2309 return sheetPin.release();
2315 wxCHECK_RET( CurTok() == T_sheet_instances,
2316 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2317 wxCHECK( aScreen, );
2321 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2323 if( token != T_LEFT )
2324 Expecting( T_LEFT );
2342 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2344 if( token != T_LEFT )
2345 Expecting( T_LEFT );
2349 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2352 size_t numReplacements = 0;
2370 for(
const wxString& ch : whitespaces )
2371 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2376 if( numReplacements > 0 )
2383 Expecting(
"path or page" );
2388 && ( instance.
m_Path.empty() ) )
2404 Expecting(
"path" );
2412 wxCHECK_RET( CurTok() == T_symbol_instances,
2413 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2414 wxCHECK( aScreen, );
2419 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2421 if( token != T_LEFT )
2422 Expecting( T_LEFT );
2439 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2441 if( token != T_LEFT )
2442 Expecting( T_LEFT );
2461 instance.
m_Value = FromUTF8();
2472 Expecting(
"path, unit, value or footprint" );
2481 Expecting(
"path" );
2490 wxCHECK( aSheet !=
nullptr, );
2494 wxCHECK( screen !=
nullptr, );
2496 if( aIsCopyableOnly )
2499 bool fileHasUuid =
false;
2513 if( !aIsCopyableOnly )
2518 if( CurTok() != T_kicad_sch )
2519 Expecting(
"kicad_sch" );
2535 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2537 if( aIsCopyableOnly && token == T_EOF )
2540 if( token != T_LEFT )
2541 Expecting( T_LEFT );
2571 case T_generator_version:
2597 if( aIsCopyableOnly )
2598 Unexpected( T_paper );
2608 if( aIsCopyableOnly )
2609 Unexpected( T_page );
2613 NeedSYMBOLorNUMBER();
2614 NeedSYMBOLorNUMBER();
2621 if( aIsCopyableOnly )
2622 Unexpected( T_title_block );
2636 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2638 if( token != T_LEFT )
2639 Expecting( T_LEFT );
2652 Expecting(
"symbol" );
2753 case T_netclass_flag:
2758 case T_global_label:
2759 case T_hierarchical_label:
2760 case T_directive_label:
2772 case T_sheet_instances:
2776 case T_symbol_instances:
2781 if( aIsCopyableOnly )
2782 Unexpected( T_bus_alias );
2788 Expecting(
"symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2789 "bus_entry, line, bus, text, label, class_label, global_label, "
2790 "hierarchical_label, symbol_instances, rule_area, or bus_alias" );
2811 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2812 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2817 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2819 std::set<int> fieldIDsRead;
2822 symbol->ClearFieldsAutoplaced();
2832 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2834 if( token != T_LEFT )
2835 Expecting( T_LEFT );
2847 if( !IsSymbol( token ) )
2850 CurLineNumber(), CurOffset() );
2853 libName = FromUTF8();
2857 libName.Replace(
"{slash}",
"/" );
2867 if( !IsSymbol( token ) && token != T_NUMBER )
2868 Expecting(
"symbol|number" );
2871 wxString
name = FromUTF8();
2875 name.Replace(
"{slash}",
"/" );
2881 if(
static_cast<int>(
name.size() ) > bad_pos )
2883 wxString msg = wxString::Format(
2884 _(
"Symbol %s contains invalid character '%c'" ),
name,
2891 CurLineNumber(), CurOffset() );
2894 symbol->SetLibId( libId );
2900 symbol->SetPosition(
parseXY() );
2902 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
2905 case 90: transform =
TRANSFORM( 0, -1, -1, 0 );
break;
2906 case 180: transform =
TRANSFORM( -1, 0, 0, 1 );
break;
2907 case 270: transform =
TRANSFORM( 0, 1, 1, 0 );
break;
2908 default: Expecting(
"0, 90, 180, or 270" );
2911 symbol->SetTransform( transform );
2920 else if( token == T_y )
2923 Expecting(
"x or y" );
2929 symbol->SetUnit(
parseInt(
"symbol unit" ) );
2934 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
2938 case T_exclude_from_sim:
2939 symbol->SetExcludedFromSim(
parseBool() );
2944 symbol->SetExcludedFromBOM( !
parseBool() );
2949 symbol->SetExcludedFromBoard( !
parseBool() );
2958 case T_fields_autoplaced:
2960 symbol->SetFieldsAutoplaced();
2970 case T_default_instance:
2974 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2976 if( token != T_LEFT )
2977 Expecting( T_LEFT );
2996 symbol->SetValueFieldText( FromUTF8() );
3002 symbol->SetFootprintFieldText( FromUTF8() );
3007 Expecting(
"reference, unit, value or footprint" );
3016 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3018 if( token != T_LEFT )
3019 Expecting( T_LEFT );
3023 if( token != T_project )
3024 Expecting(
"project" );
3028 wxString projectName = FromUTF8();
3030 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3032 if( token != T_LEFT )
3033 Expecting( T_LEFT );
3037 if( token != T_path )
3038 Expecting(
"path" );
3047 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3049 if( token != T_LEFT )
3050 Expecting( T_LEFT );
3069 symbol->SetValueFieldText( FromUTF8() );
3075 symbol->SetFootprintFieldText( FromUTF8() );
3080 Expecting(
"reference, unit, value or footprint" );
3083 symbol->AddHierarchicalReference( instance );
3100 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3107 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3113 int nextAvailableId = field->
GetId() + 1;
3116 nextAvailableId += 1;
3118 field->
SetId( nextAvailableId );
3121 if( symbol->GetFieldById( field->
GetId() ) )
3122 *symbol->GetFieldById( field->
GetId() ) = *field;
3124 symbol->AddField( *field );
3127 symbol->UpdatePrefix();
3142 number = FromUTF8();
3144 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3146 if( token != T_LEFT )
3147 Expecting( T_LEFT );
3171 Expecting(
"alternate or uuid" );
3175 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3181 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3182 "default_instance, property, pin, or instances" );
3186 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3187 symbol->SetSchSymbolLibraryName( libName );
3190 symbol->ClearFlags();
3192 return symbol.release();
3198 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3199 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3202 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3204 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3206 if( token != T_LEFT )
3207 Expecting( T_LEFT );
3214 bitmap->SetPosition(
parseXY() );
3219 bitmap->GetImage()->SetScale(
parseDouble(
"image scale factor" ) );
3221 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3222 bitmap->GetImage()->SetScale( 1.0 );
3241 data.reserve( 1 << 17 );
3243 while( token != T_RIGHT )
3245 if( !IsSymbol( token ) )
3246 Expecting(
"base64 image data" );
3252 wxMemoryBuffer buffer = wxBase64Decode( data );
3254 if( !bitmap->GetImage()->ReadImageFile( buffer ) )
3261 Expecting(
"at, scale, uuid or data" );
3276 return bitmap.release();
3282 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3283 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3289 std::vector<SCH_FIELD> fields;
3290 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3291 std::set<int> fieldIDsRead;
3294 sheet->ClearFieldsAutoplaced();
3296 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3298 if( token != T_LEFT )
3299 Expecting( T_LEFT );
3306 sheet->SetPosition(
parseXY() );
3315 sheet->SetSize( size );
3320 case T_fields_autoplaced:
3322 sheet->SetFieldsAutoplaced();
3328 sheet->SetBorderWidth( stroke.
GetWidth() );
3329 sheet->SetBorderColor( stroke.
GetColor() );
3334 sheet->SetBackgroundColor( fill.
m_Color );
3351 if( fields.empty() )
3365 if( field->
GetId() < 0 )
3368 while( !fieldIDsRead.insert( field->
GetId() ).second )
3371 fields.emplace_back( *field );
3381 std::vector<SCH_SHEET_INSTANCE> instances;
3383 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3385 if( token != T_LEFT )
3386 Expecting( T_LEFT );
3390 if( token != T_project )
3391 Expecting(
"project" );
3395 wxString projectName = FromUTF8();
3397 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3399 if( token != T_LEFT )
3400 Expecting( T_LEFT );
3404 if( token != T_path )
3405 Expecting(
"path" );
3414 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3416 if( token != T_LEFT )
3417 Expecting( T_LEFT );
3437 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ),
3438 wxT(
"\t" ), wxT(
" " ) };
3440 for( wxString ch : whitespaces )
3449 Expecting(
"page" );
3453 instances.emplace_back( instance );
3457 sheet->setInstances( instances );
3462 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3466 sheet->SetFields( fields );
3468 return sheet.release();
3474 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3475 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3478 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3480 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3482 if( token != T_LEFT )
3483 Expecting( T_LEFT );
3490 junction->SetPosition(
parseXY() );
3508 junction->SetColor(
color );
3520 Expecting(
"at, diameter, color or uuid" );
3524 return junction.release();
3530 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3531 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3534 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3536 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3538 if( token != T_LEFT )
3539 Expecting( T_LEFT );
3546 no_connect->SetPosition(
parseXY() );
3557 Expecting(
"at or uuid" );
3561 return no_connect.release();
3567 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3568 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3572 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3574 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3576 if( token != T_LEFT )
3577 Expecting( T_LEFT );
3584 busEntry->SetPosition(
parseXY() );
3594 busEntry->SetSize( size );
3601 busEntry->SetStroke( stroke );
3611 Expecting(
"at, size, uuid or stroke" );
3615 return busEntry.release();
3625 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3627 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3629 if( token != T_LEFT )
3630 Expecting( T_LEFT );
3637 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3639 if( token != T_LEFT )
3640 Expecting( T_LEFT );
3647 polyline->AddPoint(
parseXY() );
3660 polyline->SetStroke( stroke );
3666 polyline->SetFillColor( fill.
m_Color );
3676 Expecting(
"pts, uuid, stroke, or fill" );
3680 return polyline.release();
3699 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3702 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3704 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3706 if( token != T_LEFT )
3707 Expecting( T_LEFT );
3720 line->SetStartPoint(
parseXY() );
3728 line->SetEndPoint(
parseXY() );
3735 line->SetStroke( stroke );
3745 Expecting(
"at, uuid or stroke" );
3749 return line.release();
3755 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3756 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3764 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3768 if( token != T_LEFT )
3769 Expecting( T_LEFT );
3792 arc->SetStroke( stroke );
3798 arc->SetFillColor( fill.
m_Color );
3803 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3808 Expecting(
"start, mid, end, stroke, fill or uuid" );
3812 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3814 return arc.release();
3820 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3821 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3828 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3830 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3832 if( token != T_LEFT )
3833 Expecting( T_LEFT );
3851 circle->SetStroke( stroke );
3857 circle->SetFillColor( fill.
m_Color );
3862 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
3867 Expecting(
"center, radius, stroke, fill or uuid" );
3871 circle->SetCenter( center );
3872 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
3874 return circle.release();
3880 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
3881 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
3886 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
3888 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3890 if( token != T_LEFT )
3891 Expecting( T_LEFT );
3898 rectangle->SetPosition(
parseXY() );
3903 rectangle->SetEnd(
parseXY() );
3909 rectangle->SetStroke( stroke );
3915 rectangle->SetFillColor( fill.
m_Color );
3920 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
3925 Expecting(
"start, end, stroke, fill or uuid" );
3929 return rectangle.release();
3935 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
3936 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
3941 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
3943 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3945 if( token != T_LEFT )
3946 Expecting( T_LEFT );
3955 ruleArea->SetPolyShape( poly->GetPolyShape() );
3956 ruleArea->SetStroke( poly->GetStroke() );
3957 ruleArea->SetFillMode( poly->GetFillMode() );
3958 ruleArea->SetFillColor( poly->GetFillColor() );
3962 Expecting(
"polyline" );
3966 return ruleArea.release();
3972 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
3973 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
3978 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
3980 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3982 if( token != T_LEFT )
3983 Expecting( T_LEFT );
3993 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
3995 if( token != T_LEFT )
3996 Expecting( T_LEFT );
4005 case 0: bezier->SetStart(
parseXY() );
break;
4006 case 1: bezier->SetBezierC1(
parseXY() );
break;
4007 case 2: bezier->SetBezierC2(
parseXY() );
break;
4008 case 3: bezier->SetEnd(
parseXY() );
break;
4009 default: Unexpected(
"control point" );
break;
4019 bezier->SetStroke( stroke );
4025 bezier->SetFillColor( fill.
m_Color );
4030 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4035 Expecting(
"pts, stroke, fill or uuid" );
4039 return bezier.release();
4046 std::unique_ptr<SCH_TEXT>
text;
4050 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4051 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4052 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4053 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4054 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4055 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4057 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4061 text->ClearFieldsAutoplaced();
4065 text->SetText( FromUTF8() );
4067 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4069 if( token != T_LEFT )
4070 Expecting( T_LEFT );
4076 case T_exclude_from_sim:
4087 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4103 Unexpected( T_shape );
4111 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4112 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4113 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4114 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4115 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4116 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4117 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4118 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4119 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4121 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4132 Unexpected( T_length );
4141 case T_fields_autoplaced:
4143 text->SetFieldsAutoplaced();
4173 Unexpected( T_property );
4200 Expecting(
"at, shape, iref, uuid or effects" );
4206 if( label && label->
GetFields().empty() )
4209 return text.release();
4215 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4216 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4218 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4222 return textBox.release();
4228 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4229 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4231 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4235 return cell.release();
4251 bool foundEnd =
false;
4252 bool foundSize =
false;
4253 bool foundMargins =
false;
4257 aTextBox->
SetText( FromUTF8() );
4259 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4261 if( token != T_LEFT )
4262 Expecting( T_LEFT );
4268 case T_exclude_from_sim:
4299 cell->SetColSpan(
parseInt(
"column span" ) );
4300 cell->SetRowSpan(
parseInt(
"row span" ) );
4304 Expecting(
"at, size, stroke, fill, effects or uuid" );
4327 foundMargins =
true;
4343 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4345 Expecting(
"at, size, stroke, fill, effects or uuid" );
4353 else if( foundSize )
4354 aTextBox->
SetEnd( pos + size );
4356 Expecting(
"size" );
4371 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4372 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4376 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4377 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4378 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4380 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4382 if( token != T_LEFT )
4383 Expecting( T_LEFT );
4389 case T_column_count:
4390 table->SetColCount(
parseInt(
"column count" ) );
4394 case T_column_widths:
4398 while( ( token = NextTok() ) != T_RIGHT )
4408 while( ( token = NextTok() ) != T_RIGHT )
4415 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4417 if( token != T_LEFT )
4418 Expecting( T_LEFT );
4422 if( token != T_table_cell )
4423 Expecting(
"table_cell" );
4431 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4433 if( token != T_LEFT )
4434 Expecting( T_LEFT );
4441 table->SetStrokeExternal(
parseBool() );
4452 table->SetBorderStroke( borderStroke );
4456 Expecting(
"external, header or stroke" );
4464 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4466 if( token != T_LEFT )
4467 Expecting( T_LEFT );
4485 table->SetSeparatorsStroke( separatorsStroke );
4489 Expecting(
"rows, cols, or stroke" );
4497 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4501 return table.release();
4507 wxCHECK_RET( CurTok() == T_bus_alias,
4508 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4509 wxCHECK( aScreen, );
4512 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4523 busAlias->SetName( alias );
4528 if( token != T_members )
4529 Expecting(
"members" );
4533 while( token != T_RIGHT )
4535 if( !IsSymbol( token ) )
4536 Expecting(
"quoted string" );
4538 member = FromUTF8();
4543 busAlias->Members().emplace_back( member );
constexpr EDA_IU_SCALE schIUScale
void SetContentModified(bool aModified=true)
This class handle bitmap images in KiCad.
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
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)
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)
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 SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Simple container to manage fill parameters.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
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
int UpdateFieldOrdinals()
Order optional field indices.
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
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.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
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)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
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()
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()
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
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_TEXT * parseSymbolText()
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.
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()
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)
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.
int GetFileFormatVersionAtLoad() const
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.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
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...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
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
#define THROW_IO_ERROR(msg)
#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.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
#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.
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 ...
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#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)
constexpr int MilsToIU(int mils) const
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
wxString GetCanonicalFieldName(int idx)
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
constexpr T Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.