KiCad PCB EDA Suite
SCH_SEXPR_PARSER Class Reference

Object to parser s-expression symbol library and schematic file formats. More...

#include <sch_sexpr_parser.h>

Inheritance diagram for SCH_SEXPR_PARSER:

Public Member Functions

 SCH_SEXPR_PARSER (LINE_READER *aLineReader=nullptr)
 
void ParseLib (LIB_PART_MAP &aSymbolLibMap)
 
LIB_PARTParseSymbol (LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
 
LIB_ITEMParseDrawItem ()
 
void ParseSchematic (SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
 Parse the internal LINE_READER object into aSheet. More...
 
bool IsTooRecent () const
 Return whether a version number, if any was parsed, was too recent. More...
 

Private Member Functions

void parseHeader (TSCHEMATIC_T::T aHeaderType, int aFileVersion)
 
long parseHex ()
 
int parseInt ()
 
int parseInt (const char *aExpected)
 
double parseDouble ()
 Parse the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number. More...
 
double parseDouble (const char *aExpected)
 
double parseDouble (TSCHEMATIC_T::T aToken)
 
int parseInternalUnits ()
 
int parseInternalUnits (const char *aExpected)
 
int parseInternalUnits (TSCHEMATIC_T::T aToken)
 
wxPoint parseXY ()
 
bool parseBool ()
 
void parseStroke (STROKE_PARAMS &aStroke)
 Parse stroke definition aStroke. More...
 
void parseFill (FILL_PARAMS &aFill)
 
void parseEDA_TEXT (EDA_TEXT *aText)
 
void parsePinNames (std::unique_ptr< LIB_PART > &aSymbol)
 
LIB_FIELDparseProperty (std::unique_ptr< LIB_PART > &aSymbol)
 
LIB_ARCparseArc ()
 
LIB_BEZIERparseBezier ()
 
LIB_CIRCLEparseCircle ()
 
LIB_PINparsePin ()
 
LIB_POLYLINEparsePolyLine ()
 
LIB_RECTANGLEparseRectangle ()
 
LIB_TEXTparseText ()
 
void parsePAGE_INFO (PAGE_INFO &aPageInfo)
 
void parseTITLE_BLOCK (TITLE_BLOCK &aTitleBlock)
 
void parseSchSymbolInstances (SCH_SCREEN *aScreen)
 
void parseSchSheetInstances (SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
 
SCH_SHEET_PINparseSchSheetPin (SCH_SHEET *aSheet)
 
SCH_FIELDparseSchField (SCH_ITEM *aParent)
 
SCH_COMPONENTparseSchematicSymbol ()
 
SCH_BITMAPparseImage ()
 
SCH_SHEETparseSheet ()
 
SCH_JUNCTIONparseJunction ()
 
SCH_NO_CONNECTparseNoConnect ()
 
SCH_BUS_WIRE_ENTRYparseBusEntry ()
 
SCH_LINEparseLine ()
 
SCH_TEXTparseSchText ()
 
void parseBusAlias (SCH_SCREEN *aScreen)
 

Private Attributes

int m_requiredVersion
 Set to the symbol library file version required. More...
 
int m_fieldId
 The current field ID. More...
 
int m_unit
 The current unit being parsed. More...
 
int m_convert
 The current body style being parsed. More...
 
wxString m_symbolName
 The current symbol name. More...
 

Detailed Description

Object to parser s-expression symbol library and schematic file formats.

Definition at line 79 of file sch_sexpr_parser.h.

Constructor & Destructor Documentation

◆ SCH_SEXPR_PARSER()

SCH_SEXPR_PARSER::SCH_SEXPR_PARSER ( LINE_READER aLineReader = nullptr)

Definition at line 60 of file sch_sexpr_parser.cpp.

60  :
61  SCHEMATIC_LEXER( aLineReader ),
62  m_requiredVersion( 0 ),
63  m_fieldId( 0 ),
64  m_unit( 1 ),
65  m_convert( 1 )
66 {
67 }
int m_fieldId
The current field ID.
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
int m_requiredVersion
Set to the symbol library file version required.

Member Function Documentation

◆ IsTooRecent()

bool SCH_SEXPR_PARSER::IsTooRecent ( ) const

Return whether a version number, if any was parsed, was too recent.

Definition at line 85 of file sch_sexpr_parser.cpp.

86 {
88 }
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
int m_requiredVersion
Set to the symbol library file version required.

References m_requiredVersion, and SEXPR_SYMBOL_LIB_FILE_VERSION.

◆ parseArc()

LIB_ARC * SCH_SEXPR_PARSER::parseArc ( )
private

Definition at line 886 of file sch_sexpr_parser.cpp.

887 {
888  wxCHECK_MSG( CurTok() == T_arc, nullptr,
889  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc token." ) );
890 
891  T token;
892  wxPoint startPoint;
893  wxPoint midPoint;
894  wxPoint endPoint;
895  wxPoint pos;
896  FILL_PARAMS fill;
897  bool hasMidPoint = false;
898  std::unique_ptr<LIB_ARC> arc = std::make_unique<LIB_ARC>( nullptr );
899 
900  arc->SetUnit( m_unit );
901  arc->SetConvert( m_convert );
902 
903  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
904  {
905  if( token != T_LEFT )
906  Expecting( T_LEFT );
907 
908  token = NextTok();
909 
910  switch( token )
911  {
912  case T_start:
913  startPoint = parseXY();
914  NeedRIGHT();
915  break;
916 
917  case T_mid:
918  midPoint = parseXY();
919  NeedRIGHT();
920  hasMidPoint = true;
921  break;
922 
923  case T_end:
924  endPoint = parseXY();
925  NeedRIGHT();
926  break;
927 
928  case T_radius:
929  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
930  {
931  if( token != T_LEFT )
932  Expecting( T_LEFT );
933 
934  token = NextTok();
935 
936  switch( token )
937  {
938  case T_at:
939  pos = parseXY();
940  NeedRIGHT();
941  break;
942 
943  case T_length:
944  arc->SetRadius( parseInternalUnits( "radius length" ) );
945  NeedRIGHT();
946  break;
947 
948  case T_angles:
949  {
950  int angle1 = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
951  int angle2 = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
952 
953  NORMALIZE_ANGLE_POS( angle1 );
954  NORMALIZE_ANGLE_POS( angle2 );
955  arc->SetFirstRadiusAngle( angle1 );
956  arc->SetSecondRadiusAngle( angle2 );
957  NeedRIGHT();
958  break;
959  }
960 
961  default:
962  Expecting( "at, length, or angle" );
963  }
964  }
965 
966  break;
967 
968  case T_stroke:
969  NeedLEFT();
970  token = NextTok();
971 
972  if( token != T_width )
973  Expecting( "width" );
974 
975  arc->SetWidth( parseInternalUnits( "stroke width" ) );
976  NeedRIGHT(); // Closes width token;
977  NeedRIGHT(); // Closes stroke token;
978  break;
979 
980  case T_fill:
981  parseFill( fill );
982  arc->SetFillMode( fill.m_FillType );
983  break;
984 
985  default:
986  Expecting( "start, end, radius, stroke, or fill" );
987  }
988  }
989 
990  arc->SetPosition( pos );
991  arc->SetStart( startPoint );
992  arc->SetEnd( endPoint );
993 
994  if( hasMidPoint )
995  {
996  VECTOR2I center = GetArcCenter( arc->GetStart(), midPoint, arc->GetEnd() );
997 
998  arc->SetPosition( wxPoint( center.x, center.y ) );
999 
1000  // @todo Calculate the radius.
1001 
1002  arc->CalcRadiusAngles();
1003  }
1004 
1005  return arc.release();
1006 }
int m_unit
The current unit being parsed.
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:288
FILL_TYPE m_FillType
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void parseFill(FILL_PARAMS &aFill)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
const VECTOR2I GetArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:450

References GetArcCenter(), KiROUND(), m_convert, FILL_PARAMS::m_FillType, m_unit, NORMALIZE_ANGLE_POS(), parseDouble(), parseFill(), parseInternalUnits(), parseXY(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by ParseDrawItem().

◆ parseBezier()

LIB_BEZIER * SCH_SEXPR_PARSER::parseBezier ( )
private

Definition at line 1009 of file sch_sexpr_parser.cpp.

1010 {
1011  wxCHECK_MSG( CurTok() == T_bezier, nullptr,
1012  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
1013 
1014  T token;
1015  FILL_PARAMS fill;
1016  std::unique_ptr<LIB_BEZIER> bezier = std::make_unique<LIB_BEZIER>( nullptr );
1017 
1018  bezier->SetUnit( m_unit );
1019  bezier->SetConvert( m_convert );
1020 
1021  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1022  {
1023  if( token != T_LEFT )
1024  Expecting( T_LEFT );
1025 
1026  token = NextTok();
1027 
1028  switch( token )
1029  {
1030  case T_pts:
1031  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1032  {
1033  if( token != T_LEFT )
1034  Expecting( T_LEFT );
1035 
1036  token = NextTok();
1037 
1038  if( token != T_xy )
1039  Expecting( "xy" );
1040 
1041  bezier->AddPoint( parseXY() );
1042 
1043  NeedRIGHT();
1044  }
1045 
1046  break;
1047 
1048  case T_stroke:
1049  NeedLEFT();
1050  token = NextTok();
1051 
1052  if( token != T_width )
1053  Expecting( "width" );
1054 
1055  bezier->SetWidth( parseInternalUnits( "stroke width" ) );
1056  NeedRIGHT(); // Closes width token;
1057  NeedRIGHT(); // Closes stroke token;
1058  break;
1059 
1060  case T_fill:
1061  parseFill( fill );
1062  bezier->SetFillMode( fill.m_FillType );
1063  break;
1064 
1065  default:
1066  Expecting( "pts, stroke, or fill" );
1067  }
1068  }
1069 
1070  return bezier.release();
1071 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseBool()

bool SCH_SEXPR_PARSER::parseBool ( )
private

Definition at line 70 of file sch_sexpr_parser.cpp.

71 {
72  T token = NextTok();
73 
74  if( token == T_yes )
75  return true;
76  else if( token == T_no )
77  return false;
78  else
79  Expecting( "yes or no" );
80 
81  return false;
82 }

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ parseBusAlias()

void SCH_SEXPR_PARSER::parseBusAlias ( SCH_SCREEN aScreen)
private

Definition at line 2947 of file sch_sexpr_parser.cpp.

2948 {
2949  wxCHECK_RET( CurTok() == T_bus_alias,
2950  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
2951  wxCHECK( aScreen, /* void */ );
2952 
2953  T token;
2954  auto busAlias = std::make_shared<BUS_ALIAS>( aScreen );
2955 
2956  NeedSYMBOL();
2957  busAlias->SetName( FromUTF8() );
2958  NeedLEFT();
2959  token = NextTok();
2960 
2961  if( token != T_members )
2962  Expecting( "members" );
2963 
2964  token = NextTok();
2965 
2966  while( token != T_RIGHT )
2967  {
2968  if( !IsSymbol( token ) )
2969  Expecting( "quoted string" );
2970 
2971  busAlias->AddMember( FromUTF8() );
2972  token = NextTok();
2973  }
2974 
2975  NeedRIGHT();
2976 
2977  aScreen->AddBusAlias( busAlias );
2978 }
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).

References SCH_SCREEN::AddBusAlias().

Referenced by ParseSchematic().

◆ parseBusEntry()

SCH_BUS_WIRE_ENTRY * SCH_SEXPR_PARSER::parseBusEntry ( )
private

Definition at line 2709 of file sch_sexpr_parser.cpp.

2710 {
2711  wxCHECK_MSG( CurTok() == T_bus_entry, nullptr,
2712  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus entry." ) );
2713 
2714  T token;
2715  STROKE_PARAMS stroke;
2716  std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
2717 
2718  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2719  {
2720  if( token != T_LEFT )
2721  Expecting( T_LEFT );
2722 
2723  token = NextTok();
2724 
2725  switch( token )
2726  {
2727  case T_at:
2728  busEntry->SetPosition( parseXY() );
2729  NeedRIGHT();
2730  break;
2731 
2732  case T_size:
2733  {
2734  wxSize size;
2735 
2736  size.SetWidth( parseInternalUnits( "bus entry height" ) );
2737  size.SetHeight( parseInternalUnits( "bus entry width" ) );
2738  busEntry->SetSize( size );
2739  NeedRIGHT();
2740  break;
2741  }
2742 
2743  case T_stroke:
2744  parseStroke( stroke );
2745  busEntry->SetStroke( stroke );
2746  break;
2747 
2748  case T_uuid:
2749  NeedSYMBOL();
2750  const_cast<KIID&>( busEntry->m_Uuid ) = KIID( FromUTF8() );
2751  NeedRIGHT();
2752  break;
2753 
2754  default:
2755  Expecting( "at, size, uuid or stroke" );
2756  }
2757  }
2758 
2759  return busEntry.release();
2760 }
Definition: kiid.h:44
Simple container to manage line stroke parameters.
Definition: sch_item.h:155
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References parseInternalUnits(), parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseCircle()

LIB_CIRCLE * SCH_SEXPR_PARSER::parseCircle ( )
private

Definition at line 1074 of file sch_sexpr_parser.cpp.

1075 {
1076  wxCHECK_MSG( CurTok() == T_circle, nullptr,
1077  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle token." ) );
1078 
1079  T token;
1080  FILL_PARAMS fill;
1081  std::unique_ptr<LIB_CIRCLE> circle = std::make_unique<LIB_CIRCLE>( nullptr );
1082 
1083  circle->SetUnit( m_unit );
1084  circle->SetConvert( m_convert );
1085 
1086  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1087  {
1088  if( token != T_LEFT )
1089  Expecting( T_LEFT );
1090 
1091  token = NextTok();
1092 
1093  switch( token )
1094  {
1095  case T_center:
1096  circle->SetPosition( parseXY() );
1097  NeedRIGHT();
1098  break;
1099 
1100  case T_radius:
1101  circle->SetRadius( parseInternalUnits( "radius length" ) );
1102  NeedRIGHT();
1103  break;
1104 
1105  case T_stroke:
1106  NeedLEFT();
1107  token = NextTok();
1108 
1109  if( token != T_width )
1110  Expecting( "width" );
1111 
1112  circle->SetWidth( parseInternalUnits( "stroke width" ) );
1113  NeedRIGHT(); // Closes width token;
1114  NeedRIGHT(); // Closes stroke token;
1115  break;
1116 
1117  case T_fill:
1118  parseFill( fill );
1119  circle->SetFillMode( fill.m_FillType );
1120  break;
1121 
1122  default:
1123  Expecting( "start, end, radius, stroke, or fill" );
1124  }
1125  }
1126 
1127  return circle.release();
1128 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseDouble() [1/3]

double SCH_SEXPR_PARSER::parseDouble ( )
private

Parse the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number.

Exceptions
IO_ERRORif an error occurs attempting to convert the current token.
Returns
The result of the parsed token.

Definition at line 414 of file sch_sexpr_parser.cpp.

415 {
416  char* tmp;
417  wxString error;
418 
419  // In case the file got saved with the wrong locale.
420  if( strchr( CurText(), ',' ) != NULL )
421  {
422  error.Printf( _( "Floating point number with incorrect local in\nfile: \"%s\"\n"
423  "line: %d\noffset: %d" ),
424  CurSource().c_str(), CurLineNumber(), CurOffset() );
425 
426  THROW_IO_ERROR( error );
427  }
428 
429  errno = 0;
430 
431  double fval = strtod( CurText(), &tmp );
432 
433  if( errno )
434  {
435  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
436  CurSource().c_str(), CurLineNumber(), CurOffset() );
437 
438  THROW_IO_ERROR( error );
439  }
440 
441  if( CurText() == tmp )
442  {
443  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
444  CurSource().c_str(), CurLineNumber(), CurOffset() );
445 
446  THROW_IO_ERROR( error );
447  }
448 
449  return fval;
450 }
#define NULL
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, NULL, and THROW_IO_ERROR.

Referenced by parseArc(), parseDouble(), parseFill(), parseImage(), parseInternalUnits(), parseJunction(), parsePAGE_INFO(), parseProperty(), parseSchematicSymbol(), parseSchField(), parseSchSheetPin(), parseSchText(), parseStroke(), and parseText().

◆ parseDouble() [2/3]

double SCH_SEXPR_PARSER::parseDouble ( const char *  aExpected)
inlineprivate

Definition at line 115 of file sch_sexpr_parser.h.

116  {
117  NeedNUMBER( aExpected );
118  return parseDouble();
119  }
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References parseDouble().

◆ parseDouble() [3/3]

double SCH_SEXPR_PARSER::parseDouble ( TSCHEMATIC_T::T  aToken)
inlineprivate

Definition at line 121 of file sch_sexpr_parser.h.

122  {
123  return parseDouble( GetTokenText( aToken ) );
124  }
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References DSN::GetTokenText(), and parseDouble().

◆ ParseDrawItem()

LIB_ITEM * SCH_SEXPR_PARSER::ParseDrawItem ( )

Definition at line 374 of file sch_sexpr_parser.cpp.

375 {
376  switch( CurTok() )
377  {
378  case T_arc:
379  return static_cast<LIB_ITEM*>( parseArc() );
380  break;
381 
382  case T_bezier:
383  return static_cast<LIB_ITEM*>( parseBezier() );
384  break;
385 
386  case T_circle:
387  return static_cast<LIB_ITEM*>( parseCircle() );
388  break;
389 
390  case T_pin:
391  return static_cast<LIB_ITEM*>( parsePin() );
392  break;
393 
394  case T_polyline:
395  return static_cast<LIB_ITEM*>( parsePolyLine() );
396  break;
397 
398  case T_rectangle:
399  return static_cast<LIB_ITEM*>( parseRectangle() );
400  break;
401 
402  case T_text:
403  return static_cast<LIB_TEXT*>( parseText() );
404  break;
405 
406  default:
407  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
408  }
409 
410  return nullptr;
411 }
LIB_POLYLINE * parsePolyLine()
LIB_RECTANGLE * parseRectangle()
LIB_BEZIER * parseBezier()
LIB_CIRCLE * parseCircle()

References parseArc(), parseBezier(), parseCircle(), parsePin(), parsePolyLine(), parseRectangle(), and parseText().

Referenced by ParseSymbol().

◆ parseEDA_TEXT()

void SCH_SEXPR_PARSER::parseEDA_TEXT ( EDA_TEXT aText)
private

Definition at line 574 of file sch_sexpr_parser.cpp.

575 {
576  wxCHECK_RET( aText && CurTok() == T_effects,
577  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
578 
579  T token;
580 
581  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
582  {
583  if( token == T_LEFT )
584  token = NextTok();
585 
586  switch( token )
587  {
588  case T_font:
589  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
590  {
591  if( token == T_LEFT )
592  token = NextTok();
593 
594  switch( token )
595  {
596  case T_size:
597  {
598  wxSize sz;
599  sz.SetHeight( parseInternalUnits( "text height" ) );
600  sz.SetWidth( parseInternalUnits( "text width" ) );
601  aText->SetTextSize( sz );
602  NeedRIGHT();
603  break;
604  }
605 
606  case T_thickness:
607  aText->SetTextThickness( parseInternalUnits( "text thickness" ) );
608  NeedRIGHT();
609  break;
610 
611  case T_bold:
612  aText->SetBold( true );
613  break;
614 
615  case T_italic:
616  aText->SetItalic( true );
617  break;
618 
619  default:
620  Expecting( "size, bold, or italic" );
621  }
622  }
623 
624  break;
625 
626  case T_justify:
627  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
628  {
629  switch( token )
630  {
631  case T_left: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); break;
632  case T_right: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); break;
633  case T_top: aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); break;
634  case T_bottom: aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); break;
635  case T_mirror: aText->SetMirrored( true ); break;
636  default: Expecting( "left, right, top, bottom, or mirror" );
637  }
638  }
639 
640  break;
641 
642  case T_hide:
643  aText->SetVisible( false );
644  break;
645 
646  default:
647  Expecting( "font, justify, or hide" );
648  }
649  }
650 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:195
void SetItalic(bool isItalic)
Definition: eda_text.h:186
void SetVisible(bool aVisible)
Definition: eda_text.h:192
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:166
void SetBold(bool aBold)
Definition: eda_text.h:189

References GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_TOP, parseInternalUnits(), EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), EDA_TEXT::SetMirrored(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetVertJustify(), and EDA_TEXT::SetVisible().

Referenced by parsePin(), parseProperty(), parseSchField(), parseSchSheetPin(), parseSchText(), and parseText().

◆ parseFill()

void SCH_SEXPR_PARSER::parseFill ( FILL_PARAMS aFill)
private

Definition at line 519 of file sch_sexpr_parser.cpp.

520 {
521  wxCHECK_RET( CurTok() == T_fill,
522  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as fill." ) );
523 
525  aFill.m_Color = COLOR4D::UNSPECIFIED;
526 
527  T token;
528 
529  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
530  {
531  if( token != T_LEFT )
532  Expecting( T_LEFT );
533 
534  token = NextTok();
535 
536  switch( token )
537  {
538  case T_type:
539  {
540  token = NextTok();
541 
542  switch( token )
543  {
544  case T_none: aFill.m_FillType = FILL_TYPE::NO_FILL; break;
545  case T_outline: aFill.m_FillType = FILL_TYPE::FILLED_SHAPE; break;
546  case T_background: aFill.m_FillType = FILL_TYPE::FILLED_WITH_BG_BODYCOLOR; break;
547  default: Expecting( "none, outline, or background" );
548  }
549 
550  NeedRIGHT();
551  break;
552  }
553 
554  case T_color:
555  {
556  COLOR4D color;
557 
558  color.r = parseInt( "red" ) / 255.0;
559  color.g = parseInt( "green" ) / 255.0;
560  color.b = parseInt( "blue" ) / 255.0;
561  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
562  aFill.m_Color = color;
563  NeedRIGHT();
564  break;
565  }
566 
567  default:
568  Expecting( "type or color" );
569  }
570  }
571 }
int color
Definition: DXF_plotter.cpp:60
FILL_TYPE m_FillType
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98

References Clamp(), color, FILLED_SHAPE, FILLED_WITH_BG_BODYCOLOR, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, NO_FILL, parseDouble(), and parseInt().

Referenced by parseArc(), parseBezier(), parseCircle(), parsePolyLine(), parseRectangle(), and parseSheet().

◆ parseHeader()

void SCH_SEXPR_PARSER::parseHeader ( TSCHEMATIC_T::T  aHeaderType,
int  aFileVersion 
)
private

Definition at line 653 of file sch_sexpr_parser.cpp.

654 {
655  wxCHECK_RET( CurTok() == aHeaderType,
656  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
657 
658  NeedLEFT();
659 
660  T tok = NextTok();
661 
662  if( tok == T_version )
663  {
664  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
665  NeedRIGHT();
666 
667  // Skip the host name and host build version information.
668  NeedLEFT();
669  NeedSYMBOL();
670  NeedSYMBOL();
671 
672  if( m_requiredVersion < 20200827 )
673  NeedSYMBOL();
674 
675  NeedRIGHT();
676  }
677  else
678  {
679  m_requiredVersion = aFileVersion;
680 
681  // Skip the host name and host build version information.
682  NeedSYMBOL();
683  NeedSYMBOL();
684  NeedRIGHT();
685  }
686 }
int m_requiredVersion
Set to the symbol library file version required.

References m_requiredVersion, and parseInt().

Referenced by ParseLib(), and ParseSchematic().

◆ parseHex()

long SCH_SEXPR_PARSER::parseHex ( )
inlineprivate

Definition at line 89 of file sch_sexpr_parser.h.

90  {
91  NextTok();
92  return strtol( CurText(), NULL, 16 );
93  }
#define NULL

References NULL.

◆ parseImage()

SCH_BITMAP * SCH_SEXPR_PARSER::parseImage ( )
private

Definition at line 2440 of file sch_sexpr_parser.cpp.

2441 {
2442  wxCHECK_MSG( CurTok() == T_image, nullptr,
2443  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an image." ) );
2444 
2445  T token;
2446  std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
2447 
2448  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2449  {
2450  if( token != T_LEFT )
2451  Expecting( T_LEFT );
2452 
2453  token = NextTok();
2454 
2455  switch( token )
2456  {
2457  case T_at:
2458  bitmap->SetPosition( parseXY() );
2459  NeedRIGHT();
2460  break;
2461 
2462  case T_scale:
2463  bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) );
2464 
2465  if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2466  bitmap->GetImage()->SetScale( 1.0 );
2467 
2468  NeedRIGHT();
2469  break;
2470 
2471  case T_uuid:
2472  NeedSYMBOL();
2473  const_cast<KIID&>( bitmap->m_Uuid ) = KIID( FromUTF8() );
2474  NeedRIGHT();
2475  break;
2476 
2477  case T_data:
2478  {
2479  token = NextTok();
2480 
2481  wxString data;
2482 
2483  // Reserve 128K because most image files are going to be larger than the default
2484  // 1K that wxString reserves.
2485  data.reserve( 1 << 17 );
2486 
2487  while( token != T_RIGHT )
2488  {
2489  if( !IsSymbol( token ) )
2490  Expecting( "base64 image data" );
2491 
2492  data += FromUTF8();
2493  token = NextTok();
2494  }
2495 
2496  wxMemoryBuffer buffer = wxBase64Decode( data );
2497  wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2498  wxImage* image = new wxImage();
2499  wxMemoryInputStream istream( stream );
2500  image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2501  bitmap->GetImage()->SetImage( image );
2502  bitmap->GetImage()->SetBitmap( new wxBitmap( *image ) );
2503  break;
2504  }
2505 
2506  default:
2507  Expecting( "at, scale, uuid or data" );
2508  }
2509  }
2510 
2511  return bitmap.release();
2512 }
Definition: kiid.h:44
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References image, parseDouble(), and parseXY().

Referenced by ParseSchematic().

◆ parseInt() [1/2]

int SCH_SEXPR_PARSER::parseInt ( )
inlineprivate

Definition at line 95 of file sch_sexpr_parser.h.

96  {
97  return (int)strtol( CurText(), NULL, 10 );
98  }
#define NULL

References NULL.

Referenced by parseFill(), parseHeader(), parseInt(), parseJunction(), parsePin(), parseProperty(), parseSchematicSymbol(), parseSchField(), parseSchSymbolInstances(), parseStroke(), and parseTITLE_BLOCK().

◆ parseInt() [2/2]

int SCH_SEXPR_PARSER::parseInt ( const char *  aExpected)
inlineprivate

Definition at line 100 of file sch_sexpr_parser.h.

101  {
102  NeedNUMBER( aExpected );
103  return parseInt();
104  }

References parseInt().

◆ parseInternalUnits() [1/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( )
inlineprivate

Definition at line 126 of file sch_sexpr_parser.h.

127  {
128  auto retval = parseDouble() * IU_PER_MM;
129 
130  // Schematic internal units are represented as integers. Any values that are
131  // larger or smaller than the schematic units represent undefined behavior for
132  // the system. Limit values to the largest that can be displayed on the screen.
133  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
134 
135  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
136  }
static constexpr double IU_PER_MM
Mock up a conversion function.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References IU_PER_MM, KiROUND(), and parseDouble().

Referenced by parseArc(), parseBezier(), parseBusEntry(), parseCircle(), parseEDA_TEXT(), parseInternalUnits(), parseJunction(), parsePin(), parsePinNames(), parsePolyLine(), parseRectangle(), parseSheet(), parseStroke(), and parseXY().

◆ parseInternalUnits() [2/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( const char *  aExpected)
inlineprivate

Definition at line 138 of file sch_sexpr_parser.h.

139  {
140  auto retval = parseDouble( aExpected ) * IU_PER_MM;
141 
142  double int_limit = std::numeric_limits<int>::max() * 0.7071;
143 
144  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
145  }
static constexpr double IU_PER_MM
Mock up a conversion function.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References IU_PER_MM, KiROUND(), and parseDouble().

◆ parseInternalUnits() [3/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( TSCHEMATIC_T::T  aToken)
inlineprivate

Definition at line 147 of file sch_sexpr_parser.h.

148  {
149  return parseInternalUnits( GetTokenText( aToken ) );
150  }
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69

References DSN::GetTokenText(), and parseInternalUnits().

◆ parseJunction()

SCH_JUNCTION * SCH_SEXPR_PARSER::parseJunction ( )
private

Definition at line 2622 of file sch_sexpr_parser.cpp.

2623 {
2624  wxCHECK_MSG( CurTok() == T_junction, nullptr,
2625  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a junction." ) );
2626 
2627  T token;
2628  std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
2629 
2630  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2631  {
2632  if( token != T_LEFT )
2633  Expecting( T_LEFT );
2634 
2635  token = NextTok();
2636 
2637  switch( token )
2638  {
2639  case T_at:
2640  junction->SetPosition( parseXY() );
2641  NeedRIGHT();
2642  break;
2643 
2644  case T_diameter:
2645  junction->SetDiameter( parseInternalUnits( "junction diameter" ) );
2646  NeedRIGHT();
2647  break;
2648 
2649  case T_color:
2650  {
2651  COLOR4D color;
2652 
2653  color.r = parseInt( "red" ) / 255.0;
2654  color.g = parseInt( "green" ) / 255.0;
2655  color.b = parseInt( "blue" ) / 255.0;
2656  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
2657 
2658  junction->SetColor( color );
2659  NeedRIGHT();
2660  break;
2661  }
2662 
2663  default:
2664  Expecting( "at" );
2665  }
2666  }
2667 
2668  return junction.release();
2669 }
int color
Definition: DXF_plotter.cpp:60
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98

References Clamp(), color, parseDouble(), parseInt(), parseInternalUnits(), and parseXY().

Referenced by ParseSchematic().

◆ ParseLib()

void SCH_SEXPR_PARSER::ParseLib ( LIB_PART_MAP aSymbolLibMap)

Definition at line 91 of file sch_sexpr_parser.cpp.

92 {
93  T token;
94 
95  NeedLEFT();
96  NextTok();
97  parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
98 
99  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
100  {
101  if( token != T_LEFT )
102  Expecting( T_LEFT );
103 
104  token = NextTok();
105 
106  if( token == T_symbol )
107  {
108  m_unit = 1;
109  m_convert = 1;
110  LIB_PART* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
111  aSymbolLibMap[symbol->GetName()] = symbol;
112  }
113  else
114  {
115  Expecting( "symbol" );
116  }
117  }
118 }
LIB_PART * ParseSymbol(LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
wxString GetName() const override
Definition: lib_symbol.h:129
int m_unit
The current unit being parsed.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
int m_convert
The current body style being parsed.
Define a library symbol object.
Definition: lib_symbol.h:93
int m_requiredVersion
Set to the symbol library file version required.

References LIB_PART::GetName(), m_convert, m_requiredVersion, m_unit, parseHeader(), ParseSymbol(), and SEXPR_SYMBOL_LIB_FILE_VERSION.

◆ parseLine()

SCH_LINE * SCH_SEXPR_PARSER::parseLine ( )
private

Definition at line 2763 of file sch_sexpr_parser.cpp.

2764 {
2765  T token;
2766  STROKE_PARAMS stroke;
2767  std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>();
2768 
2769  switch( CurTok() )
2770  {
2771  case T_polyline: line->SetLayer( LAYER_NOTES ); break;
2772  case T_wire: line->SetLayer( LAYER_WIRE ); break;
2773  case T_bus: line->SetLayer( LAYER_BUS ); break;
2774  default:
2775  wxCHECK_MSG( false, nullptr,
2776  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a line." ) );
2777  }
2778 
2779  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2780  {
2781  if( token != T_LEFT )
2782  Expecting( T_LEFT );
2783 
2784  token = NextTok();
2785 
2786  switch( token )
2787  {
2788  case T_pts:
2789  NeedLEFT();
2790  token = NextTok();
2791 
2792  if( token != T_xy )
2793  Expecting( "xy" );
2794 
2795  line->SetStartPoint( parseXY() );
2796  NeedRIGHT();
2797  NeedLEFT();
2798  token = NextTok();
2799 
2800  if( token != T_xy )
2801  Expecting( "xy" );
2802 
2803  line->SetEndPoint( parseXY() );
2804  NeedRIGHT();
2805  NeedRIGHT();
2806  break;
2807 
2808  case T_stroke:
2809  parseStroke( stroke );
2810  line->SetStroke( stroke );
2811  break;
2812 
2813  case T_uuid:
2814  NeedSYMBOL();
2815  const_cast<KIID&>( line->m_Uuid ) = KIID( FromUTF8() );
2816  NeedRIGHT();
2817  break;
2818 
2819  default:
2820  Expecting( "at, uuid or stroke" );
2821  }
2822  }
2823 
2824  return line.release();
2825 }
Definition: kiid.h:44
Simple container to manage line stroke parameters.
Definition: sch_item.h:155
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References LAYER_BUS, LAYER_NOTES, LAYER_WIRE, parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseNoConnect()

SCH_NO_CONNECT * SCH_SEXPR_PARSER::parseNoConnect ( )
private

Definition at line 2672 of file sch_sexpr_parser.cpp.

2673 {
2674  wxCHECK_MSG( CurTok() == T_no_connect, nullptr,
2675  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a no connect." ) );
2676 
2677  T token;
2678  std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
2679 
2680  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2681  {
2682  if( token != T_LEFT )
2683  Expecting( T_LEFT );
2684 
2685  token = NextTok();
2686 
2687  switch( token )
2688  {
2689  case T_at:
2690  no_connect->SetPosition( parseXY() );
2691  NeedRIGHT();
2692  break;
2693 
2694  case T_uuid:
2695  NeedSYMBOL();
2696  const_cast<KIID&>( no_connect->m_Uuid ) = KIID( FromUTF8() );
2697  NeedRIGHT();
2698  break;
2699 
2700  default:
2701  Expecting( "at or uuid" );
2702  }
2703  }
2704 
2705  return no_connect.release();
2706 }
Definition: kiid.h:44

References parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1526 of file sch_sexpr_parser.cpp.

1527 {
1528  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1529  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1530 
1531  T token;
1532 
1533  NeedSYMBOL();
1534 
1535  wxString pageType = FromUTF8();
1536 
1537  if( !aPageInfo.SetType( pageType ) )
1538  {
1539  wxString err;
1540  err.Printf( _( "Page type \"%s\" is not valid " ), FromUTF8() );
1541  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1542  }
1543 
1544  if( pageType == PAGE_INFO::Custom )
1545  {
1546  double width = parseDouble( "width" ); // width in mm
1547 
1548  // Perform some controls to avoid crashes if the size is edited by hands
1549  if( width < 100.0 )
1550  width = 100.0;
1551  else if( width > 1200.0 )
1552  width = 1200.0;
1553 
1554  double height = parseDouble( "height" ); // height in mm
1555 
1556  if( height < 100.0 )
1557  height = 100.0;
1558  else if( height > 1200.0 )
1559  height = 1200.0;
1560 
1561  aPageInfo.SetWidthMils( Mm2mils( width ) );
1562  aPageInfo.SetHeightMils( Mm2mils( height ) );
1563  }
1564 
1565  token = NextTok();
1566 
1567  if( token == T_portrait )
1568  {
1569  aPageInfo.SetPortrait( true );
1570  NeedRIGHT();
1571  }
1572  else if( token != T_RIGHT )
1573  {
1574  Expecting( "portrait" );
1575  }
1576 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:62
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.
Definition: page_info.cpp:119
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:77
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
int m_requiredVersion
Set to the symbol library file version required.
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:243
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
Definition: page_info.cpp:186

References _, PAGE_INFO::Custom, m_requiredVersion, Mm2mils(), parseDouble(), PAGE_INFO::SetHeightMils(), PAGE_INFO::SetPortrait(), PAGE_INFO::SetType(), PAGE_INFO::SetWidthMils(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parsePin()

LIB_PIN * SCH_SEXPR_PARSER::parsePin ( )
private

Definition at line 1131 of file sch_sexpr_parser.cpp.

1132 {
1133  auto parseType = [&]( T token ) -> ELECTRICAL_PINTYPE
1134  {
1135  switch( token )
1136  {
1137  case T_input: return ELECTRICAL_PINTYPE::PT_INPUT;
1138  case T_output: return ELECTRICAL_PINTYPE::PT_OUTPUT;
1139  case T_bidirectional: return ELECTRICAL_PINTYPE::PT_BIDI;
1140  case T_tri_state: return ELECTRICAL_PINTYPE::PT_TRISTATE;
1141  case T_passive: return ELECTRICAL_PINTYPE::PT_PASSIVE;
1142  case T_unspecified: return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1143  case T_power_in: return ELECTRICAL_PINTYPE::PT_POWER_IN;
1144  case T_power_out: return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1145  case T_open_collector: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1146  case T_open_emitter: return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1147  case T_unconnected:
1148  case T_no_connect: return ELECTRICAL_PINTYPE::PT_NC;
1149  case T_free: return ELECTRICAL_PINTYPE::PT_NIC;
1150 
1151  default:
1152  Expecting( "input, output, bidirectional, tri_state, passive, "
1153  "unspecified, power_in, power_out, open_collector, "
1154  "open_emitter, free or no_connect" );
1156  }
1157  };
1158 
1159  auto parseShape = [&]( T token ) -> GRAPHIC_PINSHAPE
1160  {
1161  switch( token )
1162  {
1163  case T_line: return GRAPHIC_PINSHAPE::LINE;
1164  case T_inverted: return GRAPHIC_PINSHAPE::INVERTED;
1165  case T_clock: return GRAPHIC_PINSHAPE::CLOCK;
1166  case T_inverted_clock: return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1167  case T_input_low: return GRAPHIC_PINSHAPE::INPUT_LOW;
1168  case T_clock_low: return GRAPHIC_PINSHAPE::CLOCK_LOW;
1169  case T_output_low: return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1170  case T_edge_clock_high: return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1171  case T_non_logic: return GRAPHIC_PINSHAPE::NONLOGIC;
1172 
1173  default:
1174  Expecting( "line, inverted, clock, inverted_clock, input_low, "
1175  "clock_low, output_low, edge_clock_high, non_logic" );
1176  return GRAPHIC_PINSHAPE::LINE;
1177  }
1178  };
1179 
1180  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1181  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a pin token." ) );
1182 
1183  T token;
1184  wxString tmp;
1185  wxString error;
1186  std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( nullptr );
1187 
1188  pin->SetUnit( m_unit );
1189  pin->SetConvert( m_convert );
1190 
1191  // Pin electrical type.
1192  token = NextTok();
1193  pin->SetType( parseType( token ) );
1194 
1195  // Pin shape.
1196  token = NextTok();
1197  pin->SetShape( parseShape( token ) );
1198 
1199  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1200  {
1201  if( token == T_hide )
1202  {
1203  pin->SetVisible( false );
1204  continue;
1205  }
1206 
1207  if( token != T_LEFT )
1208  Expecting( T_LEFT );
1209 
1210  token = NextTok();
1211 
1212  switch( token )
1213  {
1214  case T_at:
1215  pin->SetPosition( parseXY() );
1216 
1217  switch( parseInt( "pin orientation" ) )
1218  {
1219  case 0:
1220  pin->SetOrientation( PIN_RIGHT );
1221  break;
1222 
1223  case 90:
1224  pin->SetOrientation( PIN_UP );
1225  break;
1226 
1227  case 180:
1228  pin->SetOrientation( PIN_LEFT );
1229  break;
1230 
1231  case 270:
1232  pin->SetOrientation( PIN_DOWN );
1233  break;
1234 
1235  default:
1236  Expecting( "0, 90, 180, or 270" );
1237  }
1238 
1239  NeedRIGHT();
1240  break;
1241 
1242  case T_length:
1243  pin->SetLength( parseInternalUnits( "pin length" ) );
1244  NeedRIGHT();
1245  break;
1246 
1247  case T_name:
1248  token = NextTok();
1249 
1250  if( !IsSymbol( token ) )
1251  {
1252  error.Printf( _( "Invalid pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1253  CurSource().c_str(), CurLineNumber(), CurOffset() );
1254  THROW_IO_ERROR( error );
1255  }
1256 
1257  pin->SetName( FromUTF8() );
1258  token = NextTok();
1259 
1260  if( token != T_RIGHT )
1261  {
1262  token = NextTok();
1263 
1264  if( token == T_effects )
1265  {
1266  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1267  // so duplicate parsing is not required.
1268  EDA_TEXT text;
1269 
1270  parseEDA_TEXT( &text );
1271  pin->SetNameTextSize( text.GetTextHeight() );
1272  NeedRIGHT();
1273  }
1274  else
1275  {
1276  Expecting( "effects" );
1277  }
1278  }
1279 
1280  break;
1281 
1282  case T_number:
1283  token = NextTok();
1284 
1285  if( !IsSymbol( token ) )
1286  {
1287  error.Printf( _( "Invalid pin number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1288  CurSource().c_str(), CurLineNumber(), CurOffset() );
1289  THROW_IO_ERROR( error );
1290  }
1291 
1292  pin->SetNumber( FromUTF8() );
1293  token = NextTok();
1294 
1295  if( token != T_RIGHT )
1296  {
1297  token = NextTok();
1298 
1299  if( token == T_effects )
1300  {
1301  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1302  // so duplicate parsing is not required.
1303  EDA_TEXT text;
1304 
1305  parseEDA_TEXT( &text );
1306  pin->SetNumberTextSize( text.GetTextHeight() );
1307  NeedRIGHT();
1308  }
1309  else
1310  {
1311  Expecting( "effects" );
1312  }
1313  }
1314 
1315  break;
1316 
1317  case T_alternate:
1318  {
1319  LIB_PIN::ALT alt;
1320 
1321  token = NextTok();
1322 
1323  if( !IsSymbol( token ) )
1324  {
1325  error.Printf( _( "Invalid alternate pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1326  CurSource().c_str(), CurLineNumber(), CurOffset() );
1327  THROW_IO_ERROR( error );
1328  }
1329 
1330  alt.m_Name = FromUTF8();
1331 
1332  token = NextTok();
1333  alt.m_Type = parseType( token );
1334 
1335  token = NextTok();
1336  alt.m_Shape = parseShape( token );
1337 
1338  pin->GetAlternates()[ alt.m_Name ] = alt;
1339 
1340  NeedRIGHT();
1341  }
1342  break;
1343 
1344  default:
1345  Expecting( "at, name, number, length, or alternate" );
1346  }
1347  }
1348 
1349  return pin.release();
1350 }
power input (GND, VCC for ICs). Must be connected to a power output.
void parseEDA_TEXT(EDA_TEXT *aText)
pin for passive components: must be connected, and can be connected to any pin
int m_unit
The current unit being parsed.
unknown electrical properties: creates always a warning when connected
Definition: lib_pin.h:50
GRAPHIC_PINSHAPE
Definition: pin_type.h:55
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:62
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:119
not internally connected (may be connected to anything)
int m_convert
The current body style being parsed.
wxString m_Name
Definition: lib_pin.h:60
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:35
#define _(s)
Definition: 3d_actions.cpp:33
usual pin input: must be connected
input or output (like port for a microprocessor)
not connected (must be left open)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
output of a regulator: intended to be connected to power input pins
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:61

References _, CLOCK, CLOCK_LOW, FALLING_EDGE_CLOCK, INPUT_LOW, INVERTED, INVERTED_CLOCK, LINE, m_convert, LIB_PIN::ALT::m_Name, LIB_PIN::ALT::m_Shape, LIB_PIN::ALT::m_Type, m_unit, NONLOGIC, OUTPUT_LOW, parseEDA_TEXT(), parseInt(), parseInternalUnits(), parseXY(), pin, PIN_DOWN, PIN_LEFT, PIN_RIGHT, PIN_UP, PT_BIDI, PT_INPUT, PT_NC, PT_NIC, PT_OPENCOLLECTOR, PT_OPENEMITTER, PT_OUTPUT, PT_PASSIVE, PT_POWER_IN, PT_POWER_OUT, PT_TRISTATE, PT_UNSPECIFIED, text, and THROW_IO_ERROR.

Referenced by ParseDrawItem().

◆ parsePinNames()

void SCH_SEXPR_PARSER::parsePinNames ( std::unique_ptr< LIB_PART > &  aSymbol)
private

Definition at line 689 of file sch_sexpr_parser.cpp.

690 {
691  wxCHECK_RET( CurTok() == T_pin_names,
692  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
693  wxT( " as a pin_name token." ) );
694 
695  wxString error;
696 
697  T token = NextTok();
698 
699  if( token == T_LEFT )
700  {
701  token = NextTok();
702 
703  if( token != T_offset )
704  Expecting( "offset" );
705 
706  aSymbol->SetPinNameOffset( parseInternalUnits( "pin name offset" ) );
707  NeedRIGHT();
708  token = NextTok(); // Either ) or hide
709  }
710 
711  if( token == T_hide )
712  {
713  aSymbol->SetShowPinNames( false );
714  NeedRIGHT();
715  }
716  else if( token != T_RIGHT )
717  {
718  error.Printf( _( "Invalid symbol names definition in\nfile: '%s'\nline: %d\noffset: %d" ),
719  CurSource().c_str(),
720  CurLineNumber(),
721  CurOffset() );
722  THROW_IO_ERROR( error );
723  }
724 }
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, parseInternalUnits(), and THROW_IO_ERROR.

Referenced by ParseSymbol().

◆ parsePolyLine()

LIB_POLYLINE * SCH_SEXPR_PARSER::parsePolyLine ( )
private

Definition at line 1353 of file sch_sexpr_parser.cpp.

1354 {
1355  wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1356  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a polyline." ) );
1357 
1358  T token;
1359  FILL_PARAMS fill;
1360  std::unique_ptr<LIB_POLYLINE> polyLine = std::make_unique<LIB_POLYLINE>( nullptr );
1361 
1362  polyLine->SetUnit( m_unit );
1363  polyLine->SetConvert( m_convert );
1364 
1365  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1366  {
1367  if( token != T_LEFT )
1368  Expecting( T_LEFT );
1369 
1370  token = NextTok();
1371 
1372  switch( token )
1373  {
1374  case T_pts:
1375  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1376  {
1377  if( token != T_LEFT )
1378  Expecting( T_LEFT );
1379 
1380  token = NextTok();
1381 
1382  if( token != T_xy )
1383  Expecting( "xy" );
1384 
1385  polyLine->AddPoint( parseXY() );
1386 
1387  NeedRIGHT();
1388  }
1389 
1390  break;
1391 
1392  case T_stroke:
1393  NeedLEFT();
1394  token = NextTok();
1395 
1396  if( token != T_width )
1397  Expecting( "width" );
1398 
1399  polyLine->SetWidth( parseInternalUnits( "stroke width" ) );
1400  NeedRIGHT(); // Closes width token;
1401  NeedRIGHT(); // Closes stroke token;
1402  break;
1403 
1404  case T_fill:
1405  parseFill( fill );
1406  polyLine->SetFillMode( fill.m_FillType );
1407  break;
1408 
1409  default:
1410  Expecting( "pts, stroke, or fill" );
1411  }
1412  }
1413 
1414  return polyLine.release();
1415 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseProperty()

LIB_FIELD * SCH_SEXPR_PARSER::parseProperty ( std::unique_ptr< LIB_PART > &  aSymbol)
private

Definition at line 727 of file sch_sexpr_parser.cpp.

728 {
729  wxCHECK_MSG( CurTok() == T_property, nullptr,
730  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a property." ) );
731  wxCHECK( aSymbol, nullptr );
732 
733  wxString error;
734  wxString name;
735  wxString value;
736  std::unique_ptr<LIB_FIELD> field = std::make_unique<LIB_FIELD>( aSymbol.get(), MANDATORY_FIELDS );
737 
738  T token = NextTok();
739 
740  if( !IsSymbol( token ) )
741  {
742  error.Printf( _( "Invalid property name in\nfile: '%s'\nline: %d\noffset: %d" ),
743  CurSource().c_str(),
744  CurLineNumber(),
745  CurOffset() );
746  THROW_IO_ERROR( error );
747  }
748 
749  name = FromUTF8();
750 
751  if( name.IsEmpty() )
752  {
753  error.Printf( _( "Empty property name in\nfile: '%s'\nline: %d\noffset: %d" ),
754  CurSource().c_str(),
755  CurLineNumber(),
756  CurOffset() );
757  THROW_IO_ERROR( error );
758  }
759 
760  field->SetName( name );
761  token = NextTok();
762 
763  if( !IsSymbol( token ) )
764  {
765  error.Printf( _( "Invalid property value in\nfile: '%s'\nline: %d\noffset: %d" ),
766  CurSource().c_str(),
767  CurLineNumber(),
768  CurOffset() );
769  THROW_IO_ERROR( error );
770  }
771 
772  // Empty property values are valid.
773  value = FromUTF8();
774 
775  field->SetText( value );
776 
777  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
778  {
779  if( token != T_LEFT )
780  Expecting( T_LEFT );
781 
782  token = NextTok();
783 
784  switch( token )
785  {
786  case T_id:
787  field->SetId( parseInt( "field ID" ) );
788  NeedRIGHT();
789  break;
790 
791  case T_at:
792  field->SetPosition( parseXY() );
793  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
794  NeedRIGHT();
795  break;
796 
797  case T_effects:
798  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ) );
799  break;
800 
801  default:
802  Expecting( "id, at or effects" );
803  }
804  }
805 
806  LIB_FIELD* existingField;
807 
808  if( field->GetId() < MANDATORY_FIELDS )
809  {
810  existingField = aSymbol->GetFieldById( field->GetId() );
811 
812  *existingField = *field;
813  return existingField;
814  }
815  else if( name == "ki_keywords" )
816  {
817  // Not a LIB_FIELD object yet.
818  aSymbol->SetKeyWords( value );
819  return nullptr;
820  }
821  else if( name == "ki_description" )
822  {
823  // Not a LIB_FIELD object yet.
824  aSymbol->SetDescription( value );
825  return nullptr;
826  }
827  else if( name == "ki_fp_filters" )
828  {
829  // Not a LIB_FIELD object yet.
830  wxArrayString filters;
831  wxStringTokenizer tokenizer( value );
832 
833  while( tokenizer.HasMoreTokens() )
834  filters.Add( tokenizer.GetNextToken() );
835 
836  aSymbol->SetFPFilters( filters );
837  return nullptr;
838  }
839  else if( name == "ki_locked" )
840  {
841  // This is a temporary LIB_FIELD object until interchangeable units are determined on
842  // the fly.
843  aSymbol->LockUnits( true );
844  return nullptr;
845  }
846  else
847  {
848  // At this point, a user field is read.
849  existingField = aSymbol->FindField( field->GetCanonicalName() );
850 
851 #if 1 // Enable it to modify the name of the field to add if already existing
852  // Disable it to skip the field having the same name as previous field
853  if( existingField )
854  {
855  // We cannot handle 2 fields with the same name, so because the field name
856  // is already in use, try to build a new name (oldname_x)
857  wxString base_name = field->GetCanonicalName();
858 
859  // Arbitrary limit 10 attempts to find a new name
860  for( int ii = 1; ii < 10 && existingField ; ii++ )
861  {
862  wxString newname = base_name;
863  newname << '_' << ii;
864 
865  existingField = aSymbol->FindField( newname );
866 
867  if( !existingField ) // the modified name is not found, use it
868  field->SetName( newname );
869  }
870  }
871 #endif
872  if( !existingField )
873  {
874  aSymbol->AddDrawItem( field.get(), false );
875  return field.release();
876  }
877  else
878  {
879  // We cannot handle 2 fields with the same name, so skip this one
880  return nullptr;
881  }
882  }
883 }
void parseEDA_TEXT(EDA_TEXT *aText)
Field object used in symbol libraries.
Definition: lib_field.h:59
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: lib_field.cpp:373
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
const char * name
Definition: DXF_plotter.cpp:59
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, LIB_FIELD::GetCanonicalName(), MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), and THROW_IO_ERROR.

Referenced by ParseSymbol().

◆ parseRectangle()

LIB_RECTANGLE * SCH_SEXPR_PARSER::parseRectangle ( )
private

Definition at line 1418 of file sch_sexpr_parser.cpp.

1419 {
1420  wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1421  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle token." ) );
1422 
1423  T token;
1424  FILL_PARAMS fill;
1425  std::unique_ptr<LIB_RECTANGLE> rectangle = std::make_unique<LIB_RECTANGLE>( nullptr );
1426 
1427  rectangle->SetUnit( m_unit );
1428  rectangle->SetConvert( m_convert );
1429 
1430  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1431  {
1432  if( token != T_LEFT )
1433  Expecting( T_LEFT );
1434 
1435  token = NextTok();
1436 
1437  switch( token )
1438  {
1439  case T_start:
1440  rectangle->SetPosition( parseXY() );
1441  NeedRIGHT();
1442  break;
1443 
1444  case T_end:
1445  rectangle->SetEnd( parseXY() );
1446  NeedRIGHT();
1447  break;
1448 
1449  case T_stroke:
1450  NeedLEFT();
1451  token = NextTok();
1452 
1453  if( token != T_width )
1454  Expecting( "width" );
1455 
1456  rectangle->SetWidth( parseInternalUnits( "stroke width" ) );
1457  NeedRIGHT(); // Closes width token;
1458  NeedRIGHT(); // Closes stroke token;
1459  break;
1460 
1461  case T_fill:
1462  parseFill( fill );
1463  rectangle->SetFillMode( fill.m_FillType );
1464  break;
1465 
1466  default:
1467  Expecting( "start, end, stroke, or fill" );
1468  }
1469  }
1470 
1471  return rectangle.release();
1472 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ ParseSchematic()

void SCH_SEXPR_PARSER::ParseSchematic ( SCH_SHEET aSheet,
bool  aIsCopyablyOnly = false,
int  aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION 
)

Parse the internal LINE_READER object into aSheet.

When aIsCopyableOnly is true, only schematic objects that are viewable on the canvas for copy and paste purposes are parsed. Other schematic content such as bus definitions or instance data will throw an IO_ERROR exception.

When aIsCopyableOnly is false, full schematic file parsing is performed.

Note
This does not load any sub-sheets or decent complex sheet hierarchies.
Parameters
aSheetThe SCH_SHEET object to store the parsed schematic file.
aIsCopyableOnlyLoad only the schematic objects that can be copied into aSheet if true. Otherwise, load the full schematic file format.
aFileVersionThe schematic file version to parser. Defaults to the schematic file being parsed when aIsCopyableOnly is false.

Definition at line 2009 of file sch_sexpr_parser.cpp.

2010 {
2011  wxCHECK( aSheet != nullptr, /* void */ );
2012 
2013  SCH_SCREEN* screen = aSheet->GetScreen();
2014 
2015  wxCHECK( screen != nullptr, /* void */ );
2016 
2017  if( aIsCopyableOnly )
2018  m_requiredVersion = aFileVersion;
2019 
2020  T token;
2021 
2022  if( !aIsCopyableOnly )
2023  {
2024  NeedLEFT();
2025  NextTok();
2026 
2027  if( CurTok() != T_kicad_sch )
2028  Expecting( "kicad_sch" );
2029 
2030  parseHeader( T_kicad_sch, SEXPR_SCHEMATIC_FILE_VERSION );
2031  }
2032 
2034 
2035  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2036  {
2037  if( aIsCopyableOnly && token == T_EOF )
2038  break;
2039 
2040  if( token != T_LEFT )
2041  Expecting( T_LEFT );
2042 
2043  token = NextTok();
2044 
2045  if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
2046  token = T_paper;
2047 
2048  switch( token )
2049  {
2050  case T_uuid:
2051  NeedSYMBOL();
2052  screen->m_uuid = KIID( FromUTF8() );
2053  NeedRIGHT();
2054  break;
2055 
2056  case T_paper:
2057  {
2058  if( aIsCopyableOnly )
2059  Unexpected( T_paper );
2060 
2061  PAGE_INFO pageInfo;
2062  parsePAGE_INFO( pageInfo );
2063  screen->SetPageSettings( pageInfo );
2064  break;
2065  }
2066 
2067  case T_page:
2068  {
2069  if( aIsCopyableOnly )
2070  Unexpected( T_page );
2071 
2072  // Only saved for top-level sniffing in Kicad Manager frame and other external
2073  // tool usage with flat hierarchies
2074  NeedSYMBOLorNUMBER();
2075  NeedSYMBOLorNUMBER();
2076  NeedRIGHT();
2077  break;
2078  }
2079 
2080  case T_title_block:
2081  {
2082  if( aIsCopyableOnly )
2083  Unexpected( T_title_block );
2084 
2085  TITLE_BLOCK tb;
2086  parseTITLE_BLOCK( tb );
2087  screen->SetTitleBlock( tb );
2088  break;
2089  }
2090 
2091  case T_lib_symbols:
2092  {
2093  // Dummy map. No derived symbols are allowed in the library cache.
2094  LIB_PART_MAP symbolLibMap;
2095 
2096  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2097  {
2098  if( token != T_LEFT )
2099  Expecting( T_LEFT );
2100 
2101  token = NextTok();
2102 
2103  switch( token )
2104  {
2105  case T_symbol:
2106  screen->AddLibSymbol( ParseSymbol( symbolLibMap, m_requiredVersion ) );
2107  break;
2108 
2109  default:
2110  Expecting( "symbol" );
2111  }
2112  }
2113 
2114  break;
2115  }
2116 
2117  case T_symbol:
2118  screen->Append( static_cast<SCH_ITEM*>( parseSchematicSymbol() ) );
2119  break;
2120 
2121  case T_image:
2122  screen->Append( static_cast<SCH_ITEM*>( parseImage() ) );
2123  break;
2124 
2125  case T_sheet:
2126  {
2127  SCH_SHEET* sheet = parseSheet();
2128 
2129  // Set the parent to aSheet. This effectively creates a method to find
2130  // the root sheet from any sheet so a pointer to the root sheet does not
2131  // need to be stored globally. Note: this is not the same as a hierarchy.
2132  // Complex hierarchies can have multiple copies of a sheet. This only
2133  // provides a simple tree to find the root sheet.
2134  sheet->SetParent( aSheet );
2135  screen->Append( static_cast<SCH_ITEM*>( sheet ) );
2136  break;
2137  }
2138 
2139  case T_junction:
2140  screen->Append( static_cast<SCH_ITEM*>( parseJunction() ) );
2141  break;
2142 
2143  case T_no_connect:
2144  screen->Append( static_cast<SCH_ITEM*>( parseNoConnect() ) );
2145  break;
2146 
2147  case T_bus_entry:
2148  screen->Append( static_cast<SCH_ITEM*>( parseBusEntry() ) );
2149  break;
2150 
2151  case T_polyline:
2152  case T_bus:
2153  case T_wire:
2154  screen->Append( static_cast<SCH_ITEM*>( parseLine() ) );
2155  break;
2156 
2157  case T_text:
2158  case T_label:
2159  case T_global_label:
2160  case T_hierarchical_label:
2161  screen->Append( static_cast<SCH_ITEM*>( parseSchText() ) );
2162  break;
2163 
2164  case T_sheet_instances:
2165  if( aIsCopyableOnly )
2166  Unexpected( T_sheet_instances );
2167 
2168  parseSchSheetInstances( aSheet, screen );
2169  break;
2170 
2171  case T_symbol_instances:
2172  if( aIsCopyableOnly )
2173  Unexpected( T_symbol_instances );
2174 
2175  parseSchSymbolInstances( screen );
2176  break;
2177 
2178  case T_bus_alias:
2179  if( aIsCopyableOnly )
2180  Unexpected( T_bus_alias );
2181 
2182  parseBusAlias( screen );
2183  break;
2184 
2185  default:
2186  Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2187  "bus_entry, line, bus, text, label, global_label, hierarchical_label, "
2188  "symbol_instances, or bus_alias" );
2189  }
2190  }
2191 
2192  screen->UpdateLocalLibSymbolLinks();
2193 }
LIB_PART * ParseSymbol(LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
void parseBusAlias(SCH_SCREEN *aScreen)
std::map< wxString, LIB_PART *, LibPartMapSort > LIB_PART_MAP
Part map used by part library object.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:129
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:40
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:166
SCH_BUS_WIRE_ENTRY * parseBusEntry()
Definition: kiid.h:44
void UpdateLocalLibSymbolLinks()
Initialize the LIB_PART reference for each SCH_COMPONENT found in this schematic with the local proje...
Definition: sch_screen.cpp:677
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
SCH_JUNCTION * parseJunction()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
SCH_NO_CONNECT * parseNoConnect()
void SetFileFormatVersionAtLoad(int aVersion)
Definition: sch_screen.h:125
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:140
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
void AddLibSymbol(LIB_PART *aLibSymbol)
Add aLibSymbol to the the library symbol map.
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:128
SCH_BITMAP * parseImage()
KIID m_uuid
A unique identifier for each schematic file.
Definition: sch_screen.h:536
SCH_TEXT * parseSchText()
#define SEXPR_SCHEMATIC_FILE_VERSION
Symbol library file version.
SCH_COMPONENT * parseSchematicSymbol()
SCH_SHEET * parseSheet()

References SCH_SCREEN::AddLibSymbol(), SCH_SCREEN::Append(), SCH_SHEET::GetScreen(), m_requiredVersion, SCH_SCREEN::m_uuid, parseBusAlias(), parseBusEntry(), parseHeader(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), parsePAGE_INFO(), parseSchematicSymbol(), parseSchSheetInstances(), parseSchSymbolInstances(), parseSchText(), parseSheet(), ParseSymbol(), parseTITLE_BLOCK(), SCH_SCREEN::SetFileFormatVersionAtLoad(), SCH_SCREEN::SetPageSettings(), EDA_ITEM::SetParent(), SCH_SCREEN::SetTitleBlock(), SEXPR_SCHEMATIC_FILE_VERSION, and SCH_SCREEN::UpdateLocalLibSymbolLinks().

Referenced by SCH_SEXPR_PLUGIN::LoadContent(), and SCH_SEXPR_PLUGIN::loadFile().

◆ parseSchematicSymbol()

SCH_COMPONENT * SCH_SEXPR_PARSER::parseSchematicSymbol ( )
private

Definition at line 2196 of file sch_sexpr_parser.cpp.

2197 {
2198  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
2199  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
2200 
2201  T token;
2202  wxString tmp;
2203  wxString error;
2204  wxString libName;
2205  SCH_FIELD* field;
2206  std::unique_ptr<SCH_COMPONENT> symbol = std::make_unique<SCH_COMPONENT>();
2207  TRANSFORM transform;
2208  std::set<int> fieldIDsRead;
2209 
2210  // We'll reset this if we find a fields_autoplaced token
2211  symbol->ClearFieldsAutoplaced();
2212 
2214 
2215  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2216  {
2217  if( token != T_LEFT )
2218  Expecting( T_LEFT );
2219 
2220  token = NextTok();
2221 
2222  switch( token )
2223  {
2224  case T_lib_name:
2225  {
2226  LIB_ID libId;
2227 
2228  token = NextTok();
2229 
2230  if( !IsSymbol( token ) )
2231  {
2232  error.Printf( _( "Invalid symbol library name in\nfile: \"%s\"\n"
2233  "line: %d\noffset: %d" ),
2234  CurSource().c_str(), CurLineNumber(), CurOffset() );
2235  THROW_IO_ERROR( error );
2236  }
2237 
2238  libName = FromUTF8();
2239  NeedRIGHT();
2240  break;
2241  }
2242 
2243  case T_lib_id:
2244  {
2245  token = NextTok();
2246 
2247  if( !IsSymbol( token ) && token != T_NUMBER )
2248  Expecting( "symbol|number" );
2249 
2250  LIB_ID libId;
2251 
2252  if( libId.Parse( FromUTF8() ) >= 0 )
2253  {
2254  error.Printf( _( "Invalid symbol library ID in\nfile: \"%s\"\nline: %d\n"
2255  "offset: %d" ),
2256  CurSource(), CurLineNumber(), CurOffset() );
2257  THROW_IO_ERROR( error );
2258  }
2259 
2260  symbol->SetLibId( libId );
2261  NeedRIGHT();
2262  break;
2263  }
2264 
2265  case T_at:
2266  symbol->SetPosition( parseXY() );
2267 
2268  switch( static_cast<int>( parseDouble( "symbol orientation" ) ) )
2269  {
2270  case 0: transform = TRANSFORM(); break;
2271  case 90: transform = TRANSFORM( 0, -1, -1, 0 ); break;
2272  case 180: transform = TRANSFORM( -1, 0, 0, 1 ); break;
2273  case 270: transform = TRANSFORM( 0, 1, 1, 0 ); break;
2274  default: Expecting( "0, 90, 180, or 270" );
2275  }
2276 
2277  symbol->SetTransform( transform );
2278  NeedRIGHT();
2279  break;
2280 
2281  case T_mirror:
2282  token = NextTok();
2283 
2284  if( token == T_x )
2285  symbol->SetOrientation( CMP_MIRROR_X );
2286  else if( token == T_y )
2287  symbol->SetOrientation( CMP_MIRROR_Y );
2288  else
2289  Expecting( "x or y" );
2290 
2291  NeedRIGHT();
2292  break;
2293 
2294  case T_unit:
2295  symbol->SetUnit( parseInt( "symbol unit" ) );
2296  NeedRIGHT();
2297  break;
2298 
2299  case T_convert:
2300  symbol->SetConvert( parseInt( "symbol convert" ) );
2301  NeedRIGHT();
2302  break;
2303 
2304  case T_in_bom:
2305  symbol->SetIncludeInBom( parseBool() );
2306  NeedRIGHT();
2307  break;
2308 
2309  case T_on_board:
2310  symbol->SetIncludeOnBoard( parseBool() );
2311  NeedRIGHT();
2312  break;
2313 
2314  case T_fields_autoplaced:
2315  symbol->SetFieldsAutoplaced();
2316  NeedRIGHT();
2317  break;
2318 
2319  case T_uuid:
2320  NeedSYMBOL();
2321  const_cast<KIID&>( symbol->m_Uuid ) = KIID( FromUTF8() );
2322  NeedRIGHT();
2323  break;
2324 
2325  case T_property:
2326  // The field parent symbol must be set and it's orientation must be set before
2327  // the field positions are set.
2328  field = parseSchField( symbol.get() );
2329 
2330  // It would appear that at some point we allowed duplicate ids to slip through
2331  // when writing files. The easiest (and most complete) solution is to disallow
2332  // multiple instances of the same id (for all files since the source of the error
2333  // *might* in fact be hand-edited files).
2334  //
2335  // While no longer used, -1 is still a valid id for user field. It gets converted
2336  // to the next unused number on save.
2337  if( fieldIDsRead.count( field->GetId() ) )
2338  field->SetId( -1 );
2339  else
2340  fieldIDsRead.insert( field->GetId() );
2341 
2342  // Set the default symbol reference prefix.
2343  if( field->GetId() == REFERENCE_FIELD )
2344  {
2345  wxString refDesignator = field->GetText();
2346 
2347  refDesignator.Replace( "~", " " );
2348 
2349  wxString prefix = refDesignator;
2350 
2351  while( prefix.Length() )
2352  {
2353  if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' )
2354  break;
2355 
2356  prefix.RemoveLast();
2357  }
2358 
2359  // Avoid a prefix containing trailing/leading spaces
2360  prefix.Trim( true );
2361  prefix.Trim( false );
2362 
2363  if( prefix.IsEmpty() )
2364  symbol->SetPrefix( wxString( "U" ) );
2365  else
2366  symbol->SetPrefix( prefix );
2367  }
2368 
2369  if( symbol->GetFieldById( field->GetId() ) )
2370  *symbol->GetFieldById( field->GetId() ) = *field;
2371  else
2372  symbol->AddField( *field );
2373 
2374  delete field;
2375  break;
2376 
2377  case T_pin:
2378  {
2379  // Read an alternate pin designation
2380  wxString number;
2381  KIID uuid;
2382  wxString alt;
2383 
2384  NeedSYMBOL();
2385  number = FromUTF8();
2386 
2387  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2388  {
2389  if( token != T_LEFT )
2390  Expecting( T_LEFT );
2391 
2392  token = NextTok();
2393 
2394  switch( token )
2395  {
2396  case T_alternate:
2397  NeedSYMBOL();
2398  alt = FromUTF8();
2399  NeedRIGHT();
2400  break;
2401 
2402  case T_uuid:
2403  NeedSYMBOL();
2404 
2405  // First version to write out pin uuids accidentally wrote out the symbol's
2406  // uuid for each pin, so ignore uuids coming from that version.
2407  if( m_requiredVersion >= 20210126 )
2408  uuid = KIID( FromUTF8() );
2409 
2410  NeedRIGHT();
2411  break;
2412 
2413  default:
2414  Expecting( "alternate or uuid" );
2415  }
2416  }
2417 
2418  symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(),
2419  number, alt ) );
2420 
2421  const_cast<KIID&>( symbol->GetRawPins().back()->m_Uuid ) = uuid;
2422  }
2423  break;
2424 
2425  default:
2426  Expecting( "lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
2427  }
2428  }
2429 
2430  if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2431  symbol->SetSchSymbolLibraryName( libName );
2432 
2433  // Ensure edit/status flags are cleared after these initializations:
2434  symbol->ClearFlags();
2435 
2436  return symbol.release();
2437 }
Field Reference of part, i.e. "IC21".
int m_fieldId
The current field ID.
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
int GetId() const
Definition: sch_field.h:114
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
Definition: kiid.h:44
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
int m_requiredVersion
Set to the symbol library file version required.
#define _(s)
Definition: 3d_actions.cpp:33
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void SetId(int aId)
Definition: sch_field.cpp:80
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133

References _, CMP_MIRROR_X, CMP_MIRROR_Y, SCH_FIELD::GetId(), EDA_TEXT::GetText(), m_fieldId, m_requiredVersion, MANDATORY_FIELDS, LIB_ID::Parse(), parseBool(), parseDouble(), parseInt(), parseSchField(), parseXY(), REFERENCE_FIELD, SCH_FIELD::SetId(), and THROW_IO_ERROR.

Referenced by ParseSchematic().

◆ parseSchField()

SCH_FIELD * SCH_SEXPR_PARSER::parseSchField ( SCH_ITEM aParent)
private

Definition at line 1685 of file sch_sexpr_parser.cpp.

1686 {
1687  wxCHECK_MSG( CurTok() == T_property, nullptr,
1688  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1689  wxT( " as a property token." ) );
1690 
1691  wxString error;
1692  wxString name;
1693  wxString value;
1694 
1695  T token = NextTok();
1696 
1697  if( !IsSymbol( token ) )
1698  {
1699  error.Printf( _( "Invalid property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1700  CurSource().c_str(), CurLineNumber(), CurOffset() );
1701  THROW_IO_ERROR( error );
1702  }
1703 
1704  name = FromUTF8();
1705 
1706  if( name.IsEmpty() )
1707  {
1708  error.Printf( _( "Empty property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1709  CurSource().c_str(), CurLineNumber(), CurOffset() );
1710  THROW_IO_ERROR( error );
1711  }
1712 
1713  token = NextTok();
1714 
1715  if( !IsSymbol( token ) )
1716  {
1717  error.Printf( _( "Invalid property value in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1718  CurSource().c_str(), CurLineNumber(), CurOffset() );
1719  THROW_IO_ERROR( error );
1720  }
1721 
1722  // Empty property values are valid.
1723  value = FromUTF8();
1724 
1725  std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1, aParent, name );
1726 
1727  field->SetText( value );
1728  field->SetVisible( true );
1729 
1730  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1731  {
1732  if( token != T_LEFT )
1733  Expecting( T_LEFT );
1734 
1735  token = NextTok();
1736 
1737  switch( token )
1738  {
1739  case T_id:
1740  field->SetId( parseInt( "field ID" ) );
1741  NeedRIGHT();
1742  break;
1743 
1744  case T_at:
1745  field->SetPosition( parseXY() );
1746  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
1747  NeedRIGHT();
1748  break;
1749 
1750  case T_effects:
1751  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ) );
1752  break;
1753 
1754  default:
1755  Expecting( "at or effects" );
1756  }
1757  }
1758 
1759  return field.release();
1760 }
void parseEDA_TEXT(EDA_TEXT *aText)
const char * name
Definition: DXF_plotter.cpp:59
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), and THROW_IO_ERROR.

Referenced by parseSchematicSymbol(), parseSchText(), and parseSheet().

◆ parseSchSheetInstances()

void SCH_SEXPR_PARSER::parseSchSheetInstances ( SCH_SHEET aRootSheet,
SCH_SCREEN aScreen 
)
private

Definition at line 1856 of file sch_sexpr_parser.cpp.

1857 {
1858  wxCHECK_RET( CurTok() == T_sheet_instances,
1859  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1860  wxT( " as a instances token." ) );
1861  wxCHECK( aScreen, /* void */ );
1862 
1863  T token;
1864 
1865  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1866  {
1867  if( token != T_LEFT )
1868  Expecting( T_LEFT );
1869 
1870  token = NextTok();
1871 
1872  switch( token )
1873  {
1874  case T_path:
1875  {
1876  NeedSYMBOL();
1877 
1878  SCH_SHEET_INSTANCE instance;
1879 
1880  instance.m_Path = KIID_PATH( FromUTF8() );
1881 
1882  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1883  {
1884  if( token != T_LEFT )
1885  Expecting( T_LEFT );
1886 
1887  token = NextTok();
1888 
1889  switch( token )
1890  {
1891  case T_page:
1892  NeedSYMBOL();
1893  instance.m_PageNumber = FromUTF8();
1894 
1895  // Empty page numbers are not permitted
1896  if( instance.m_PageNumber.IsEmpty() )
1897  {
1898  // Use space character instead
1899  instance.m_PageNumber = wxT( " " );
1900 
1901  // Set the file as modified so the user can be warned.
1902  aScreen->SetModify();
1903  }
1904 
1905  NeedRIGHT();
1906  break;
1907 
1908  default:
1909  Expecting( "path or page" );
1910  }
1911  }
1912 
1913  aScreen->m_sheetInstances.emplace_back( instance );
1914  break;
1915  }
1916 
1917  default:
1918  Expecting( "path" );
1919  }
1920  }
1921 
1922  // We don't store the root sheet's KIID, so pick it up from any sheet instance paths so
1923  // that it doesn't change on every round-trip.
1924  for( const SCH_SHEET_INSTANCE& instance : aScreen->m_sheetInstances )
1925  {
1926  if( instance.m_Path.size() > 0 )
1927  {
1928  const_cast<KIID&>( aRootSheet->m_Uuid ) = instance.m_Path[0];
1929  break;
1930  }
1931  }
1932 }
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:528
const KIID m_Uuid
Definition: eda_item.h:525
A simple container for sheet instance information.
void SetModify()
Definition: base_screen.h:59

References SCH_SHEET_INSTANCE::m_PageNumber, SCH_SHEET_INSTANCE::m_Path, SCH_SCREEN::m_sheetInstances, EDA_ITEM::m_Uuid, and BASE_SCREEN::SetModify().

Referenced by ParseSchematic().

◆ parseSchSheetPin()

SCH_SHEET_PIN * SCH_SEXPR_PARSER::parseSchSheetPin ( SCH_SHEET aSheet)
private

Definition at line 1763 of file sch_sexpr_parser.cpp.

1764 {
1765  wxCHECK_MSG( aSheet != nullptr, nullptr, "" );
1766  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1767  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1768  wxT( " as a sheet pin token." ) );
1769 
1770  wxString error;
1771  wxString name;
1772  wxString shape;
1773 
1774  T token = NextTok();
1775 
1776  if( !IsSymbol( token ) )
1777  {
1778  error.Printf( _( "Invalid sheet pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1779  CurSource().c_str(), CurLineNumber(), CurOffset() );
1780  THROW_IO_ERROR( error );
1781  }
1782 
1783  name = FromUTF8();
1784 
1785  if( name.IsEmpty() )
1786  {
1787  error.Printf( _( "Empty sheet pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1788  CurSource().c_str(), CurLineNumber(), CurOffset() );
1789  THROW_IO_ERROR( error );
1790  }
1791 
1792  std::unique_ptr<SCH_SHEET_PIN> sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet, wxPoint( 0, 0 ), name );
1793 
1794  token = NextTok();
1795 
1796  switch( token )
1797  {
1798  case T_input: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
1799  case T_output: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
1800  case T_bidirectional: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
1801  case T_tri_state: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
1802  case T_passive: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
1803  default:
1804  Expecting( "input, output, bidirectional, tri_state, or passive" );
1805  }
1806 
1807  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1808  {
1809  if( token != T_LEFT )
1810  Expecting( T_LEFT );
1811 
1812  token = NextTok();
1813 
1814  switch( token )
1815  {
1816  case T_at:
1817  {
1818  sheetPin->SetPosition( parseXY() );
1819 
1820  double angle = parseDouble( "sheet pin angle (side)" );
1821 
1822  if( angle == 0.0 )
1823  sheetPin->SetEdge( SHEET_RIGHT_SIDE );
1824  else if( angle == 90.0 )
1825  sheetPin->SetEdge( SHEET_TOP_SIDE );
1826  else if( angle == 180.0 )
1827  sheetPin->SetEdge( SHEET_LEFT_SIDE );
1828  else if( angle == 270.0 )
1829  sheetPin->SetEdge( SHEET_BOTTOM_SIDE );
1830  else
1831  Expecting( "0, 90, 180, or 270" );
1832 
1833  NeedRIGHT();
1834  break;
1835  }
1836 
1837  case T_effects:
1838  parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ) );
1839  break;
1840 
1841  case T_uuid:
1842  NeedSYMBOL();
1843  const_cast<KIID&>( sheetPin->m_Uuid ) = KIID( FromUTF8() );
1844  NeedRIGHT();
1845  break;
1846 
1847  default:
1848  Expecting( "at, uuid or effects" );
1849  }
1850  }
1851 
1852  return sheetPin.release();
1853 }
void parseEDA_TEXT(EDA_TEXT *aText)
Definition: kiid.h:44
const char * name
Definition: DXF_plotter.cpp:59
#define _(s)
Definition: 3d_actions.cpp:33
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, PNS::angle(), name, parseDouble(), parseEDA_TEXT(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, SHEET_BOTTOM_SIDE, SHEET_LEFT_SIDE, SHEET_RIGHT_SIDE, SHEET_TOP_SIDE, and THROW_IO_ERROR.

Referenced by parseSheet().

◆ parseSchSymbolInstances()

void SCH_SEXPR_PARSER::parseSchSymbolInstances ( SCH_SCREEN aScreen)
private

Definition at line 1935 of file sch_sexpr_parser.cpp.

1936 {
1937  wxCHECK_RET( CurTok() == T_symbol_instances,
1938  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1939  wxT( " as a instances token." ) );
1940  wxCHECK( aScreen, /* void */ );
1941 
1942  T token;
1943 
1944  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1945  {
1946  if( token != T_LEFT )
1947  Expecting( T_LEFT );
1948 
1949  token = NextTok();
1950 
1951  switch( token )
1952  {
1953  case T_path:
1954  {
1955  NeedSYMBOL();
1956 
1957  SYMBOL_INSTANCE_REFERENCE instance;
1958 
1959  instance.m_Path = KIID_PATH( FromUTF8() );
1960 
1961  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1962  {
1963  if( token != T_LEFT )
1964  Expecting( T_LEFT );
1965 
1966  token = NextTok();
1967 
1968  switch( token )
1969  {
1970  case T_reference:
1971  NeedSYMBOL();
1972  instance.m_Reference = FromUTF8();
1973  NeedRIGHT();
1974  break;
1975 
1976  case T_unit:
1977  instance.m_Unit = parseInt( "symbol unit" );
1978  NeedRIGHT();
1979  break;
1980 
1981  case T_value:
1982  NeedSYMBOL();
1983  instance.m_Value = FromUTF8();
1984  NeedRIGHT();
1985  break;
1986 
1987  case T_footprint:
1988  NeedSYMBOL();
1989  instance.m_Footprint = FromUTF8();
1990  NeedRIGHT();
1991  break;
1992 
1993  default:
1994  Expecting( "path, unit, value or footprint" );
1995  }
1996  }
1997 
1998  aScreen->m_symbolInstances.emplace_back( instance );
1999  break;
2000  }
2001 
2002  default:
2003  Expecting( "path" );
2004  }
2005  }
2006 }
std::vector< SYMBOL_INSTANCE_REFERENCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
Definition: sch_screen.h:527
A simple container for schematic symbol instance information.

References SYMBOL_INSTANCE_REFERENCE::m_Footprint, SYMBOL_INSTANCE_REFERENCE::m_Path, SYMBOL_INSTANCE_REFERENCE::m_Reference, SCH_SCREEN::m_symbolInstances, SYMBOL_INSTANCE_REFERENCE::m_Unit, SYMBOL_INSTANCE_REFERENCE::m_Value, and parseInt().

Referenced by ParseSchematic().

◆ parseSchText()

SCH_TEXT * SCH_SEXPR_PARSER::parseSchText ( )
private

Definition at line 2828 of file sch_sexpr_parser.cpp.

2829 {
2830  T token;
2831  std::unique_ptr<SCH_TEXT> text;
2832 
2833  switch( CurTok() )
2834  {
2835  case T_text: text = std::make_unique<SCH_TEXT>(); break;
2836  case T_label: text = std::make_unique<SCH_LABEL>(); break;
2837  case T_global_label: text = std::make_unique<SCH_GLOBALLABEL>(); break;
2838  case T_hierarchical_label: text = std::make_unique<SCH_HIERLABEL>(); break;
2839  default:
2840  wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as text." );
2841  }
2842 
2843  // We'll reset this if we find a fields_autoplaced token
2844  text->ClearFieldsAutoplaced();
2845 
2846  NeedSYMBOL();
2847 
2848  text->SetText( FromUTF8() );
2849 
2850  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2851  {
2852  if( token != T_LEFT )
2853  Expecting( T_LEFT );
2854 
2855  token = NextTok();
2856 
2857  switch( token )
2858  {
2859  case T_at:
2860  text->SetPosition( parseXY() );
2861 
2862  switch( static_cast<int>( parseDouble( "text angle" ) ) )
2863  {
2864  case 0: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT ); break;
2865  case 90: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::UP ); break;
2866  case 180: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); break;
2867  case 270: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM ); break;
2868  default:
2869  wxFAIL;
2870  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT );
2871  break;
2872  }
2873 
2874  NeedRIGHT();
2875  break;
2876 
2877  case T_shape:
2878  if( text->Type() == SCH_TEXT_T || text->Type() == SCH_LABEL_T )
2879  Unexpected( T_shape );
2880 
2881  token = NextTok();
2882 
2883  switch( token )
2884  {
2885  case T_input: text->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
2886  case T_output: text->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
2887  case T_bidirectional: text->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
2888  case T_tri_state: text->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
2889  case T_passive: text->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
2890  default:
2891  Expecting( "input, output, bidirectional, tri_state, or passive" );
2892  }
2893 
2894  NeedRIGHT();
2895  break;
2896 
2897  case T_fields_autoplaced:
2898  text->SetFieldsAutoplaced();
2899  NeedRIGHT();
2900  break;
2901 
2902  case T_effects:
2903  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ) );
2904  break;
2905 
2906  case T_iref: // legacy format; current is a T_property (aka SCH_FIELD)
2907  if( text->Type() == SCH_GLOBAL_LABEL_T )
2908  {
2909  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2910  SCH_FIELD* field = label->GetIntersheetRefs();
2911 
2912  field->SetTextPos( parseXY() );
2913  NeedRIGHT();
2914 
2915  field->SetVisible( true );
2916  }
2917  break;
2918 
2919  case T_uuid:
2920  NeedSYMBOL();
2921  const_cast<KIID&>( text->m_Uuid ) = KIID( FromUTF8() );
2922  NeedRIGHT();
2923  break;
2924 
2925  case T_property:
2926  if( text->Type() == SCH_GLOBAL_LABEL_T )
2927  {
2928  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2929  SCH_FIELD* field = parseSchField( label );
2930 
2931  field->SetLayer( LAYER_GLOBLABEL );
2932  label->SetIntersheetRefs( *field );
2933 
2934  delete field;
2935  }
2936  break;
2937 
2938  default:
2939  Expecting( "at, shape, iref, uuid or effects" );
2940  }
2941  }
2942 
2943  return text.release();
2944 }
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
void parseEDA_TEXT(EDA_TEXT *aText)
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:253
Definition: kiid.h:44
void SetIntersheetRefs(const SCH_FIELD &aField)
Definition: sch_text.h:460
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:459
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References LABEL_SPIN_STYLE::BOTTOM, SCH_GLOBALLABEL::GetIntersheetRefs(), LAYER_GLOBLABEL, LABEL_SPIN_STYLE::LEFT, parseDouble(), parseEDA_TEXT(), parseSchField(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, LABEL_SPIN_STYLE::RIGHT, SCH_GLOBAL_LABEL_T, SCH_LABEL_T, SCH_TEXT_T, SCH_GLOBALLABEL::SetIntersheetRefs(), EDA_TEXT::SetTextPos(), text, and LABEL_SPIN_STYLE::UP.

Referenced by ParseSchematic().

◆ parseSheet()

SCH_SHEET * SCH_SEXPR_PARSER::parseSheet ( )
private

Definition at line 2515 of file sch_sexpr_parser.cpp.

2516 {
2517  wxCHECK_MSG( CurTok() == T_sheet, nullptr,
2518  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a sheet." ) );
2519 
2520  T token;
2521  STROKE_PARAMS stroke;
2522  FILL_PARAMS fill;
2523  SCH_FIELD* field;
2524  std::vector<SCH_FIELD> fields;
2525  std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
2526  std::set<int> fieldIDsRead;
2527 
2528  // We'll reset this if we find a fields_autoplaced token
2529  sheet->ClearFieldsAutoplaced();
2530 
2531  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2532  {
2533  if( token != T_LEFT )
2534  Expecting( T_LEFT );
2535 
2536  token = NextTok();
2537 
2538  switch( token )
2539  {
2540  case T_at:
2541  sheet->SetPosition( parseXY() );
2542  NeedRIGHT();
2543  break;
2544 
2545  case T_size:
2546  {
2547  wxSize size;
2548  size.SetWidth( parseInternalUnits( "sheet width" ) );
2549  size.SetHeight( parseInternalUnits( "sheet height" ) );
2550  sheet->SetSize( size );
2551  NeedRIGHT();
2552  break;
2553  }
2554 
2555  case T_fields_autoplaced:
2556  sheet->SetFieldsAutoplaced();
2557  NeedRIGHT();
2558  break;
2559 
2560  case T_stroke:
2561  parseStroke( stroke );
2562  sheet->SetBorderWidth( stroke.GetWidth() );
2563  sheet->SetBorderColor( stroke.GetColor() );
2564  break;
2565 
2566  case T_fill:
2567  parseFill( fill );
2568  sheet->SetBackgroundColor( fill.m_Color );
2569  break;
2570 
2571  case T_uuid:
2572  NeedSYMBOL();
2573  const_cast<KIID&>( sheet->m_Uuid ) = KIID( FromUTF8() );
2574  NeedRIGHT();
2575  break;
2576 
2577  case T_property:
2578  field = parseSchField( sheet.get() );
2579 
2580  if( m_requiredVersion <= 20200310 )
2581  {
2582  // Earlier versions had the wrong ids (and names) saved for sheet fields.
2583  // Fortunately they only saved the sheetname and sheetfilepath (and always
2584  // in that order), so we can hack in a recovery.
2585  if( fields.empty() )
2586  field->SetId( SHEETNAME );
2587  else
2588  field->SetId( SHEETFILENAME );
2589  }
2590 
2591  // It would appear the problem persists past 20200310, but this time with the
2592  // earlier ids being re-used for later (user) fields. The easiest (and most
2593  // complete) solution is to disallow multiple instances of the same id (for all
2594  // files since the source of the error *might* in fact be hand-edited files).
2595  //
2596  // While no longer used, -1 is still a valid id for user field. It gets converted
2597  // to the next unused number on save.
2598  if( fieldIDsRead.count( field->GetId() ) )
2599  field->SetId( -1 );
2600  else
2601  fieldIDsRead.insert( field->GetId() );
2602 
2603  fields.emplace_back( *field );
2604  delete field;
2605  break;
2606 
2607  case T_pin:
2608  sheet->AddPin( parseSchSheetPin( sheet.get() ) );
2609  break;
2610 
2611  default:
2612  Expecting( "at, size, stroke, background, uuid, property, or pin" );
2613  }
2614  }
2615 
2616  sheet->SetFields( fields );
2617 
2618  return sheet.release();
2619 }
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int GetId() const
Definition: sch_field.h:114
Definition: kiid.h:44
Simple container to manage fill parameters.
int GetWidth() const
Definition: sch_item.h:167
COLOR4D GetColor() const
Definition: sch_item.h:173
int m_requiredVersion
Set to the symbol library file version required.
Simple container to manage line stroke parameters.
Definition: sch_item.h:155
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
void parseFill(FILL_PARAMS &aFill)
void SetId(int aId)
Definition: sch_field.cpp:80
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References STROKE_PARAMS::GetColor(), SCH_FIELD::GetId(), STROKE_PARAMS::GetWidth(), FILL_PARAMS::m_Color, m_requiredVersion, parseFill(), parseInternalUnits(), parseSchField(), parseSchSheetPin(), parseStroke(), parseXY(), SCH_FIELD::SetId(), SHEETFILENAME, and SHEETNAME.

Referenced by ParseSchematic().

◆ parseStroke()

void SCH_SEXPR_PARSER::parseStroke ( STROKE_PARAMS aStroke)
private

Parse stroke definition aStroke.

Parameters
aStrokeDefA reference to the STROKE_PARAMS structure to write to.

Definition at line 453 of file sch_sexpr_parser.cpp.

454 {
455  wxCHECK_RET( CurTok() == T_stroke,
456  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) );
457 
458  aStroke.SetWidth( Mils2iu( DEFAULT_LINE_THICKNESS ) );
460  aStroke.SetColor( COLOR4D::UNSPECIFIED );
461 
462  T token;
463 
464  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
465  {
466  if( token != T_LEFT )
467  Expecting( T_LEFT );
468 
469  token = NextTok();
470 
471  switch( token )
472  {
473  case T_width:
474  aStroke.SetWidth( parseInternalUnits( "stroke width" ) );
475  NeedRIGHT();
476  break;
477 
478  case T_type:
479  {
480  token = NextTok();
481 
482  switch( token )
483  {
484  case T_dash: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH ); break;
485  case T_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT ); break;
486  case T_dash_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT ); break;
487  case T_solid: aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID ); break;
488  case T_default: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); break;
489  default:
490  Expecting( "solid, dash, dash_dot, dot or default" );
491  }
492 
493  NeedRIGHT();
494  break;
495  }
496 
497  case T_color:
498  {
499  COLOR4D color;
500 
501  color.r = parseInt( "red" ) / 255.0;
502  color.g = parseInt( "green" ) / 255.0;
503  color.b = parseInt( "blue" ) / 255.0;
504  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
505 
506  aStroke.SetColor( color );
507  NeedRIGHT();
508  break;
509  }
510 
511  default:
512  Expecting( "width, type, or color" );
513  }
514 
515  }
516 }
void SetWidth(int aWidth)
Definition: sch_item.h:168
int color
Definition: DXF_plotter.cpp:60
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
Definition: sch_item.h:171
#define DEFAULT_LINE_THICKNESS
The default wire width in mils. (can be changed in preference menu)
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
void SetColor(const COLOR4D &aColor)
Definition: sch_item.h:174
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98

References Clamp(), color, DASH, DASHDOT, DEFAULT, DEFAULT_LINE_THICKNESS, DOT, parseDouble(), parseInt(), parseInternalUnits(), STROKE_PARAMS::SetColor(), STROKE_PARAMS::SetPlotStyle(), STROKE_PARAMS::SetWidth(), and SOLID.

Referenced by parseBusEntry(), parseLine(), and parseSheet().

◆ ParseSymbol()

LIB_PART * SCH_SEXPR_PARSER::ParseSymbol ( LIB_PART_MAP aSymbolLibMap,
int  aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION 
)

Definition at line 121 of file sch_sexpr_parser.cpp.

122 {
123  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
124  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
125 
126  T token;
127  long tmp;
128  wxString name;
129  wxString error;
130  LIB_ITEM* item;
131  LIB_FIELD* field;
132  std::unique_ptr<LIB_PART> symbol = std::make_unique<LIB_PART>( wxEmptyString );
133  std::set<int> fieldIDsRead;
134 
135  m_requiredVersion = aFileVersion;
136  symbol->SetUnitCount( 1 );
137 
139 
140  token = NextTok();
141 
142  if( !IsSymbol( token ) )
143  {
144  error.Printf( _( "Invalid symbol name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
145  CurSource().c_str(), CurLineNumber(), CurOffset() );
146  THROW_IO_ERROR( error );
147  }
148 
149  name = FromUTF8();
150 
151  LIB_ID id;
152 
153  if( id.Parse( name ) >= 0 )
154  {
155  error.Printf( _( "Invalid library identifier in\nfile: \"%s\"\nline: %d\noffset: %d" ),
156  CurSource().c_str(), CurLineNumber(), CurOffset() );
157  THROW_IO_ERROR( error );
158  }
159 
160  m_symbolName = id.GetLibItemName().wx_str();
161  symbol->SetName( m_symbolName );
162  symbol->SetLibId( id );
163 
164  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
165  {
166  if( token != T_LEFT )
167  Expecting( T_LEFT );
168 
169  token = NextTok();
170 
171  switch( token )
172  {
173  case T_power:
174  symbol->SetPower();
175  NeedRIGHT();
176  break;
177 
178  case T_pin_names:
179  parsePinNames( symbol );
180  break;
181 
182  case T_pin_numbers:
183  token = NextTok();
184 
185  if( token != T_hide )
186  Expecting( "hide" );
187 
188  symbol->SetShowPinNumbers( false );
189  NeedRIGHT();
190  break;
191 
192  case T_in_bom:
193  symbol->SetIncludeInBom( parseBool() );
194  NeedRIGHT();
195  break;
196 
197  case T_on_board:
198  symbol->SetIncludeOnBoard( parseBool() );
199  NeedRIGHT();
200  break;
201 
202  case T_property:
203  field = parseProperty( symbol );
204 
205  if( field )
206  {
207  // It would appear that at some point we allowed duplicate ids to slip through
208  // when writing files. The easiest (and most complete) solution is to disallow
209  // multiple instances of the same id (for all files since the source of the error
210  // *might* in fact be hand-edited files).
211  //
212  // While no longer used, -1 is still a valid id for user field. It gets converted
213  // to the next unused number on save.
214  if( fieldIDsRead.count( field->GetId() ) )
215  field->SetId( -1 );
216  else if( field )
217  fieldIDsRead.insert( field->GetId() );
218  }
219 
220  break;
221 
222  case T_extends:
223  {
224  token = NextTok();
225 
226  if( !IsSymbol( token ) )
227  {
228  error.Printf(
229  _( "Invalid symbol extends name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
230  CurSource().c_str(), CurLineNumber(), CurOffset() );
231  THROW_IO_ERROR( error );
232  }
233 
234  name = FromUTF8();
235  auto it = aSymbolLibMap.find( name );
236 
237  if( it == aSymbolLibMap.end() )
238  {
239  error.Printf(
240  _( "No parent for extended symbol %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
241  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
242  THROW_IO_ERROR( error );
243  }
244 
245  symbol->SetParent( it->second );
246  NeedRIGHT();
247  break;
248  }
249 
250  case T_symbol:
251  {
252  token = NextTok();
253 
254  if( !IsSymbol( token ) )
255  {
256  error.Printf(
257  _( "Invalid symbol unit name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
258  CurSource().c_str(), CurLineNumber(), CurOffset() );
259  THROW_IO_ERROR( error );
260  }
261 
262  name = FromUTF8();
263 
264  if( !name.StartsWith( m_symbolName ) )
265  {
266  error.Printf(
267  _( "Invalid symbol unit name prefix %s in\nfile: \"%s\"\n"
268  "line: %d\noffset: %d" ),
269  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
270  THROW_IO_ERROR( error );
271  }
272 
273  name = name.Right( name.Length() - m_symbolName.Length() - 1 );
274 
275  wxStringTokenizer tokenizer( name, "_" );
276 
277  if( tokenizer.CountTokens() != 2 )
278  {
279  error.Printf(
280  _( "Invalid symbol unit name suffix %s in\nfile: \"%s\"\n"
281  "line: %d\noffset: %d" ),
282  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
283  THROW_IO_ERROR( error );
284  }
285 
286  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
287  {
288  error.Printf(
289  _( "Invalid symbol unit number %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
290  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
291  THROW_IO_ERROR( error );
292  }
293 
294  m_unit = static_cast<int>( tmp );
295 
296  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
297  {
298  error.Printf(
299  _( "Invalid symbol convert number %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
300  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
301  THROW_IO_ERROR( error );
302  }
303 
304  m_convert = static_cast<int>( tmp );
305 
306  if( m_convert > 1 )
307  symbol->SetConversion( true, false );
308 
309  if( m_unit > symbol->GetUnitCount() )
310  symbol->SetUnitCount( m_unit, false );
311 
312  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
313  {
314  if( token != T_LEFT )
315  Expecting( T_LEFT );
316 
317  token = NextTok();
318 
319  switch( token )
320  {
321  case T_arc:
322  case T_bezier:
323  case T_circle:
324  case T_pin:
325  case T_polyline:
326  case T_rectangle:
327  case T_text:
328  item = ParseDrawItem();
329 
330  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
331 
332  item->SetParent( symbol.get() );
333  symbol->AddDrawItem( item, false );
334  break;
335 
336  default:
337  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
338  };
339  }
340 
341  m_unit = 1;
342  m_convert = 1;
343  break;
344  }
345 
346  case T_arc:
347  case T_bezier:
348  case T_circle:
349  case T_pin:
350  case T_polyline:
351  case T_rectangle:
352  case T_text:
353  item = ParseDrawItem();
354 
355  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
356 
357  item->SetParent( symbol.get() );
358  symbol->AddDrawItem( item, false );
359  break;
360 
361  default:
362  Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
363  "rectangle, or text" );
364  }
365  }
366 
367  symbol->GetDrawItems().sort();
368  m_symbolName.clear();
369 
370  return symbol.release();
371 }
int m_fieldId
The current field ID.
LIB_FIELD * parseProperty(std::unique_ptr< LIB_PART > &aSymbol)
Field object used in symbol libraries.
Definition: lib_field.h:59
int m_unit
The current unit being parsed.
int GetId() const
Definition: lib_field.h:138
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:166
The base class for drawable items used by schematic library components.
Definition: lib_item.h:62
wxString m_symbolName
The current symbol name.
int m_convert
The current body style being parsed.
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
LIB_ITEM * ParseDrawItem()
int m_requiredVersion
Set to the symbol library file version required.
const char * name
Definition: DXF_plotter.cpp:59
#define _(s)
Definition: 3d_actions.cpp:33
void parsePinNames(std::unique_ptr< LIB_PART > &aSymbol)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetId(int aId)
Definition: lib_field.h:139

References _, LIB_FIELD::GetId(), m_convert, m_fieldId, m_requiredVersion, m_symbolName, m_unit, MANDATORY_FIELDS, name, parseBool(), ParseDrawItem(), parsePinNames(), parseProperty(), LIB_FIELD::SetId(), EDA_ITEM::SetParent(), and THROW_IO_ERROR.

Referenced by ParseLib(), SCH_SEXPR_PLUGIN::ParsePart(), and ParseSchematic().

◆ parseText()

LIB_TEXT * SCH_SEXPR_PARSER::parseText ( )
private

Definition at line 1475 of file sch_sexpr_parser.cpp.

1476 {
1477  wxCHECK_MSG( CurTok() == T_text, nullptr,
1478  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1479 
1480  T token;
1481  wxString tmp;
1482  wxString error;
1483  std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( nullptr );
1484 
1485  text->SetUnit( m_unit );
1486  text->SetConvert( m_convert );
1487  token = NextTok();
1488 
1489  if( !IsSymbol( token ) )
1490  {
1491  error.Printf( _( "Invalid text string in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1492  CurSource().c_str(), CurLineNumber(), CurOffset() );
1493  THROW_IO_ERROR( error );
1494  }
1495 
1496  text->SetText( FromUTF8() );
1497 
1498  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1499  {
1500  if( token != T_LEFT )
1501  Expecting( T_LEFT );
1502 
1503  token = NextTok();
1504 
1505  switch( token )
1506  {
1507  case T_at:
1508  text->SetPosition( parseXY() );
1509  text->SetTextAngle( parseDouble( "text angle" ) );
1510  NeedRIGHT();
1511  break;
1512 
1513  case T_effects:
1514  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ) );
1515  break;
1516 
1517  default:
1518  Expecting( "at or effects" );
1519  }
1520  }
1521 
1522  return text.release();
1523 }
void parseEDA_TEXT(EDA_TEXT *aText)
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, m_convert, m_unit, parseDouble(), parseEDA_TEXT(), parseXY(), text, and THROW_IO_ERROR.

Referenced by ParseDrawItem().

◆ parseTITLE_BLOCK()

void SCH_SEXPR_PARSER::parseTITLE_BLOCK ( TITLE_BLOCK aTitleBlock)
private

Definition at line 1579 of file sch_sexpr_parser.cpp.

1580 {
1581  wxCHECK_RET( CurTok() == T_title_block,
1582  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1583  wxT( " as TITLE_BLOCK." ) );
1584 
1585  T token;
1586 
1587  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1588  {
1589  if( token != T_LEFT )
1590  Expecting( T_LEFT );
1591 
1592  token = NextTok();
1593 
1594  switch( token )
1595  {
1596  case T_title:
1597  NextTok();
1598  aTitleBlock.SetTitle( FromUTF8() );
1599  break;
1600 
1601  case T_date:
1602  NextTok();
1603  aTitleBlock.SetDate( FromUTF8() );
1604  break;
1605 
1606  case T_rev:
1607  NextTok();
1608  aTitleBlock.SetRevision( FromUTF8() );
1609  break;
1610 
1611  case T_company:
1612  NextTok();
1613  aTitleBlock.SetCompany( FromUTF8() );
1614  break;
1615 
1616  case T_comment:
1617  {
1618  int commentNumber = parseInt( "comment" );
1619 
1620  switch( commentNumber )
1621  {
1622  case 1:
1623  NextTok();
1624  aTitleBlock.SetComment( 0, FromUTF8() );
1625  break;
1626 
1627  case 2:
1628  NextTok();
1629  aTitleBlock.SetComment( 1, FromUTF8() );
1630  break;
1631 
1632  case 3:
1633  NextTok();
1634  aTitleBlock.SetComment( 2, FromUTF8() );
1635  break;
1636 
1637  case 4:
1638  NextTok();
1639  aTitleBlock.SetComment( 3, FromUTF8() );
1640  break;
1641 
1642  case 5:
1643  NextTok();
1644  aTitleBlock.SetComment( 4, FromUTF8() );
1645  break;
1646 
1647  case 6:
1648  NextTok();
1649  aTitleBlock.SetComment( 5, FromUTF8() );
1650  break;
1651 
1652  case 7:
1653  NextTok();
1654  aTitleBlock.SetComment( 6, FromUTF8() );
1655  break;
1656 
1657  case 8:
1658  NextTok();
1659  aTitleBlock.SetComment( 7, FromUTF8() );
1660  break;
1661 
1662  case 9:
1663  NextTok();
1664  aTitleBlock.SetComment( 8, FromUTF8() );
1665  break;
1666 
1667  default:
1668  wxString err;
1669  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
1670  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1671  }
1672 
1673  break;
1674  }
1675 
1676  default:
1677  Expecting( "title, date, rev, company, or comment" );
1678  }
1679 
1680  NeedRIGHT();
1681  }
1682 }
void SetRevision(const wxString &aRevision)
Definition: title_block.h:81
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Definition: title_block.h:71
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:101
void SetCompany(const wxString &aCompany)
Definition: title_block.h:91
void SetTitle(const wxString &aTitle)
Definition: title_block.h:58

References parseInt(), TITLE_BLOCK::SetComment(), TITLE_BLOCK::SetCompany(), TITLE_BLOCK::SetDate(), TITLE_BLOCK::SetRevision(), TITLE_BLOCK::SetTitle(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseXY()

wxPoint SCH_SEXPR_PARSER::parseXY ( )
inlineprivate

Definition at line 152 of file sch_sexpr_parser.h.

153  {
154  wxPoint xy;
155 
156  xy.x = parseInternalUnits( "X coordinate" );
157  xy.y = parseInternalUnits( "Y coordinate" );
158 
159  return xy;
160  }

References parseInternalUnits().

Referenced by parseArc(), parseBezier(), parseBusEntry(), parseCircle(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), parsePin(), parsePolyLine(), parseProperty(), parseRectangle(), parseSchematicSymbol(), parseSchField(), parseSchSheetPin(), parseSchText(), parseSheet(), and parseText().

Member Data Documentation

◆ m_convert

int SCH_SEXPR_PARSER::m_convert
private

The current body style being parsed.

Definition at line 84 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().

◆ m_fieldId

int SCH_SEXPR_PARSER::m_fieldId
private

The current field ID.

Definition at line 82 of file sch_sexpr_parser.h.

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ m_requiredVersion

int SCH_SEXPR_PARSER::m_requiredVersion
private

Set to the symbol library file version required.

Definition at line 81 of file sch_sexpr_parser.h.

Referenced by IsTooRecent(), parseHeader(), ParseLib(), parsePAGE_INFO(), ParseSchematic(), parseSchematicSymbol(), parseSheet(), and ParseSymbol().

◆ m_symbolName

wxString SCH_SEXPR_PARSER::m_symbolName
private

The current symbol name.

Definition at line 85 of file sch_sexpr_parser.h.

Referenced by ParseSymbol().

◆ m_unit

int SCH_SEXPR_PARSER::m_unit
private

The current unit being parsed.

Definition at line 83 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().


The documentation for this class was generated from the following files: