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(
_(
"Symbol %s contains invalid character '%c'" ),
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 );
505 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
508 symbol->AddDrawItem( item,
false );
512 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
531 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
534 symbol->AddDrawItem( item,
false );
538 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
539 "rectangle, or text" );
543 symbol->GetDrawItems().sort();
546 return symbol.release();
562 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
576 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
578 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
586 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
588 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
595 strokeParser.SyncLineReaderWith( *
this );
598 SyncLineReaderWith( strokeParser );
604 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
607 aFill.
m_Color = COLOR4D::UNSPECIFIED;
611 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
613 if( token != T_LEFT )
626 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
627 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
628 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
629 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
630 default: Expecting(
"none, outline, color or background" );
651 Expecting(
"type or color" );
658 bool aEnforceMinTextSize )
660 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
661 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
679 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
681 if( token == T_LEFT )
687 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
689 if( token == T_LEFT )
696 faceName = FromUTF8();
740 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
744 if( !faceName.IsEmpty() )
750 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
759 case T_mirror:
break;
760 default: Expecting(
"left, right, top, bottom, or mirror" );
769 wxString hyperlink = FromUTF8();
774 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
793 Expecting(
"font, justify, hide or href" );
801 wxCHECK_RET( CurTok() == aHeaderType,
802 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
808 if( tok == T_version )
822 wxCHECK_RET( CurTok() == T_pin_names,
823 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
827 if( token == T_LEFT )
831 if( token != T_offset )
832 Expecting(
"offset" );
839 if( token == T_hide )
841 aSymbol->SetShowPinNames(
false );
844 else if( token != T_RIGHT )
847 CurLineNumber(), CurOffset() );
854 wxCHECK_MSG( CurTok() == T_property,
nullptr,
855 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
856 wxCHECK( aSymbol,
nullptr );
860 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(),
MANDATORY_FIELDS );
864 field->SetVisible(
true );
868 if( !IsSymbol( token ) )
870 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
878 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
882 field->SetName(
name );
897 if( !IsSymbol( token ) )
899 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
906 field->SetText( value );
908 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
910 if( token != T_LEFT )
931 field->SetPosition(
parseXY(
true ) );
943 field->SetNameShown( show );
947 case T_do_not_autoplace:
950 field->SetCanAutoplace( !doNotAutoplace );
955 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
963 int nextAvailableId = field->GetId() + 1;
966 nextAvailableId += 1;
968 field->SetId( nextAvailableId );
973 if( field->IsMandatory() )
975 existingField = aSymbol->GetFieldById( field->GetId() );
977 *existingField = *field;
979 return existingField;
981 else if(
name ==
"ki_keywords" )
984 aSymbol->SetKeyWords( value );
988 else if(
name ==
"ki_description" )
990 aSymbol->SetDescription( value );
993 else if(
name ==
"ki_fp_filters" )
996 wxArrayString filters;
997 wxStringTokenizer tokenizer( value );
999 while( tokenizer.HasMoreTokens() )
1001 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1002 filters.Add( curr_token );
1005 aSymbol->SetFPFilters( filters );
1008 else if(
name ==
"ki_locked" )
1012 aSymbol->LockUnits(
true );
1018 existingField = aSymbol->FindField( field->GetCanonicalName() );
1029 for(
int ii = 1; ii < 10 && existingField; ii++ )
1031 wxString newname = base_name;
1032 newname <<
'_' << ii;
1034 existingField = aSymbol->FindField( newname );
1036 if( !existingField )
1037 field->SetName( newname );
1041 if( !existingField )
1043 aSymbol->AddDrawItem( field.get(),
false );
1045 return field.release();
1058 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1059 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1065 bool hasMidPoint =
false;
1073 bool hasAngles =
false;
1075 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1082 if( token == T_private )
1084 arc->SetPrivate(
true );
1088 for( ; token != T_RIGHT; token = NextTok() )
1090 if( token != T_LEFT )
1091 Expecting( T_LEFT );
1114 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1116 if( token != T_LEFT )
1117 Expecting( T_LEFT );
1145 Expecting(
"at, length, or angles" );
1153 arc->SetStroke( stroke );
1159 arc->SetFillColor( fill.
m_Color );
1163 Expecting(
"start, mid, end, radius, stroke, or fill" );
1169 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1180 EDA_ANGLE arc_start, arc_end, arc_angle;
1181 arc->CalcArcAngles( arc_start, arc_end );
1182 arc_angle = arc_end - arc_start;
1187 arc->SetStart( endPoint );
1188 arc->SetEnd( startPoint );
1191 arc->SetCenter( new_center );
1197 arc->SetCenter( new_center );
1201 else if( hasAngles )
1203 arc->SetCenter( center );
1209 arc->SetStart( endPoint );
1210 arc->SetEnd( startPoint );
1214 EDA_ANGLE arc_start, arc_end, arc_angle;
1215 arc->CalcArcAngles( arc_start, arc_end );
1216 arc_angle = arc_end - arc_start;
1222 arc->SetStart( startPoint );
1223 arc->SetEnd( endPoint );
1227 arc->SetStart( startPoint );
1228 arc->SetEnd( endPoint );
1231 arc->SetCenter( new_center );
1236 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1239 return arc.release();
1245 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1246 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1252 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1254 bezier->SetUnit(
m_unit );
1259 if( token == T_private )
1261 bezier->SetPrivate(
true );
1265 for( ; token != T_RIGHT; token = NextTok() )
1267 if( token != T_LEFT )
1268 Expecting( T_LEFT );
1278 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1280 if( token != T_LEFT )
1281 Expecting( T_LEFT );
1290 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1291 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1292 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1293 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1294 default: Unexpected(
"control point" );
break;
1304 bezier->SetStroke( stroke );
1310 bezier->SetFillColor( fill.
m_Color );
1314 Expecting(
"pts, stroke, or fill" );
1318 bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1320 return bezier.release();
1326 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1327 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1335 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1337 circle->SetUnit(
m_unit );
1342 if( token == T_private )
1344 circle->SetPrivate(
true );
1348 for( ; token != T_RIGHT; token = NextTok() )
1350 if( token != T_LEFT )
1351 Expecting( T_LEFT );
1369 circle->SetStroke( stroke );
1375 circle->SetFillColor( fill.
m_Color );
1379 Expecting(
"center, radius, stroke, or fill" );
1383 circle->SetCenter( center );
1384 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1386 return circle.release();
1397 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1398 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1399 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1400 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1401 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1402 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1403 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1404 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1405 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1406 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1408 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1409 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1412 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1413 "power_in, power_out, open_collector, open_emitter, free or "
1415 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1424 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1425 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1426 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1427 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1428 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1429 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1430 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1431 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1432 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1435 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1436 "output_low, edge_clock_high, non_logic" );
1437 return GRAPHIC_PINSHAPE::LINE;
1441 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1442 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1447 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1454 pin->SetType( parseType( token ) );
1458 pin->SetShape( parseShape( token ) );
1460 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1462 if( token == T_hide )
1464 pin->SetVisible(
false );
1468 if( token != T_LEFT )
1469 Expecting( T_LEFT );
1478 switch(
parseInt(
"pin orientation" ) )
1480 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1481 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1482 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1483 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1484 default: Expecting(
"0, 90, 180, or 270" );
1498 if( !IsSymbol( token ) )
1507 pin->SetName( FromUTF8() );
1511 if( token != T_RIGHT )
1515 if( token == T_effects )
1522 pin->SetNameTextSize(
text.GetTextHeight() );
1527 Expecting(
"effects" );
1536 if( !IsSymbol( token ) )
1539 CurLineNumber(), CurOffset() );
1542 pin->SetNumber( FromUTF8() );
1545 if( token != T_RIGHT )
1549 if( token == T_effects )
1556 pin->SetNumberTextSize(
text.GetTextHeight() );
1561 Expecting(
"effects" );
1573 if( !IsSymbol( token ) )
1576 CurLineNumber(), CurOffset() );
1582 alt.
m_Type = parseType( token );
1585 alt.
m_Shape = parseShape( token );
1587 pin->GetAlternates()[ alt.
m_Name ] = alt;
1594 Expecting(
"at, name, number, length, or alternate" );
1598 return pin.release();
1604 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1605 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1610 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1617 if( token == T_private )
1619 poly->SetPrivate(
true );
1623 for( ; token != T_RIGHT; token = NextTok() )
1625 if( token != T_LEFT )
1626 Expecting( T_LEFT );
1633 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1635 if( token != T_LEFT )
1636 Expecting( T_LEFT );
1643 poly->AddPoint(
parseXY(
true ) );
1652 poly->SetStroke( stroke );
1658 poly->SetFillColor( fill.
m_Color );
1662 Expecting(
"pts, stroke, or fill" );
1666 return poly.release();
1672 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1673 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1678 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1680 rectangle->SetUnit(
m_unit );
1685 if( token == T_private )
1687 rectangle->SetPrivate(
true );
1691 for( ; token != T_RIGHT; token = NextTok() )
1693 if( token != T_LEFT )
1694 Expecting( T_LEFT );
1701 rectangle->SetPosition(
parseXY(
true ) );
1706 rectangle->SetEnd(
parseXY(
true ) );
1712 rectangle->SetStroke( stroke );
1718 rectangle->SetFillColor( fill.
m_Color );
1722 Expecting(
"start, end, stroke, or fill" );
1726 return rectangle.release();
1732 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1733 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1736 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1743 if( token == T_private )
1745 text->SetPrivate(
true );
1749 if( !IsSymbol( token ) )
1751 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1755 text->SetText( FromUTF8() );
1757 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1759 if( token != T_LEFT )
1760 Expecting( T_LEFT );
1778 Expecting(
"at or effects" );
1782 return text.release();
1788 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1789 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1801 bool foundEnd =
false;
1802 bool foundSize =
false;
1803 bool foundMargins =
false;
1805 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1807 textBox->SetUnit(
m_unit );
1811 if( token == T_private )
1813 textBox->SetPrivate(
true );
1817 if( !IsSymbol( token ) )
1819 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1823 textBox->SetText( FromUTF8() );
1825 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1827 if( token != T_LEFT )
1828 Expecting( T_LEFT );
1859 textBox->SetStroke( stroke );
1865 textBox->SetFillColor( fill.
m_Color );
1870 textBox->SetMarginLeft(
left );
1871 textBox->SetMarginTop( top );
1872 textBox->SetMarginRight(
right );
1873 textBox->SetMarginBottom( bottom );
1874 foundMargins =
true;
1883 Expecting(
"at, size, stroke, fill or effects" );
1887 textBox->SetPosition( pos );
1890 textBox->SetEnd( end );
1891 else if( foundSize )
1892 textBox->SetEnd( pos + size );
1894 Expecting(
"size" );
1898 int margin = textBox->GetLegacyTextMargin();
1899 textBox->SetMarginLeft( margin );
1900 textBox->SetMarginTop( margin );
1901 textBox->SetMarginRight( margin );
1902 textBox->SetMarginBottom( margin );
1905 return textBox.release();
1911 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1912 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1918 wxString pageType = FromUTF8();
1920 if( !aPageInfo.
SetType( pageType ) )
1922 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1949 if( token == T_portrait )
1954 else if( token != T_RIGHT )
1956 Expecting(
"portrait" );
1963 wxCHECK_RET( CurTok() == T_title_block,
1964 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
1968 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1970 if( token != T_LEFT )
1971 Expecting( T_LEFT );
1979 aTitleBlock.
SetTitle( FromUTF8() );
1984 aTitleBlock.
SetDate( FromUTF8() );
1999 int commentNumber =
parseInt(
"comment" );
2001 switch( commentNumber )
2050 CurLine(), CurLineNumber(), CurOffset() );
2057 Expecting(
"title, date, rev, company, or comment" );
2067 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2068 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2070 T token = NextTok();
2072 if( !IsSymbol( token ) )
2074 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2078 wxString
name = FromUTF8();
2080 if(
name.IsEmpty() )
2082 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2088 if( !IsSymbol( token ) )
2090 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2095 wxString value = FromUTF8();
2097 int mandatoryFieldCount = 0;
2104 std::unique_ptr<SCH_FIELD> field =
2105 std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), mandatoryFieldCount, aParent,
name );
2106 field->SetText( value );
2107 field->SetVisible(
true );
2132 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2137 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2145 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2147 if( token != T_LEFT )
2148 Expecting( T_LEFT );
2159 if(
id >= mandatoryFieldCount )
2166 field->SetPosition(
parseXY() );
2178 field->SetNameShown( show );
2182 case T_do_not_autoplace:
2185 field->SetCanAutoplace( !doNotAutoplace );
2190 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2194 return field.release();
2200 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2201 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2202 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2204 T token = NextTok();
2206 if( !IsSymbol( token ) )
2208 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2212 wxString
name = FromUTF8();
2214 if(
name.IsEmpty() )
2216 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2220 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2226 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2227 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2228 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2229 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2230 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2232 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2235 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2237 if( token != T_LEFT )
2238 Expecting( T_LEFT );
2246 sheetPin->SetPosition(
parseXY() );
2248 double angle =
parseDouble(
"sheet pin angle (side)" );
2251 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2252 else if( angle == 90.0 )
2253 sheetPin->SetSide( SHEET_SIDE::TOP );
2254 else if( angle == 180.0 )
2255 sheetPin->SetSide( SHEET_SIDE::LEFT );
2256 else if( angle == 270.0 )
2257 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2259 Expecting(
"0, 90, 180, or 270" );
2276 Expecting(
"at, uuid or effects" );
2280 return sheetPin.release();
2286 wxCHECK_RET( CurTok() == T_sheet_instances,
2287 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2288 wxCHECK( aScreen, );
2292 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2294 if( token != T_LEFT )
2295 Expecting( T_LEFT );
2313 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2315 if( token != T_LEFT )
2316 Expecting( T_LEFT );
2320 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2323 size_t numReplacements = 0;
2341 for(
const wxString& ch : whitespaces )
2342 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2347 if( numReplacements > 0 )
2354 Expecting(
"path or page" );
2359 && ( instance.
m_Path.empty() ) )
2375 Expecting(
"path" );
2383 wxCHECK_RET( CurTok() == T_symbol_instances,
2384 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2385 wxCHECK( aScreen, );
2390 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2392 if( token != T_LEFT )
2393 Expecting( T_LEFT );
2410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2412 if( token != T_LEFT )
2413 Expecting( T_LEFT );
2432 instance.
m_Value = FromUTF8();
2443 Expecting(
"path, unit, value or footprint" );
2452 Expecting(
"path" );
2461 wxCHECK( aSheet !=
nullptr, );
2465 wxCHECK( screen !=
nullptr, );
2467 if( aIsCopyableOnly )
2470 bool fileHasUuid =
false;
2484 if( !aIsCopyableOnly )
2489 if( CurTok() != T_kicad_sch )
2490 Expecting(
"kicad_sch" );
2506 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2508 if( aIsCopyableOnly && token == T_EOF )
2511 if( token != T_LEFT )
2512 Expecting( T_LEFT );
2542 case T_generator_version:
2568 if( aIsCopyableOnly )
2569 Unexpected( T_paper );
2579 if( aIsCopyableOnly )
2580 Unexpected( T_page );
2584 NeedSYMBOLorNUMBER();
2585 NeedSYMBOLorNUMBER();
2592 if( aIsCopyableOnly )
2593 Unexpected( T_title_block );
2607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2609 if( token != T_LEFT )
2610 Expecting( T_LEFT );
2623 Expecting(
"symbol" );
2724 case T_netclass_flag:
2729 case T_global_label:
2730 case T_hierarchical_label:
2731 case T_directive_label:
2743 case T_sheet_instances:
2747 case T_symbol_instances:
2752 if( aIsCopyableOnly )
2753 Unexpected( T_bus_alias );
2759 Expecting(
"symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2760 "bus_entry, line, bus, text, label, class_label, global_label, "
2761 "hierarchical_label, symbol_instances, rule_area, or bus_alias" );
2782 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2783 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2788 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2790 std::set<int> fieldIDsRead;
2793 symbol->ClearFieldsAutoplaced();
2803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2805 if( token != T_LEFT )
2806 Expecting( T_LEFT );
2818 if( !IsSymbol( token ) )
2821 CurLineNumber(), CurOffset() );
2824 libName = FromUTF8();
2828 libName.Replace(
"{slash}",
"/" );
2838 if( !IsSymbol( token ) && token != T_NUMBER )
2839 Expecting(
"symbol|number" );
2842 wxString
name = FromUTF8();
2846 name.Replace(
"{slash}",
"/" );
2852 if(
static_cast<int>(
name.size() ) > bad_pos )
2854 wxString msg = wxString::Format(
2855 _(
"Symbol %s contains invalid character '%c'" ),
name,
2862 CurLineNumber(), CurOffset() );
2865 symbol->SetLibId( libId );
2871 symbol->SetPosition(
parseXY() );
2873 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
2876 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
2877 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
2878 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
2879 default: Expecting(
"0, 90, 180, or 270" );
2882 symbol->SetTransform( transform );
2891 else if( token == T_y )
2894 Expecting(
"x or y" );
2900 symbol->SetUnit(
parseInt(
"symbol unit" ) );
2905 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
2909 case T_exclude_from_sim:
2910 symbol->SetExcludedFromSim(
parseBool() );
2915 symbol->SetExcludedFromBOM( !
parseBool() );
2920 symbol->SetExcludedFromBoard( !
parseBool() );
2929 case T_fields_autoplaced:
2931 symbol->SetFieldsAutoplaced();
2941 case T_default_instance:
2945 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2947 if( token != T_LEFT )
2948 Expecting( T_LEFT );
2967 symbol->SetValueFieldText( FromUTF8() );
2973 symbol->SetFootprintFieldText( FromUTF8() );
2978 Expecting(
"reference, unit, value or footprint" );
2987 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2989 if( token != T_LEFT )
2990 Expecting( T_LEFT );
2994 if( token != T_project )
2995 Expecting(
"project" );
2999 wxString projectName = FromUTF8();
3001 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3003 if( token != T_LEFT )
3004 Expecting( T_LEFT );
3008 if( token != T_path )
3009 Expecting(
"path" );
3018 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3020 if( token != T_LEFT )
3021 Expecting( T_LEFT );
3040 symbol->SetValueFieldText( FromUTF8() );
3046 symbol->SetFootprintFieldText( FromUTF8() );
3051 Expecting(
"reference, unit, value or footprint" );
3054 symbol->AddHierarchicalReference( instance );
3071 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3078 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3084 int nextAvailableId = field->
GetId() + 1;
3087 nextAvailableId += 1;
3089 field->
SetId( nextAvailableId );
3092 if( symbol->GetFieldById( field->
GetId() ) )
3093 *symbol->GetFieldById( field->
GetId() ) = *field;
3095 symbol->AddField( *field );
3098 symbol->UpdatePrefix();
3113 number = FromUTF8();
3115 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3117 if( token != T_LEFT )
3118 Expecting( T_LEFT );
3142 Expecting(
"alternate or uuid" );
3146 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3152 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3153 "default_instance, property, pin, or instances" );
3157 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3158 symbol->SetSchSymbolLibraryName( libName );
3161 symbol->ClearFlags();
3163 return symbol.release();
3169 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3170 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3173 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3175 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3177 if( token != T_LEFT )
3178 Expecting( T_LEFT );
3185 bitmap->SetPosition(
parseXY() );
3190 bitmap->GetImage()->SetScale(
parseDouble(
"image scale factor" ) );
3192 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3193 bitmap->GetImage()->SetScale( 1.0 );
3212 data.reserve( 1 << 17 );
3214 while( token != T_RIGHT )
3216 if( !IsSymbol( token ) )
3217 Expecting(
"base64 image data" );
3223 wxMemoryBuffer buffer = wxBase64Decode( data );
3225 if( !bitmap->GetImage()->ReadImageFile( buffer ) )
3232 Expecting(
"at, scale, uuid or data" );
3247 return bitmap.release();
3253 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3254 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3260 std::vector<SCH_FIELD> fields;
3261 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3262 std::set<int> fieldIDsRead;
3265 sheet->ClearFieldsAutoplaced();
3267 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3269 if( token != T_LEFT )
3270 Expecting( T_LEFT );
3277 sheet->SetPosition(
parseXY() );
3286 sheet->SetSize( size );
3291 case T_fields_autoplaced:
3293 sheet->SetFieldsAutoplaced();
3299 sheet->SetBorderWidth( stroke.
GetWidth() );
3300 sheet->SetBorderColor( stroke.
GetColor() );
3305 sheet->SetBackgroundColor( fill.
m_Color );
3322 if( fields.empty() )
3336 if( field->
GetId() < 0 )
3339 while( !fieldIDsRead.insert( field->
GetId() ).second )
3342 fields.emplace_back( *field );
3352 std::vector<SCH_SHEET_INSTANCE> instances;
3354 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3356 if( token != T_LEFT )
3357 Expecting( T_LEFT );
3361 if( token != T_project )
3362 Expecting(
"project" );
3366 wxString projectName = FromUTF8();
3368 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3370 if( token != T_LEFT )
3371 Expecting( T_LEFT );
3375 if( token != T_path )
3376 Expecting(
"path" );
3385 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3387 if( token != T_LEFT )
3388 Expecting( T_LEFT );
3408 static std::vector<wxString> whitespaces =
3414 for( wxString ch : whitespaces )
3423 Expecting(
"page" );
3427 instances.emplace_back( instance );
3431 sheet->setInstances( instances );
3436 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3440 sheet->SetFields( fields );
3442 return sheet.release();
3448 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3449 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3452 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3454 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3456 if( token != T_LEFT )
3457 Expecting( T_LEFT );
3464 junction->SetPosition(
parseXY() );
3482 junction->SetColor(
color );
3494 Expecting(
"at, diameter, color or uuid" );
3498 return junction.release();
3504 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3505 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3508 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3510 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3512 if( token != T_LEFT )
3513 Expecting( T_LEFT );
3520 no_connect->SetPosition(
parseXY() );
3531 Expecting(
"at or uuid" );
3535 return no_connect.release();
3541 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3542 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3546 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3548 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3550 if( token != T_LEFT )
3551 Expecting( T_LEFT );
3558 busEntry->SetPosition(
parseXY() );
3568 busEntry->SetSize( size );
3575 busEntry->SetStroke( stroke );
3585 Expecting(
"at, size, uuid or stroke" );
3589 return busEntry.release();
3599 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3601 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3603 if( token != T_LEFT )
3604 Expecting( T_LEFT );
3611 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3613 if( token != T_LEFT )
3614 Expecting( T_LEFT );
3621 polyline->AddPoint(
parseXY() );
3634 polyline->SetStroke( stroke );
3640 polyline->SetFillColor( fill.
m_Color );
3650 Expecting(
"pts, uuid, stroke, or fill" );
3654 return polyline.release();
3673 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3676 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3678 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3680 if( token != T_LEFT )
3681 Expecting( T_LEFT );
3694 line->SetStartPoint(
parseXY() );
3702 line->SetEndPoint(
parseXY() );
3709 line->SetStroke( stroke );
3719 Expecting(
"at, uuid or stroke" );
3723 return line.release();
3729 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3730 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3738 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3740 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3742 if( token != T_LEFT )
3743 Expecting( T_LEFT );
3766 arc->SetStroke( stroke );
3772 arc->SetFillColor( fill.
m_Color );
3777 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3782 Expecting(
"start, mid, end, stroke, fill or uuid" );
3786 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3788 return arc.release();
3794 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3795 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3802 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3804 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3806 if( token != T_LEFT )
3807 Expecting( T_LEFT );
3825 circle->SetStroke( stroke );
3831 circle->SetFillColor( fill.
m_Color );
3836 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
3841 Expecting(
"center, radius, stroke, fill or uuid" );
3845 circle->SetCenter( center );
3846 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
3848 return circle.release();
3854 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
3855 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
3860 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
3862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3864 if( token != T_LEFT )
3865 Expecting( T_LEFT );
3872 rectangle->SetPosition(
parseXY() );
3877 rectangle->SetEnd(
parseXY() );
3883 rectangle->SetStroke( stroke );
3889 rectangle->SetFillColor( fill.
m_Color );
3894 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
3899 Expecting(
"start, end, stroke, fill or uuid" );
3903 return rectangle.release();
3909 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
3910 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
3915 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
3917 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3919 if( token != T_LEFT )
3920 Expecting( T_LEFT );
3929 ruleArea->SetPolyShape( poly->GetPolyShape() );
3930 ruleArea->SetStroke( poly->GetStroke() );
3931 ruleArea->SetFillMode( poly->GetFillMode() );
3932 ruleArea->SetFillColor( poly->GetFillColor() );
3936 Expecting(
"polyline" );
3940 return ruleArea.release();
3946 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
3947 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
3952 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
3954 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3956 if( token != T_LEFT )
3957 Expecting( T_LEFT );
3967 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
3969 if( token != T_LEFT )
3970 Expecting( T_LEFT );
3979 case 0: bezier->SetStart(
parseXY() );
break;
3980 case 1: bezier->SetBezierC1(
parseXY() );
break;
3981 case 2: bezier->SetBezierC2(
parseXY() );
break;
3982 case 3: bezier->SetEnd(
parseXY() );
break;
3983 default: Unexpected(
"control point" );
break;
3993 bezier->SetStroke( stroke );
3999 bezier->SetFillColor( fill.
m_Color );
4004 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4009 Expecting(
"pts, stroke, fill or uuid" );
4013 return bezier.release();
4020 std::unique_ptr<SCH_TEXT>
text;
4024 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4025 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4026 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4027 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4028 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4029 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4031 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4035 text->ClearFieldsAutoplaced();
4039 text->SetText( FromUTF8() );
4041 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4043 if( token != T_LEFT )
4044 Expecting( T_LEFT );
4050 case T_exclude_from_sim:
4061 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4077 Unexpected( T_shape );
4085 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4086 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4087 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4088 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4089 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4090 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4091 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4092 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4093 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4095 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4106 Unexpected( T_length );
4115 case T_fields_autoplaced:
4117 text->SetFieldsAutoplaced();
4147 Unexpected( T_property );
4174 Expecting(
"at, shape, iref, uuid or effects" );
4180 if( label && label->
GetFields().empty() )
4183 return text.release();
4189 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4190 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4192 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4196 return textBox.release();
4202 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4203 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4205 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4209 return cell.release();
4225 bool foundEnd =
false;
4226 bool foundSize =
false;
4227 bool foundMargins =
false;
4231 aTextBox->
SetText( FromUTF8() );
4233 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4235 if( token != T_LEFT )
4236 Expecting( T_LEFT );
4242 case T_exclude_from_sim:
4273 cell->SetColSpan(
parseInt(
"column span" ) );
4274 cell->SetRowSpan(
parseInt(
"row span" ) );
4278 Expecting(
"at, size, stroke, fill, effects or uuid" );
4301 foundMargins =
true;
4317 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4319 Expecting(
"at, size, stroke, fill, effects or uuid" );
4327 else if( foundSize )
4328 aTextBox->
SetEnd( pos + size );
4330 Expecting(
"size" );
4345 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4346 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4350 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4351 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4352 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4354 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4356 if( token != T_LEFT )
4357 Expecting( T_LEFT );
4363 case T_column_count:
4364 table->SetColCount(
parseInt(
"column count" ) );
4368 case T_column_widths:
4372 while( ( token = NextTok() ) != T_RIGHT )
4382 while( ( token = NextTok() ) != T_RIGHT )
4389 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4391 if( token != T_LEFT )
4392 Expecting( T_LEFT );
4396 if( token != T_table_cell )
4397 Expecting(
"table_cell" );
4405 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4407 if( token != T_LEFT )
4408 Expecting( T_LEFT );
4415 table->SetStrokeExternal(
parseBool() );
4426 table->SetBorderStroke( borderStroke );
4430 Expecting(
"external, header or stroke" );
4438 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4440 if( token != T_LEFT )
4441 Expecting( T_LEFT );
4459 table->SetSeparatorsStroke( separatorsStroke );
4463 Expecting(
"rows, cols, or stroke" );
4471 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4475 return table.release();
4481 wxCHECK_RET( CurTok() == T_bus_alias,
4482 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4483 wxCHECK( aScreen, );
4486 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4497 busAlias->SetName( alias );
4502 if( token != T_members )
4503 Expecting(
"members" );
4507 while( token != T_RIGHT )
4509 if( !IsSymbol( token ) )
4510 Expecting(
"quoted string" );
4512 member = FromUTF8();
4517 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.
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_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.