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, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0)
 
void ParseLib (LIB_SYMBOL_MAP &aSymbolLibMap)
 
LIB_SYMBOLParseSymbol (LIB_SYMBOL_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...
 

Private Member Functions

void checkpoint ()
 
KIID parseKIID ()
 
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, bool aConvertOverbarSyntax)
 
void parsePinNames (std::unique_ptr< LIB_SYMBOL > &aSymbol)
 
LIB_FIELDparseProperty (std::unique_ptr< LIB_SYMBOL > &aSymbol)
 
LIB_SHAPEparseArc ()
 
LIB_SHAPEparseBezier ()
 
LIB_SHAPEparseCircle ()
 
LIB_PINparsePin ()
 
LIB_SHAPEparsePolyLine ()
 
LIB_SHAPEparseRectangle ()
 
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_SYMBOLparseSchematicSymbol ()
 
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...
 
std::set< int > m_fieldIDsRead
 Field IDs that have been read so far for the current symbol. More...
 
std::set< KIIDm_uuids
 
PROGRESS_REPORTERm_progressReporter
 
const LINE_READERm_lineReader
 
unsigned m_lastProgressLine
 
unsigned m_lineCount
 

Detailed Description

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

Definition at line 76 of file sch_sexpr_parser.h.

Constructor & Destructor Documentation

◆ SCH_SEXPR_PARSER()

SCH_SEXPR_PARSER::SCH_SEXPR_PARSER ( LINE_READER aLineReader = nullptr,
PROGRESS_REPORTER aProgressReporter = nullptr,
unsigned  aLineCount = 0 
)

Definition at line 60 of file sch_sexpr_parser.cpp.

61  :
62  SCHEMATIC_LEXER( aLineReader ),
63  m_requiredVersion( 0 ),
64  m_fieldId( 0 ),
65  m_unit( 1 ),
66  m_convert( 1 ),
67  m_progressReporter( aProgressReporter ),
68  m_lineReader( aLineReader ),
69  m_lastProgressLine( 0 ),
70  m_lineCount( aLineCount )
71 {
72 }
int m_fieldId
The current field ID.
unsigned m_lastProgressLine
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
const LINE_READER * m_lineReader
int m_requiredVersion
Set to the symbol library file version required.
PROGRESS_REPORTER * m_progressReporter

Member Function Documentation

◆ checkpoint()

void SCH_SEXPR_PARSER::checkpoint ( )
private

Definition at line 75 of file sch_sexpr_parser.cpp.

76 {
77  const unsigned PROGRESS_DELTA = 250;
78 
79  if( m_progressReporter )
80  {
81  unsigned curLine = m_lineReader->LineNumber();
82 
83  if( curLine > m_lastProgressLine + PROGRESS_DELTA )
84  {
85  m_progressReporter->SetCurrentProgress( ( (double) curLine )
86  / std::max( 1U, m_lineCount ) );
87 
89  THROW_IO_ERROR( ( "Open cancelled by user." ) );
90 
91  m_lastProgressLine = curLine;
92  }
93  }
94 }
unsigned m_lastProgressLine
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
const LINE_READER * m_lineReader
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
PROGRESS_REPORTER * m_progressReporter
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).

References PROGRESS_REPORTER::KeepRefreshing(), LINE_READER::LineNumber(), m_lastProgressLine, m_lineCount, m_lineReader, m_progressReporter, PROGRESS_REPORTER::SetCurrentProgress(), and THROW_IO_ERROR.

Referenced by ParseSchematic().

◆ parseArc()

LIB_SHAPE * SCH_SEXPR_PARSER::parseArc ( )
private

This accounts for an oddity in the old library format, where the symbol is overdefined. The previous draw (based on wxwidgets) used start point and end point and always drew counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of these points were stored in the file, so we need to mimic the swapping of start/end points rather than using the stored angles in order to properly map edge cases.

Definition at line 914 of file sch_sexpr_parser.cpp.

915 {
916  wxCHECK_MSG( CurTok() == T_arc, nullptr,
917  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) );
918 
919  T token;
920  wxPoint startPoint( 1, 0 ); // Initialize to a non-degenerate arc just for safety
921  wxPoint midPoint( 1, 1 );
922  wxPoint endPoint( 0, 1 );
923  bool hasMidPoint = false;
925  FILL_PARAMS fill;
926 
927  // Parameters for legacy format
928  wxPoint center( 0, 0 );
929  int startAngle = 0;
930  int endAngle = 900;
931  bool hasAngles = false;
932 
933  std::unique_ptr<LIB_SHAPE> arc = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::ARC );
934 
935  arc->SetUnit( m_unit );
936  arc->SetConvert( m_convert );
937 
938  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
939  {
940  if( token != T_LEFT )
941  Expecting( T_LEFT );
942 
943  token = NextTok();
944 
945  switch( token )
946  {
947  case T_start:
948  startPoint = parseXY();
949  NeedRIGHT();
950  break;
951 
952  case T_mid:
953  midPoint = parseXY();
954  NeedRIGHT();
955  hasMidPoint = true;
956  break;
957 
958  case T_end:
959  endPoint = parseXY();
960  NeedRIGHT();
961  break;
962 
963  case T_radius:
964  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
965  {
966  if( token != T_LEFT )
967  Expecting( T_LEFT );
968 
969  token = NextTok();
970 
971  switch( token )
972  {
973  case T_at:
974  center = parseXY();
975  NeedRIGHT();
976  break;
977 
978  case T_length:
979  parseInternalUnits( "radius length" );
980  NeedRIGHT();
981  break;
982 
983  case T_angles:
984  {
985  startAngle = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
986  endAngle = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
987  NORMALIZE_ANGLE_POS( startAngle );
988  NORMALIZE_ANGLE_POS( endAngle );
989  NeedRIGHT();
990  hasAngles = true;
991  break;
992  }
993 
994  default:
995  Expecting( "at, length, or angles" );
996  }
997  }
998 
999  break;
1000 
1001  case T_stroke:
1002  parseStroke( stroke );
1003  arc->SetWidth( stroke.GetWidth() );
1004  break;
1005 
1006  case T_fill:
1007  parseFill( fill );
1008  arc->SetFillMode( fill.m_FillType );
1009  break;
1010 
1011  default:
1012  Expecting( "start, mid, end, radius, stroke, or fill" );
1013  }
1014  }
1015 
1016  if( hasMidPoint )
1017  {
1018  arc->SetArcGeometry( startPoint, midPoint, endPoint);
1019  }
1020  else if( hasAngles )
1021  {
1022  arc->SetStart( startPoint );
1023  arc->SetEnd( endPoint );
1024 
1032  if( !TRANSFORM().MapAngles( &startAngle, &endAngle ) )
1033  {
1034  wxPoint temp = arc->GetStart();
1035  arc->SetStart( arc->GetEnd() );
1036  arc->SetEnd( temp );
1037  }
1038 
1039  arc->SetCenter( center );
1040  }
1041  else
1042  {
1043  wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." );
1044  }
1045 
1046  return arc.release();
1047 }
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int m_unit
The current unit being parsed.
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:290
Simple container to manage fill parameters.
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
int m_convert
The current body style being parsed.
Simple container to manage line stroke parameters.
Definition: sch_item.h:140
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:73
void parseFill(FILL_PARAMS &aFill)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References ARC, DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetWidth(), KiROUND(), m_convert, FILL_PARAMS::m_FillType, m_unit, NORMALIZE_ANGLE_POS(), parseDouble(), parseFill(), parseInternalUnits(), parseStroke(), and parseXY().

Referenced by ParseDrawItem().

◆ parseBezier()

LIB_SHAPE * SCH_SEXPR_PARSER::parseBezier ( )
private

Definition at line 1050 of file sch_sexpr_parser.cpp.

1051 {
1052  wxCHECK_MSG( CurTok() == T_bezier, nullptr,
1053  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
1054 
1055  T token;
1057  FILL_PARAMS fill;
1058 
1059  std::unique_ptr<LIB_SHAPE> bezier = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::BEZIER );
1060 
1061  bezier->SetUnit( m_unit );
1062  bezier->SetConvert( m_convert );
1063 
1064  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1065  {
1066  if( token != T_LEFT )
1067  Expecting( T_LEFT );
1068 
1069  token = NextTok();
1070 
1071  switch( token )
1072  {
1073  case T_pts:
1074  {
1075  int ii = 0;
1076 
1077  for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1078  {
1079  if( token != T_LEFT )
1080  Expecting( T_LEFT );
1081 
1082  token = NextTok();
1083 
1084  if( token != T_xy )
1085  Expecting( "xy" );
1086 
1087  switch( ii )
1088  {
1089  case 0: bezier->SetStart( parseXY() ); break;
1090  case 1: bezier->SetBezierC1( parseXY() ); break;
1091  case 2: bezier->SetBezierC2( parseXY() ); break;
1092  case 3: bezier->SetEnd( parseXY() ); break;
1093  default: Unexpected( "control point" ); break;
1094  }
1095 
1096  NeedRIGHT();
1097  }
1098  }
1099  break;
1100 
1101  case T_stroke:
1102  parseStroke( stroke );
1103  bezier->SetWidth( stroke.GetWidth() );
1104  break;
1105 
1106  case T_fill:
1107  parseFill( fill );
1108  bezier->SetFillMode( fill.m_FillType );
1109  break;
1110 
1111  default:
1112  Expecting( "pts, stroke, or fill" );
1113  }
1114  }
1115 
1116  bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1117 
1118  return bezier.release();
1119 }
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
Simple container to manage line stroke parameters.
Definition: sch_item.h:140
void parseFill(FILL_PARAMS &aFill)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References BEZIER, DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetWidth(), m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseStroke(), and parseXY().

Referenced by ParseDrawItem().

◆ parseBool()

bool SCH_SEXPR_PARSER::parseBool ( )
private

Definition at line 110 of file sch_sexpr_parser.cpp.

111 {
112  T token = NextTok();
113 
114  if( token == T_yes )
115  return true;
116  else if( token == T_no )
117  return false;
118  else
119  Expecting( "yes or no" );
120 
121  return false;
122 }

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ parseBusAlias()

void SCH_SEXPR_PARSER::parseBusAlias ( SCH_SCREEN aScreen)
private

Definition at line 2972 of file sch_sexpr_parser.cpp.

2973 {
2974  wxCHECK_RET( CurTok() == T_bus_alias,
2975  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
2976  wxCHECK( aScreen, /* void */ );
2977 
2978  T token;
2979  std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
2980  wxString alias;
2981  wxString member;
2982 
2983  NeedSYMBOL();
2984 
2985  alias = FromUTF8();
2986 
2987  if( m_requiredVersion < 20210621 )
2988  alias = ConvertToNewOverbarNotation( alias );
2989 
2990  busAlias->SetName( alias );
2991 
2992  NeedLEFT();
2993  token = NextTok();
2994 
2995  if( token != T_members )
2996  Expecting( "members" );
2997 
2998  token = NextTok();
2999 
3000  while( token != T_RIGHT )
3001  {
3002  if( !IsSymbol( token ) )
3003  Expecting( "quoted string" );
3004 
3005  member = FromUTF8();
3006 
3007  if( m_requiredVersion < 20210621 )
3008  member = ConvertToNewOverbarNotation( member );
3009 
3010  busAlias->AddMember( member );
3011 
3012  token = NextTok();
3013  }
3014 
3015  NeedRIGHT();
3016 
3017  aScreen->AddBusAlias( busAlias );
3018 }
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
int m_requiredVersion
Set to the symbol library file version required.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).

References SCH_SCREEN::AddBusAlias(), ConvertToNewOverbarNotation(), and m_requiredVersion.

Referenced by ParseSchematic().

◆ parseBusEntry()

SCH_BUS_WIRE_ENTRY * SCH_SEXPR_PARSER::parseBusEntry ( )
private

Definition at line 2713 of file sch_sexpr_parser.cpp.

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

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, parseInternalUnits(), parseKIID(), parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseCircle()

LIB_SHAPE * SCH_SEXPR_PARSER::parseCircle ( )
private

Definition at line 1122 of file sch_sexpr_parser.cpp.

1123 {
1124  wxCHECK_MSG( CurTok() == T_circle, nullptr,
1125  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
1126 
1127  T token;
1128  wxPoint center( 0, 0 );
1129  int radius = 1; // defaulting to 0 could result in troublesome math....
1131  FILL_PARAMS fill;
1132 
1133  std::unique_ptr<LIB_SHAPE> circle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::CIRCLE );
1134 
1135  circle->SetUnit( m_unit );
1136  circle->SetConvert( m_convert );
1137 
1138  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1139  {
1140  if( token != T_LEFT )
1141  Expecting( T_LEFT );
1142 
1143  token = NextTok();
1144 
1145  switch( token )
1146  {
1147  case T_center:
1148  center = parseXY();
1149  NeedRIGHT();
1150  break;
1151 
1152  case T_radius:
1153  radius = parseInternalUnits( "radius length" );
1154  NeedRIGHT();
1155  break;
1156 
1157  case T_stroke:
1158  parseStroke( stroke );
1159  circle->SetWidth( stroke.GetWidth() );
1160  break;
1161 
1162  case T_fill:
1163  parseFill( fill );
1164  circle->SetFillMode( fill.m_FillType );
1165  break;
1166 
1167  default:
1168  Expecting( "center, radius, stroke, or fill" );
1169  }
1170  }
1171 
1172  circle->SetCenter( center );
1173  circle->SetEnd( wxPoint( center.x + radius, center.y ) );
1174 
1175  return circle.release();
1176 }
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
Simple container to manage line stroke parameters.
Definition: sch_item.h:140
void parseFill(FILL_PARAMS &aFill)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References CIRCLE, DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetWidth(), m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), parseStroke(), 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 413 of file sch_sexpr_parser.cpp.

414 {
415  char* tmp;
416 
417  // In case the file got saved with the wrong locale.
418  if( strchr( CurText(), ',' ) != nullptr )
419  {
420  THROW_PARSE_ERROR( _( "Floating point number with incorrect locale" ), CurSource(),
421  CurLine(), CurLineNumber(), CurOffset() );
422  }
423 
424  errno = 0;
425 
426  double fval = strtod( CurText(), &tmp );
427 
428  if( errno )
429  {
430  THROW_PARSE_ERROR( _( "Invalid floating point number" ), CurSource(), CurLine(),
431  CurLineNumber(), CurOffset() );
432  }
433 
434  if( CurText() == tmp )
435  {
436  THROW_PARSE_ERROR( _( "Missing floating point number" ), CurSource(), CurLine(),
437  CurLineNumber(), CurOffset() );
438  }
439 
440  return fval;
441 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)

References _, and THROW_PARSE_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 126 of file sch_sexpr_parser.h.

127  {
128  NeedNUMBER( aExpected );
129  return parseDouble();
130  }
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 132 of file sch_sexpr_parser.h.

133  {
134  return parseDouble( GetTokenText( aToken ) );
135  }
const char * GetTokenText(T aTok)
The DSN namespace and returns the C string representing a SPECCTRA_DB::keyword.
Definition: specctra.cpp:70
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 373 of file sch_sexpr_parser.cpp.

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

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

Referenced by ParseSymbol().

◆ parseEDA_TEXT()

void SCH_SEXPR_PARSER::parseEDA_TEXT ( EDA_TEXT aText,
bool  aConvertOverbarSyntax 
)
private

Definition at line 587 of file sch_sexpr_parser.cpp.

588 {
589  wxCHECK_RET( aText && CurTok() == T_effects,
590  "Cannot parse " + GetTokenString( CurTok() ) + " as an EDA_TEXT." );
591 
592  // In version 20210606 the notation for overbars was changed from `~...~` to `~{...}`.
593  // We need to convert the old syntax to the new one.
594  if( aConvertOverbarSyntax && m_requiredVersion < 20210606 )
595  aText->SetText( ConvertToNewOverbarNotation( aText->GetText() ) );
596 
597  T token;
598 
599  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
600  {
601  if( token == T_LEFT )
602  token = NextTok();
603 
604  switch( token )
605  {
606  case T_font:
607  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
608  {
609  if( token == T_LEFT )
610  token = NextTok();
611 
612  switch( token )
613  {
614  case T_size:
615  {
616  wxSize sz;
617  sz.SetHeight( parseInternalUnits( "text height" ) );
618  sz.SetWidth( parseInternalUnits( "text width" ) );
619  aText->SetTextSize( sz );
620  NeedRIGHT();
621  break;
622  }
623 
624  case T_thickness:
625  aText->SetTextThickness( parseInternalUnits( "text thickness" ) );
626  NeedRIGHT();
627  break;
628 
629  case T_bold:
630  aText->SetBold( true );
631  break;
632 
633  case T_italic:
634  aText->SetItalic( true );
635  break;
636 
637  default:
638  Expecting( "size, bold, or italic" );
639  }
640  }
641 
642  break;
643 
644  case T_justify:
645  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
646  {
647  switch( token )
648  {
649  case T_left: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); break;
650  case T_right: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); break;
651  case T_top: aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); break;
652  case T_bottom: aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); break;
653  case T_mirror: aText->SetMirrored( true ); break;
654  default: Expecting( "left, right, top, bottom, or mirror" );
655  }
656  }
657 
658  break;
659 
660  case T_hide:
661  aText->SetVisible( false );
662  break;
663 
664  default:
665  Expecting( "font, justify, or hide" );
666  }
667  }
668 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:209
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
void SetItalic(bool isItalic)
Definition: eda_text.h:200
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:206
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:124
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:223
int m_requiredVersion
Set to the symbol library file version required.
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:222
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:180
void SetBold(bool aBold)
Definition: eda_text.h:203
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:154

References ConvertToNewOverbarNotation(), EDA_TEXT::GetText(), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_TOP, m_requiredVersion, parseInternalUnits(), EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), EDA_TEXT::SetMirrored(), EDA_TEXT::SetText(), 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 533 of file sch_sexpr_parser.cpp.

534 {
535  wxCHECK_RET( CurTok() == T_fill, "Cannot parse " + GetTokenString( CurTok() ) + " as a fill." );
536 
537  aFill.m_FillType = FILL_T::NO_FILL;
538  aFill.m_Color = COLOR4D::UNSPECIFIED;
539 
540  T token;
541 
542  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
543  {
544  if( token != T_LEFT )
545  Expecting( T_LEFT );
546 
547  token = NextTok();
548 
549  switch( token )
550  {
551  case T_type:
552  {
553  token = NextTok();
554 
555  switch( token )
556  {
557  case T_none: aFill.m_FillType = FILL_T::NO_FILL; break;
558  case T_outline: aFill.m_FillType = FILL_T::FILLED_SHAPE; break;
559  case T_background: aFill.m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR; break;
560  default: Expecting( "none, outline, or background" );
561  }
562 
563  NeedRIGHT();
564  break;
565  }
566 
567  case T_color:
568  {
569  COLOR4D color;
570 
571  color.r = parseInt( "red" ) / 255.0;
572  color.g = parseInt( "green" ) / 255.0;
573  color.b = parseInt( "blue" ) / 255.0;
574  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
575  aFill.m_Color = color;
576  NeedRIGHT();
577  break;
578  }
579 
580  default:
581  Expecting( "type or color" );
582  }
583  }
584 }
int color
Definition: DXF_plotter.cpp:57
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
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:103

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 671 of file sch_sexpr_parser.cpp.

672 {
673  wxCHECK_RET( CurTok() == aHeaderType,
674  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
675 
676  NeedLEFT();
677 
678  T tok = NextTok();
679 
680  if( tok == T_version )
681  {
682  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
683 
684  if( m_requiredVersion > aFileVersion )
685  throw FUTURE_FORMAT_ERROR( FromUTF8() );
686 
687  NeedRIGHT();
688 
689  // Skip the host name and host build version information.
690  NeedLEFT();
691  NeedSYMBOL();
692  NeedSYMBOL();
693 
694  if( m_requiredVersion < 20200827 )
695  NeedSYMBOL();
696 
697  NeedRIGHT();
698  }
699  else
700  {
701  m_requiredVersion = aFileVersion;
702 
703  // Skip the host name and host build version information.
704  NeedSYMBOL();
705  NeedSYMBOL();
706  NeedRIGHT();
707  }
708 }
int m_requiredVersion
Set to the symbol library file version required.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:174

References m_requiredVersion, and parseInt().

Referenced by ParseLib(), and ParseSchematic().

◆ parseHex()

long SCH_SEXPR_PARSER::parseHex ( )
inlineprivate

Definition at line 100 of file sch_sexpr_parser.h.

101  {
102  NextTok();
103  return strtol( CurText(), nullptr, 16 );
104  }

◆ parseImage()

SCH_BITMAP * SCH_SEXPR_PARSER::parseImage ( )
private

Definition at line 2438 of file sch_sexpr_parser.cpp.

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

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

Referenced by ParseSchematic().

◆ parseInt() [1/2]

int SCH_SEXPR_PARSER::parseInt ( )
inlineprivate

Definition at line 106 of file sch_sexpr_parser.h.

107  {
108  return (int)strtol( CurText(), nullptr, 10 );
109  }

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 111 of file sch_sexpr_parser.h.

112  {
113  NeedNUMBER( aExpected );
114  return parseInt();
115  }

References parseInt().

◆ parseInternalUnits() [1/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( )
private

Definition at line 444 of file sch_sexpr_parser.cpp.

445 {
446  auto retval = parseDouble() * IU_PER_MM;
447 
448  // Schematic internal units are represented as integers. Any values that are
449  // larger or smaller than the schematic units represent undefined behavior for
450  // the system. Limit values to the largest that can be displayed on the screen.
451  constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
452 
453  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
454 }
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:73
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(), parseBusEntry(), parseCircle(), parseEDA_TEXT(), parseInternalUnits(), parseJunction(), parsePin(), parsePinNames(), parseSheet(), parseStroke(), and parseXY().

◆ parseInternalUnits() [2/3]

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

Definition at line 457 of file sch_sexpr_parser.cpp.

458 {
459  auto retval = parseDouble( aExpected ) * IU_PER_MM;
460 
461  constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
462 
463  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
464 }
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:73
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 141 of file sch_sexpr_parser.h.

142  {
143  return parseInternalUnits( GetTokenText( aToken ) );
144  }
const char * GetTokenText(T aTok)
The DSN namespace and returns the C string representing a SPECCTRA_DB::keyword.
Definition: specctra.cpp:70

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

◆ parseJunction()

SCH_JUNCTION * SCH_SEXPR_PARSER::parseJunction ( )
private

Definition at line 2620 of file sch_sexpr_parser.cpp.

2621 {
2622  wxCHECK_MSG( CurTok() == T_junction, nullptr,
2623  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a junction." ) );
2624 
2625  T token;
2626  std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
2627 
2628  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2629  {
2630  if( token != T_LEFT )
2631  Expecting( T_LEFT );
2632 
2633  token = NextTok();
2634 
2635  switch( token )
2636  {
2637  case T_at:
2638  junction->SetPosition( parseXY() );
2639  NeedRIGHT();
2640  break;
2641 
2642  case T_diameter:
2643  junction->SetDiameter( parseInternalUnits( "junction diameter" ) );
2644  NeedRIGHT();
2645  break;
2646 
2647  case T_color:
2648  {
2649  COLOR4D color;
2650 
2651  color.r = parseInt( "red" ) / 255.0;
2652  color.g = parseInt( "green" ) / 255.0;
2653  color.b = parseInt( "blue" ) / 255.0;
2654  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
2655 
2656  junction->SetColor( color );
2657  NeedRIGHT();
2658  break;
2659  }
2660 
2661  case T_uuid:
2662  NeedSYMBOL();
2663  const_cast<KIID&>( junction->m_Uuid ) = parseKIID();
2664  NeedRIGHT();
2665  break;
2666 
2667  default:
2668  Expecting( "at, diameter, color or uuid" );
2669  }
2670  }
2671 
2672  return junction.release();
2673 }
int color
Definition: DXF_plotter.cpp:57
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
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:103

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

Referenced by ParseSchematic().

◆ parseKIID()

KIID SCH_SEXPR_PARSER::parseKIID ( )
private

Definition at line 97 of file sch_sexpr_parser.cpp.

98 {
99  KIID id( FromUTF8() );
100 
101  while( m_uuids.count( id ) )
102  id.Increment();
103 
104  m_uuids.insert( id );
105 
106  return id;
107 }
Definition: kiid.h:44
std::set< KIID > m_uuids

References m_uuids.

Referenced by parseBusEntry(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), ParseSchematic(), parseSchematicSymbol(), parseSchSheetPin(), parseSchText(), and parseSheet().

◆ ParseLib()

void SCH_SEXPR_PARSER::ParseLib ( LIB_SYMBOL_MAP aSymbolLibMap)

Definition at line 125 of file sch_sexpr_parser.cpp.

126 {
127  T token;
128 
129  NeedLEFT();
130  NextTok();
131  parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
132 
133  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
134  {
135  if( token != T_LEFT )
136  Expecting( T_LEFT );
137 
138  token = NextTok();
139 
140  if( token == T_symbol )
141  {
142  m_unit = 1;
143  m_convert = 1;
144  LIB_SYMBOL* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
145  aSymbolLibMap[symbol->GetName()] = symbol;
146  }
147  else
148  {
149  Expecting( "symbol" );
150  }
151  }
152 }
wxString GetName() const override
Definition: lib_symbol.h:133
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
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...
Define a library symbol object.
Definition: lib_symbol.h:96
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
int m_convert
The current body style being parsed.
int m_requiredVersion
Set to the symbol library file version required.

References LIB_SYMBOL::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 2767 of file sch_sexpr_parser.cpp.

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

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, LAYER_BUS, LAYER_NOTES, LAYER_WIRE, parseKIID(), parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseNoConnect()

SCH_NO_CONNECT * SCH_SEXPR_PARSER::parseNoConnect ( )
private

Definition at line 2676 of file sch_sexpr_parser.cpp.

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

References parseKIID(), and parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1548 of file sch_sexpr_parser.cpp.

1549 {
1550  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1551  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1552 
1553  T token;
1554 
1555  NeedSYMBOL();
1556 
1557  wxString pageType = FromUTF8();
1558 
1559  if( !aPageInfo.SetType( pageType ) )
1560  {
1561  THROW_PARSE_ERROR( _( "Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1562  CurOffset() );
1563  }
1564 
1565  if( pageType == PAGE_INFO::Custom )
1566  {
1567  int width = Mm2mils( parseDouble( "width" ) ); // width stored in mm so we convert to mils
1568 
1569  // Perform some controls to avoid crashes if the size is edited by hands
1570  if( width < MIN_PAGE_SIZE_MILS )
1571  width = MIN_PAGE_SIZE_MILS;
1572  else if( width > MAX_PAGE_SIZE_EESCHEMA_MILS )
1574 
1575  int height = Mm2mils( parseDouble( "height" ) ); // height stored in mm so we convert to mils
1576 
1577  if( height < MIN_PAGE_SIZE_MILS )
1578  height = MIN_PAGE_SIZE_MILS;
1579  else if( height > MAX_PAGE_SIZE_EESCHEMA_MILS )
1580  height = MAX_PAGE_SIZE_EESCHEMA_MILS;
1581 
1582  aPageInfo.SetWidthMils( width );
1583  aPageInfo.SetHeightMils( height );
1584  }
1585 
1586  token = NextTok();
1587 
1588  if( token == T_portrait )
1589  {
1590  aPageInfo.SetPortrait( true );
1591  NeedRIGHT();
1592  }
1593  else if( token != T_RIGHT )
1594  {
1595  Expecting( "portrait" );
1596  }
1597 }
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 MIN_PAGE_SIZE_MILS
Min and max page sizes for clamping, in mils.
Definition: page_info.h:39
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.cpp:56
#define MAX_PAGE_SIZE_EESCHEMA_MILS
Definition: page_info.h:41
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
int m_requiredVersion
Set to the symbol library file version required.
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, MAX_PAGE_SIZE_EESCHEMA_MILS, MIN_PAGE_SIZE_MILS, 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 1179 of file sch_sexpr_parser.cpp.

1180 {
1181  auto parseType = [&]( T token ) -> ELECTRICAL_PINTYPE
1182  {
1183  switch( token )
1184  {
1185  case T_input: return ELECTRICAL_PINTYPE::PT_INPUT;
1186  case T_output: return ELECTRICAL_PINTYPE::PT_OUTPUT;
1187  case T_bidirectional: return ELECTRICAL_PINTYPE::PT_BIDI;
1188  case T_tri_state: return ELECTRICAL_PINTYPE::PT_TRISTATE;
1189  case T_passive: return ELECTRICAL_PINTYPE::PT_PASSIVE;
1190  case T_unspecified: return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1191  case T_power_in: return ELECTRICAL_PINTYPE::PT_POWER_IN;
1192  case T_power_out: return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1193  case T_open_collector: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1194  case T_open_emitter: return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1195  case T_unconnected:
1196  case T_no_connect: return ELECTRICAL_PINTYPE::PT_NC;
1197  case T_free: return ELECTRICAL_PINTYPE::PT_NIC;
1198 
1199  default:
1200  Expecting( "input, output, bidirectional, tri_state, passive, "
1201  "unspecified, power_in, power_out, open_collector, "
1202  "open_emitter, free or no_connect" );
1204  }
1205  };
1206 
1207  auto parseShape = [&]( T token ) -> GRAPHIC_PINSHAPE
1208  {
1209  switch( token )
1210  {
1211  case T_line: return GRAPHIC_PINSHAPE::LINE;
1212  case T_inverted: return GRAPHIC_PINSHAPE::INVERTED;
1213  case T_clock: return GRAPHIC_PINSHAPE::CLOCK;
1214  case T_inverted_clock: return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1215  case T_input_low: return GRAPHIC_PINSHAPE::INPUT_LOW;
1216  case T_clock_low: return GRAPHIC_PINSHAPE::CLOCK_LOW;
1217  case T_output_low: return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1218  case T_edge_clock_high: return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1219  case T_non_logic: return GRAPHIC_PINSHAPE::NONLOGIC;
1220 
1221  default:
1222  Expecting( "line, inverted, clock, inverted_clock, input_low, "
1223  "clock_low, output_low, edge_clock_high, non_logic" );
1224  return GRAPHIC_PINSHAPE::LINE;
1225  }
1226  };
1227 
1228  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1229  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a pin token." ) );
1230 
1231  T token;
1232  wxString tmp;
1233  wxString error;
1234  std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( nullptr );
1235 
1236  pin->SetUnit( m_unit );
1237  pin->SetConvert( m_convert );
1238 
1239  // Pin electrical type.
1240  token = NextTok();
1241  pin->SetType( parseType( token ) );
1242 
1243  // Pin shape.
1244  token = NextTok();
1245  pin->SetShape( parseShape( token ) );
1246 
1247  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1248  {
1249  if( token == T_hide )
1250  {
1251  pin->SetVisible( false );
1252  continue;
1253  }
1254 
1255  if( token != T_LEFT )
1256  Expecting( T_LEFT );
1257 
1258  token = NextTok();
1259 
1260  switch( token )
1261  {
1262  case T_at:
1263  pin->SetPosition( parseXY() );
1264 
1265  switch( parseInt( "pin orientation" ) )
1266  {
1267  case 0: pin->SetOrientation( PIN_RIGHT ); break;
1268  case 90: pin->SetOrientation( PIN_UP ); break;
1269  case 180: pin->SetOrientation( PIN_LEFT ); break;
1270  case 270: pin->SetOrientation( PIN_DOWN ); break;
1271  default: Expecting( "0, 90, 180, or 270" );
1272  }
1273 
1274  NeedRIGHT();
1275  break;
1276 
1277  case T_length:
1278  pin->SetLength( parseInternalUnits( "pin length" ) );
1279  NeedRIGHT();
1280  break;
1281 
1282  case T_name:
1283  token = NextTok();
1284 
1285  if( !IsSymbol( token ) )
1286  {
1287  THROW_PARSE_ERROR( _( "Invalid pin name" ), CurSource(), CurLine(), CurLineNumber(),
1288  CurOffset() );
1289  }
1290 
1291  if( m_requiredVersion < 20210606 )
1292  pin->SetName( ConvertToNewOverbarNotation( FromUTF8() ) );
1293  else
1294  pin->SetName( FromUTF8() );
1295 
1296  token = NextTok();
1297 
1298  if( token != T_RIGHT )
1299  {
1300  token = NextTok();
1301 
1302  if( token == T_effects )
1303  {
1304  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1305  // so duplicate parsing is not required.
1306  EDA_TEXT text;
1307 
1308  parseEDA_TEXT( &text, true );
1309  pin->SetNameTextSize( text.GetTextHeight() );
1310  NeedRIGHT();
1311  }
1312  else
1313  {
1314  Expecting( "effects" );
1315  }
1316  }
1317 
1318  break;
1319 
1320  case T_number:
1321  token = NextTok();
1322 
1323  if( !IsSymbol( token ) )
1324  {
1325  THROW_PARSE_ERROR( _( "Invalid pin number" ), CurSource(), CurLine(),
1326  CurLineNumber(), CurOffset() );
1327  }
1328 
1329  pin->SetNumber( FromUTF8() );
1330  token = NextTok();
1331 
1332  if( token != T_RIGHT )
1333  {
1334  token = NextTok();
1335 
1336  if( token == T_effects )
1337  {
1338  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1339  // so duplicate parsing is not required.
1340  EDA_TEXT text;
1341 
1342  parseEDA_TEXT( &text, false );
1343  pin->SetNumberTextSize( text.GetTextHeight() );
1344  NeedRIGHT();
1345  }
1346  else
1347  {
1348  Expecting( "effects" );
1349  }
1350  }
1351 
1352  break;
1353 
1354  case T_alternate:
1355  {
1356  LIB_PIN::ALT alt;
1357 
1358  token = NextTok();
1359 
1360  if( !IsSymbol( token ) )
1361  {
1362  THROW_PARSE_ERROR( _( "Invalid alternate pin name" ), CurSource(), CurLine(),
1363  CurLineNumber(), CurOffset() );
1364  }
1365 
1366  alt.m_Name = FromUTF8();
1367 
1368  token = NextTok();
1369  alt.m_Type = parseType( token );
1370 
1371  token = NextTok();
1372  alt.m_Shape = parseShape( token );
1373 
1374  pin->GetAlternates()[ alt.m_Name ] = alt;
1375 
1376  NeedRIGHT();
1377  }
1378  break;
1379 
1380  default:
1381  Expecting( "at, name, number, length, or alternate" );
1382  }
1383  }
1384 
1385  return pin.release();
1386 }
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
power input (GND, VCC for ICs). Must be connected to a power output.
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
pin for passive symbols: 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:48
GRAPHIC_PINSHAPE
Definition: pin_type.h:55
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:60
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:140
not internally connected (may be connected to anything)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
int m_convert
The current body style being parsed.
wxString m_Name
Definition: lib_pin.h:58
#define _(s)
int m_requiredVersion
Set to the symbol library file version required.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:35
usual pin input: must be connected
input or output (like port for a microprocessor)
not connected (must be left open)
output of a regulator: intended to be connected to power input pins
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:59

References _, CLOCK, CLOCK_LOW, ConvertToNewOverbarNotation(), FALLING_EDGE_CLOCK, INPUT_LOW, INVERTED, INVERTED_CLOCK, LINE, m_convert, LIB_PIN::ALT::m_Name, m_requiredVersion, 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_PARSE_ERROR.

Referenced by ParseDrawItem().

◆ parsePinNames()

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

Definition at line 711 of file sch_sexpr_parser.cpp.

712 {
713  wxCHECK_RET( CurTok() == T_pin_names,
714  "Cannot parse " + GetTokenString( CurTok() ) + " as a pin_name token." );
715 
716  wxString error;
717 
718  T token = NextTok();
719 
720  if( token == T_LEFT )
721  {
722  token = NextTok();
723 
724  if( token != T_offset )
725  Expecting( "offset" );
726 
727  aSymbol->SetPinNameOffset( parseInternalUnits( "pin name offset" ) );
728  NeedRIGHT();
729  token = NextTok(); // Either ) or hide
730  }
731 
732  if( token == T_hide )
733  {
734  aSymbol->SetShowPinNames( false );
735  NeedRIGHT();
736  }
737  else if( token != T_RIGHT )
738  {
739  THROW_PARSE_ERROR( _( "Invalid pin names definition" ), CurSource(), CurLine(),
740  CurLineNumber(), CurOffset() );
741  }
742 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)

References _, parseInternalUnits(), and THROW_PARSE_ERROR.

Referenced by ParseSymbol().

◆ parsePolyLine()

LIB_SHAPE * SCH_SEXPR_PARSER::parsePolyLine ( )
private

Definition at line 1389 of file sch_sexpr_parser.cpp.

1390 {
1391  wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1392  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a poly." ) );
1393 
1394  T token;
1396  FILL_PARAMS fill;
1397  std::unique_ptr<LIB_SHAPE> poly = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::POLY );
1398 
1399  poly->SetUnit( m_unit );
1400  poly->SetConvert( m_convert );
1401 
1402  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1403  {
1404  if( token != T_LEFT )
1405  Expecting( T_LEFT );
1406 
1407  token = NextTok();
1408 
1409  switch( token )
1410  {
1411  case T_pts:
1412  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1413  {
1414  if( token != T_LEFT )
1415  Expecting( T_LEFT );
1416 
1417  token = NextTok();
1418 
1419  if( token != T_xy )
1420  Expecting( "xy" );
1421 
1422  poly->AddPoint( parseXY() );
1423 
1424  NeedRIGHT();
1425  }
1426 
1427  break;
1428 
1429  case T_stroke:
1430  parseStroke( stroke );
1431  poly->SetWidth( stroke.GetWidth() );
1432  break;
1433 
1434  case T_fill:
1435  parseFill( fill );
1436  poly->SetFillMode( fill.m_FillType );
1437  break;
1438 
1439  default:
1440  Expecting( "pts, stroke, or fill" );
1441  }
1442  }
1443 
1444  return poly.release();
1445 }
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
Simple container to manage line stroke parameters.
Definition: sch_item.h:140
void parseFill(FILL_PARAMS &aFill)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetWidth(), m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseStroke(), parseXY(), and POLY.

Referenced by ParseDrawItem().

◆ parseProperty()

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

Definition at line 745 of file sch_sexpr_parser.cpp.

746 {
747  wxCHECK_MSG( CurTok() == T_property, nullptr,
748  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a property." ) );
749  wxCHECK( aSymbol, nullptr );
750 
751  wxString error;
752  wxString name;
753  wxString value;
754  std::unique_ptr<LIB_FIELD> field = std::make_unique<LIB_FIELD>( aSymbol.get(),
756 
757  T token = NextTok();
758 
759  if( !IsSymbol( token ) )
760  {
761  THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
762  CurOffset() );
763  }
764 
765  name = FromUTF8();
766 
767  if( name.IsEmpty() )
768  {
769  THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
770  CurOffset() );
771  }
772 
773  field->SetName( name );
774  token = NextTok();
775 
776  if( !IsSymbol( token ) )
777  {
778  THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
779  CurOffset() );
780  }
781 
782  // Empty property values are valid.
783  value = FromUTF8();
784 
785  field->SetText( value );
786 
787  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
788  {
789  if( token != T_LEFT )
790  Expecting( T_LEFT );
791 
792  token = NextTok();
793 
794  switch( token )
795  {
796  case T_id:
797  field->SetId( parseInt( "field ID" ) );
798  NeedRIGHT();
799  break;
800 
801  case T_at:
802  field->SetPosition( parseXY() );
803  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
804  NeedRIGHT();
805  break;
806 
807  case T_effects:
808  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
809  break;
810 
811  default:
812  Expecting( "id, at or effects" );
813  }
814  }
815 
816  // Due to an bug when in #LIB_SYMBOL::Flatten, duplicate ids slipped through
817  // when writing files. This section replaces duplicate #LIB_FIELD indices on
818  // load.
819  if( m_fieldIDsRead.count( field->GetId() ) )
820  {
821  int nextAvailableId = field->GetId() + 1;
822 
823  while( m_fieldIDsRead.count( nextAvailableId ) )
824  nextAvailableId += 1;
825 
826  field->SetId( nextAvailableId );
827  }
828 
829  LIB_FIELD* existingField;
830 
831  if( field->GetId() < MANDATORY_FIELDS )
832  {
833  existingField = aSymbol->GetFieldById( field->GetId() );
834 
835  *existingField = *field;
836  m_fieldIDsRead.insert( field->GetId() );
837  return existingField;
838  }
839  else if( name == "ki_keywords" )
840  {
841  // Not a LIB_FIELD object yet.
842  aSymbol->SetKeyWords( value );
843  return nullptr;
844  }
845  else if( name == "ki_description" )
846  {
847  // Not a LIB_FIELD object yet.
848  aSymbol->SetDescription( value );
849  return nullptr;
850  }
851  else if( name == "ki_fp_filters" )
852  {
853  // Not a LIB_FIELD object yet.
854  wxArrayString filters;
855  wxStringTokenizer tokenizer( value );
856 
857  while( tokenizer.HasMoreTokens() )
858  {
859  wxString curr_token = UnescapeString( tokenizer.GetNextToken() );
860  filters.Add( curr_token );
861  }
862 
863  aSymbol->SetFPFilters( filters );
864  return nullptr;
865  }
866  else if( name == "ki_locked" )
867  {
868  // This is a temporary LIB_FIELD object until interchangeable units are determined on
869  // the fly.
870  aSymbol->LockUnits( true );
871  return nullptr;
872  }
873  else
874  {
875  // At this point, a user field is read.
876  existingField = aSymbol->FindField( field->GetCanonicalName() );
877 
878 #if 1 // Enable it to modify the name of the field to add if already existing
879  // Disable it to skip the field having the same name as previous field
880  if( existingField )
881  {
882  // We cannot handle 2 fields with the same name, so because the field name
883  // is already in use, try to build a new name (oldname_x)
884  wxString base_name = field->GetCanonicalName();
885 
886  // Arbitrary limit 10 attempts to find a new name
887  for( int ii = 1; ii < 10 && existingField ; ii++ )
888  {
889  wxString newname = base_name;
890  newname << '_' << ii;
891 
892  existingField = aSymbol->FindField( newname );
893 
894  if( !existingField ) // the modified name is not found, use it
895  field->SetName( newname );
896  }
897  }
898 #endif
899  if( !existingField )
900  {
901  aSymbol->AddDrawItem( field.get(), false );
902  m_fieldIDsRead.insert( field->GetId() );
903  return field.release();
904  }
905  else
906  {
907  // We cannot handle 2 fields with the same name, so skip this one
908  return nullptr;
909  }
910  }
911 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
Field object used in symbol libraries.
Definition: lib_field.h:59
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
Field Value of part, i.e. "3.3K".
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:402
#define _(s)
wxString UnescapeString(const wxString &aSource)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
const char * name
Definition: DXF_plotter.cpp:56
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References _, LIB_FIELD::GetCanonicalName(), m_fieldIDsRead, MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), THROW_PARSE_ERROR, UnescapeString(), and VALUE_FIELD.

Referenced by ParseSymbol().

◆ parseRectangle()

LIB_SHAPE * SCH_SEXPR_PARSER::parseRectangle ( )
private

Definition at line 1448 of file sch_sexpr_parser.cpp.

1449 {
1450  wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1451  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
1452 
1453  T token;
1455  FILL_PARAMS fill;
1456  std::unique_ptr<LIB_SHAPE> rectangle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::RECT );
1457 
1458  rectangle->SetUnit( m_unit );
1459  rectangle->SetConvert( m_convert );
1460 
1461  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1462  {
1463  if( token != T_LEFT )
1464  Expecting( T_LEFT );
1465 
1466  token = NextTok();
1467 
1468  switch( token )
1469  {
1470  case T_start:
1471  rectangle->SetPosition( parseXY() );
1472  NeedRIGHT();
1473  break;
1474 
1475  case T_end:
1476  rectangle->SetEnd( parseXY() );
1477  NeedRIGHT();
1478  break;
1479 
1480  case T_stroke:
1481  parseStroke( stroke );
1482  rectangle->SetWidth( stroke.GetWidth() );
1483  break;
1484 
1485  case T_fill:
1486  parseFill( fill );
1487  rectangle->SetFillMode( fill.m_FillType );
1488  break;
1489 
1490  default:
1491  Expecting( "start, end, stroke, or fill" );
1492  }
1493  }
1494 
1495  return rectangle.release();
1496 }
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
Simple container to manage line stroke parameters.
Definition: sch_item.h:140
void parseFill(FILL_PARAMS &aFill)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetWidth(), m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseStroke(), parseXY(), and RECT.

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 2013 of file sch_sexpr_parser.cpp.

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

References SCH_SCREEN::AddLibSymbol(), SCH_SCREEN::Append(), checkpoint(), SCH_SHEET::GetScreen(), m_requiredVersion, SCH_SCREEN::m_uuid, parseBusAlias(), parseBusEntry(), parseHeader(), parseImage(), parseJunction(), parseKIID(), 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, LIB_SYMBOL::UpdateFieldOrdinals(), and SCH_SCREEN::UpdateLocalLibSymbolLinks().

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

◆ parseSchematicSymbol()

SCH_SYMBOL * SCH_SEXPR_PARSER::parseSchematicSymbol ( )
private

Definition at line 2199 of file sch_sexpr_parser.cpp.

2200 {
2201  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
2202  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
2203 
2204  T token;
2205  wxString tmp;
2206  wxString libName;
2207  SCH_FIELD* field;
2208  std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2209  TRANSFORM transform;
2210  std::set<int> fieldIDsRead;
2211 
2212  // We'll reset this if we find a fields_autoplaced token
2213  symbol->ClearFieldsAutoplaced();
2214 
2216 
2217  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2218  {
2219  if( token != T_LEFT )
2220  Expecting( T_LEFT );
2221 
2222  token = NextTok();
2223 
2224  switch( token )
2225  {
2226  case T_lib_name:
2227  {
2228  LIB_ID libId;
2229 
2230  token = NextTok();
2231 
2232  if( !IsSymbol( token ) )
2233  {
2234  THROW_PARSE_ERROR( _( "Invalid symbol library name" ), CurSource(), CurLine(),
2235  CurLineNumber(), CurOffset() );
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  THROW_PARSE_ERROR( _( "Invalid symbol library ID" ), CurSource(), CurLine(),
2255  CurLineNumber(), CurOffset() );
2256  }
2257 
2258  symbol->SetLibId( libId );
2259  NeedRIGHT();
2260  break;
2261  }
2262 
2263  case T_at:
2264  symbol->SetPosition( parseXY() );
2265 
2266  switch( static_cast<int>( parseDouble( "symbol orientation" ) ) )
2267  {
2268  case 0: transform = TRANSFORM(); break;
2269  case 90: transform = TRANSFORM( 0, -1, -1, 0 ); break;
2270  case 180: transform = TRANSFORM( -1, 0, 0, 1 ); break;
2271  case 270: transform = TRANSFORM( 0, 1, 1, 0 ); break;
2272  default: Expecting( "0, 90, 180, or 270" );
2273  }
2274 
2275  symbol->SetTransform( transform );
2276  NeedRIGHT();
2277  break;
2278 
2279  case T_mirror:
2280  token = NextTok();
2281 
2282  if( token == T_x )
2283  symbol->SetOrientation( SYM_MIRROR_X );
2284  else if( token == T_y )
2285  symbol->SetOrientation( SYM_MIRROR_Y );
2286  else
2287  Expecting( "x or y" );
2288 
2289  NeedRIGHT();
2290  break;
2291 
2292  case T_unit:
2293  symbol->SetUnit( parseInt( "symbol unit" ) );
2294  NeedRIGHT();
2295  break;
2296 
2297  case T_convert:
2298  symbol->SetConvert( parseInt( "symbol convert" ) );
2299  NeedRIGHT();
2300  break;
2301 
2302  case T_in_bom:
2303  symbol->SetIncludeInBom( parseBool() );
2304  NeedRIGHT();
2305  break;
2306 
2307  case T_on_board:
2308  symbol->SetIncludeOnBoard( parseBool() );
2309  NeedRIGHT();
2310  break;
2311 
2312  case T_fields_autoplaced:
2313  symbol->SetFieldsAutoplaced();
2314  NeedRIGHT();
2315  break;
2316 
2317  case T_uuid:
2318  NeedSYMBOL();
2319  const_cast<KIID&>( symbol->m_Uuid ) = parseKIID();
2320  NeedRIGHT();
2321  break;
2322 
2323  case T_property:
2324  // The field parent symbol must be set and its orientation must be set before
2325  // the field positions are set.
2326  field = parseSchField( symbol.get() );
2327 
2328  // It would appear that at some point we allowed duplicate ids to slip through
2329  // when writing files. The easiest (and most complete) solution is to disallow
2330  // multiple instances of the same id (for all files since the source of the error
2331  // *might* in fact be hand-edited files).
2332  //
2333  // While no longer used, -1 is still a valid id for user field. It gets converted
2334  // to the next unused number on save.
2335  if( fieldIDsRead.count( field->GetId() ) )
2336  field->SetId( -1 );
2337  else
2338  fieldIDsRead.insert( field->GetId() );
2339 
2340  // Set the default symbol reference prefix.
2341  if( field->GetId() == REFERENCE_FIELD )
2342  {
2343  wxString refDesignator = field->GetText();
2344 
2345  refDesignator.Replace( "~", " " );
2346 
2347  wxString prefix = refDesignator;
2348 
2349  while( prefix.Length() )
2350  {
2351  if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' )
2352  break;
2353 
2354  prefix.RemoveLast();
2355  }
2356 
2357  // Avoid a prefix containing trailing/leading spaces
2358  prefix.Trim( true );
2359  prefix.Trim( false );
2360 
2361  if( prefix.IsEmpty() )
2362  symbol->SetPrefix( wxString( "U" ) );
2363  else
2364  symbol->SetPrefix( prefix );
2365  }
2366 
2367  if( symbol->GetFieldById( field->GetId() ) )
2368  *symbol->GetFieldById( field->GetId() ) = *field;
2369  else
2370  symbol->AddField( *field );
2371 
2372  delete field;
2373  break;
2374 
2375  case T_pin:
2376  {
2377  // Read an alternate pin designation
2378  wxString number;
2379  KIID uuid;
2380  wxString alt;
2381 
2382  NeedSYMBOL();
2383  number = FromUTF8();
2384 
2385  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2386  {
2387  if( token != T_LEFT )
2388  Expecting( T_LEFT );
2389 
2390  token = NextTok();
2391 
2392  switch( token )
2393  {
2394  case T_alternate:
2395  NeedSYMBOL();
2396  alt = FromUTF8();
2397  NeedRIGHT();
2398  break;
2399 
2400  case T_uuid:
2401  NeedSYMBOL();
2402 
2403  // First version to write out pin uuids accidentally wrote out the symbol's
2404  // uuid for each pin, so ignore uuids coming from that version.
2405  if( m_requiredVersion >= 20210126 )
2406  uuid = parseKIID();
2407 
2408  NeedRIGHT();
2409  break;
2410 
2411  default:
2412  Expecting( "alternate or uuid" );
2413  }
2414  }
2415 
2416  symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(),
2417  number, alt ) );
2418 
2419  const_cast<KIID&>( symbol->GetRawPins().back()->m_Uuid ) = uuid;
2420  }
2421  break;
2422 
2423  default:
2424  Expecting( "lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
2425  }
2426  }
2427 
2428  if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2429  symbol->SetSchSymbolLibraryName( libName );
2430 
2431  // Ensure edit/status flags are cleared after these initializations:
2432  symbol->ClearFlags();
2433 
2434  return symbol.release();
2435 }
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 symbol's value,...
Definition: sch_field.h:49
int GetId() const
Definition: sch_field.h:113
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
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
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:49
int m_requiredVersion
Set to the symbol library file version required.
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
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:154

References _, SCH_FIELD::GetId(), EDA_TEXT::GetText(), m_fieldId, m_requiredVersion, MANDATORY_FIELDS, LIB_ID::Parse(), parseBool(), parseDouble(), parseInt(), parseKIID(), parseSchField(), parseXY(), REFERENCE_FIELD, SCH_FIELD::SetId(), SYM_MIRROR_X, SYM_MIRROR_Y, and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseSchField()

SCH_FIELD * SCH_SEXPR_PARSER::parseSchField ( SCH_ITEM aParent)
private

Definition at line 1704 of file sch_sexpr_parser.cpp.

1705 {
1706  wxCHECK_MSG( CurTok() == T_property, nullptr,
1707  "Cannot parse " + GetTokenString( CurTok() ) + " as a property token." );
1708 
1709  T token = NextTok();
1710 
1711  if( !IsSymbol( token ) )
1712  {
1713  THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1714  CurOffset() );
1715  }
1716 
1717  wxString name = FromUTF8();
1718 
1719  if( name.IsEmpty() )
1720  {
1721  THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1722  CurOffset() );
1723  }
1724 
1725  token = NextTok();
1726 
1727  if( !IsSymbol( token ) )
1728  {
1729  THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1730  CurOffset() );
1731  }
1732 
1733  // Empty property values are valid.
1734  wxString value = FromUTF8();
1735 
1736  std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1,
1737  aParent, name );
1738 
1739  field->SetText( value );
1740  field->SetVisible( true );
1741 
1742  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1743  {
1744  if( token != T_LEFT )
1745  Expecting( T_LEFT );
1746 
1747  token = NextTok();
1748 
1749  switch( token )
1750  {
1751  case T_id:
1752  field->SetId( parseInt( "field ID" ) );
1753  NeedRIGHT();
1754  break;
1755 
1756  case T_at:
1757  field->SetPosition( parseXY() );
1758  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
1759  NeedRIGHT();
1760  break;
1761 
1762  case T_effects:
1763  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
1764  break;
1765 
1766  default:
1767  Expecting( "at or effects" );
1768  }
1769  }
1770 
1771  return field.release();
1772 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
Field Value of part, i.e. "3.3K".
#define _(s)
const char * name
Definition: DXF_plotter.cpp:56
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

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

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

◆ parseSchSheetInstances()

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

Definition at line 1861 of file sch_sexpr_parser.cpp.

1862 {
1863  wxCHECK_RET( CurTok() == T_sheet_instances,
1864  "Cannot parse " + GetTokenString( CurTok() ) + " as an instances token." );
1865  wxCHECK( aScreen, /* void */ );
1866 
1867  T token;
1868 
1869  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1870  {
1871  if( token != T_LEFT )
1872  Expecting( T_LEFT );
1873 
1874  token = NextTok();
1875 
1876  switch( token )
1877  {
1878  case T_path:
1879  {
1880  NeedSYMBOL();
1881 
1882  SCH_SHEET_INSTANCE instance;
1883 
1884  instance.m_Path = KIID_PATH( FromUTF8() );
1885 
1886  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1887  {
1888  if( token != T_LEFT )
1889  Expecting( T_LEFT );
1890 
1891  token = NextTok();
1892 
1893  std::vector<wxString> whitespaces = { wxT( "\r" ), wxT( "\n" ), wxT( "\t" ),
1894  wxT( " " ) };
1895 
1896  size_t numReplacements = 0;
1897 
1898  switch( token )
1899  {
1900  case T_page:
1901  NeedSYMBOL();
1902  instance.m_PageNumber = FromUTF8();
1903 
1904  // Whitespaces are not permitted
1905  for( wxString ch : whitespaces )
1906  numReplacements += instance.m_PageNumber.Replace( ch, wxEmptyString );
1907 
1908 
1909  // Empty page numbers are not permitted
1910  if( instance.m_PageNumber.IsEmpty() )
1911  {
1912  // Use hash character instead
1913  instance.m_PageNumber = wxT( "#" );
1914  numReplacements++;
1915  }
1916 
1917  // Set the file as modified so the user can be warned.
1918  if( numReplacements > 0 )
1919  aScreen->SetContentModified();
1920 
1921  NeedRIGHT();
1922  break;
1923 
1924  default:
1925  Expecting( "path or page" );
1926  }
1927  }
1928 
1929  aScreen->m_sheetInstances.emplace_back( instance );
1930  break;
1931  }
1932 
1933  default:
1934  Expecting( "path" );
1935  }
1936  }
1937 }
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:572
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
A simple container for sheet instance information.

References SCH_SHEET_INSTANCE::m_PageNumber, SCH_SHEET_INSTANCE::m_Path, SCH_SCREEN::m_sheetInstances, and BASE_SCREEN::SetContentModified().

Referenced by ParseSchematic().

◆ parseSchSheetPin()

SCH_SHEET_PIN * SCH_SEXPR_PARSER::parseSchSheetPin ( SCH_SHEET aSheet)
private

Definition at line 1775 of file sch_sexpr_parser.cpp.

1776 {
1777  wxCHECK_MSG( aSheet != nullptr, nullptr, "" );
1778  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1779  "Cannot parse " + GetTokenString( CurTok() ) + " as a sheet pin token." );
1780 
1781  T token = NextTok();
1782 
1783  if( !IsSymbol( token ) )
1784  {
1785  THROW_PARSE_ERROR( _( "Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1786  CurOffset() );
1787  }
1788 
1789  wxString name = FromUTF8();
1790 
1791  if( name.IsEmpty() )
1792  {
1793  THROW_PARSE_ERROR( _( "Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1794  CurOffset() );
1795  }
1796 
1797  auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet, wxPoint( 0, 0 ), name );
1798 
1799  token = NextTok();
1800 
1801  switch( token )
1802  {
1803  case T_input: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
1804  case T_output: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
1805  case T_bidirectional: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
1806  case T_tri_state: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
1807  case T_passive: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
1808  default:
1809  Expecting( "input, output, bidirectional, tri_state, or passive" );
1810  }
1811 
1812  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1813  {
1814  if( token != T_LEFT )
1815  Expecting( T_LEFT );
1816 
1817  token = NextTok();
1818 
1819  switch( token )
1820  {
1821  case T_at:
1822  {
1823  sheetPin->SetPosition( parseXY() );
1824 
1825  double angle = parseDouble( "sheet pin angle (side)" );
1826 
1827  if( angle == 0.0 )
1828  sheetPin->SetSide( SHEET_SIDE::RIGHT );
1829  else if( angle == 90.0 )
1830  sheetPin->SetSide( SHEET_SIDE::TOP );
1831  else if( angle == 180.0 )
1832  sheetPin->SetSide( SHEET_SIDE::LEFT );
1833  else if( angle == 270.0 )
1834  sheetPin->SetSide( SHEET_SIDE::BOTTOM );
1835  else
1836  Expecting( "0, 90, 180, or 270" );
1837 
1838  NeedRIGHT();
1839  break;
1840  }
1841 
1842  case T_effects:
1843  parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ), true );
1844  break;
1845 
1846  case T_uuid:
1847  NeedSYMBOL();
1848  const_cast<KIID&>( sheetPin->m_Uuid ) = parseKIID();
1849  NeedRIGHT();
1850  break;
1851 
1852  default:
1853  Expecting( "at, uuid or effects" );
1854  }
1855  }
1856 
1857  return sheetPin.release();
1858 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
const char * name
Definition: DXF_plotter.cpp:56
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...

References _, PNS::angle(), BOTTOM, LEFT, name, parseDouble(), parseEDA_TEXT(), parseKIID(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, RIGHT, THROW_PARSE_ERROR, and TOP.

Referenced by parseSheet().

◆ parseSchSymbolInstances()

void SCH_SEXPR_PARSER::parseSchSymbolInstances ( SCH_SCREEN aScreen)
private

Definition at line 1940 of file sch_sexpr_parser.cpp.

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

2834 {
2835  T token;
2836  std::unique_ptr<SCH_TEXT> text;
2837 
2838  switch( CurTok() )
2839  {
2840  case T_text: text = std::make_unique<SCH_TEXT>(); break;
2841  case T_label: text = std::make_unique<SCH_LABEL>(); break;
2842  case T_global_label: text = std::make_unique<SCH_GLOBALLABEL>(); break;
2843  case T_hierarchical_label: text = std::make_unique<SCH_HIERLABEL>(); break;
2844  default:
2845  wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as text." );
2846  }
2847 
2848  // We'll reset this if we find a fields_autoplaced token
2849  text->ClearFieldsAutoplaced();
2850 
2851  NeedSYMBOL();
2852 
2853  text->SetText( FromUTF8() );
2854 
2855  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2856  {
2857  if( token != T_LEFT )
2858  Expecting( T_LEFT );
2859 
2860  token = NextTok();
2861 
2862  switch( token )
2863  {
2864  case T_at:
2865  text->SetPosition( parseXY() );
2866 
2867  switch( static_cast<int>( parseDouble( "text angle" ) ) )
2868  {
2869  case 0: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT ); break;
2870  case 90: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::UP ); break;
2871  case 180: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); break;
2872  case 270: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM ); break;
2873  default:
2874  wxFAIL;
2875  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT );
2876  break;
2877  }
2878 
2879  NeedRIGHT();
2880  break;
2881 
2882  case T_shape:
2883  if( text->Type() == SCH_TEXT_T || text->Type() == SCH_LABEL_T )
2884  Unexpected( T_shape );
2885 
2886  token = NextTok();
2887 
2888  switch( token )
2889  {
2890  case T_input: text->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
2891  case T_output: text->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
2892  case T_bidirectional: text->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
2893  case T_tri_state: text->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
2894  case T_passive: text->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
2895  default:
2896  Expecting( "input, output, bidirectional, tri_state, or passive" );
2897  }
2898 
2899  NeedRIGHT();
2900  break;
2901 
2902  case T_fields_autoplaced:
2903  text->SetFieldsAutoplaced();
2904  NeedRIGHT();
2905  break;
2906 
2907  case T_effects:
2908  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
2909 
2910  // Spin style is defined differently for graphical text (#SCH_TEXT) objects.
2911  if( text->Type() == SCH_TEXT_T )
2912  {
2913  if( text->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT
2914  && text->GetTextAngle() == TEXT_ANGLE_VERT )
2915  {
2916  // The vertically aligned text angle is always 90 (labels use 270 for the
2917  // down direction) combined with the text justification flags.
2918  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM );
2919  }
2920  else if( text->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT
2921  && text->GetTextAngle() == TEXT_ANGLE_HORIZ )
2922  {
2923  // The horizontally aligned text angle is always 0 (labels use 180 for the
2924  // left direction) combined with the text justification flags.
2925  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT );
2926  }
2927  }
2928 
2929  break;
2930 
2931  case T_iref: // legacy format; current is a T_property (aka SCH_FIELD)
2932  if( text->Type() == SCH_GLOBAL_LABEL_T )
2933  {
2934  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2935  SCH_FIELD* field = label->GetIntersheetRefs();
2936 
2937  field->SetTextPos( parseXY() );
2938  NeedRIGHT();
2939 
2940  field->SetVisible( true );
2941  }
2942  break;
2943 
2944  case T_uuid:
2945  NeedSYMBOL();
2946  const_cast<KIID&>( text->m_Uuid ) = parseKIID();
2947  NeedRIGHT();
2948  break;
2949 
2950  case T_property:
2951  if( text->Type() == SCH_GLOBAL_LABEL_T )
2952  {
2953  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2954  SCH_FIELD* field = parseSchField( label );
2955 
2956  field->SetLayer( LAYER_GLOBLABEL );
2957  label->SetIntersheetRefs( *field );
2958 
2959  delete field;
2960  }
2961  break;
2962 
2963  default:
2964  Expecting( "at, shape, iref, uuid or effects" );
2965  }
2966  }
2967 
2968  return text.release();
2969 }
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: eda_text.h:71
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:267
void SetIntersheetRefs(const SCH_FIELD &aField)
Definition: sch_text.h:416
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:415
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...
#define TEXT_ANGLE_VERT
Definition: eda_text.h:72

References LABEL_SPIN_STYLE::BOTTOM, SCH_GLOBALLABEL::GetIntersheetRefs(), GR_TEXT_HJUSTIFY_RIGHT, LAYER_GLOBLABEL, LABEL_SPIN_STYLE::LEFT, parseDouble(), parseEDA_TEXT(), parseKIID(), 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, TEXT_ANGLE_HORIZ, TEXT_ANGLE_VERT, and LABEL_SPIN_STYLE::UP.

Referenced by ParseSchematic().

◆ parseSheet()

SCH_SHEET * SCH_SEXPR_PARSER::parseSheet ( )
private

Definition at line 2513 of file sch_sexpr_parser.cpp.

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

468 {
469  wxCHECK_RET( CurTok() == T_stroke,
470  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) );
471 
472  aStroke.SetWidth( Mils2iu( DEFAULT_LINE_WIDTH_MILS ) );
474  aStroke.SetColor( COLOR4D::UNSPECIFIED );
475 
476  T token;
477 
478  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
479  {
480  if( token != T_LEFT )
481  Expecting( T_LEFT );
482 
483  token = NextTok();
484 
485  switch( token )
486  {
487  case T_width:
488  aStroke.SetWidth( parseInternalUnits( "stroke width" ) );
489  NeedRIGHT();
490  break;
491 
492  case T_type:
493  {
494  token = NextTok();
495 
496  switch( token )
497  {
498  case T_dash: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH ); break;
499  case T_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT ); break;
500  case T_dash_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT ); break;
501  case T_solid: aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID ); break;
502  case T_default: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); break;
503  default:
504  Expecting( "solid, dash, dash_dot, dot or default" );
505  }
506 
507  NeedRIGHT();
508  break;
509  }
510 
511  case T_color:
512  {
513  COLOR4D color;
514 
515  color.r = parseInt( "red" ) / 255.0;
516  color.g = parseInt( "green" ) / 255.0;
517  color.b = parseInt( "blue" ) / 255.0;
518  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
519 
520  aStroke.SetColor( color );
521  NeedRIGHT();
522  break;
523  }
524 
525  default:
526  Expecting( "width, type, or color" );
527  }
528 
529  }
530 }
void SetWidth(int aWidth)
Definition: sch_item.h:153
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int color
Definition: DXF_plotter.cpp:57
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
Definition: sch_item.h:156
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
void SetColor(const COLOR4D &aColor)
Definition: sch_item.h:159
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:103

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

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

◆ ParseSymbol()

LIB_SYMBOL * SCH_SEXPR_PARSER::ParseSymbol ( LIB_SYMBOL_MAP aSymbolLibMap,
int  aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION 
)

Definition at line 155 of file sch_sexpr_parser.cpp.

156 {
157  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
158  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
159 
160  T token;
161  long tmp;
162  wxString name;
163  wxString error;
164  LIB_ITEM* item;
165  std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
166 
167  m_requiredVersion = aFileVersion;
168  symbol->SetUnitCount( 1 );
169 
171  m_fieldIDsRead.clear();
172 
173  token = NextTok();
174 
175  if( !IsSymbol( token ) )
176  {
177  THROW_PARSE_ERROR( _( "Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
178  CurOffset() );
179  }
180 
181  name = FromUTF8();
182 
183  LIB_ID id;
184 
185  if( id.Parse( name ) >= 0 )
186  {
187  THROW_PARSE_ERROR( _( "Invalid library identifier" ), CurSource(), CurLine(),
188  CurLineNumber(), CurOffset() );
189  }
190 
191  m_symbolName = id.GetLibItemName().wx_str();
192  symbol->SetName( m_symbolName );
193  symbol->SetLibId( id );
194 
195  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
196  {
197  if( token != T_LEFT )
198  Expecting( T_LEFT );
199 
200  token = NextTok();
201 
202  switch( token )
203  {
204  case T_power:
205  symbol->SetPower();
206  NeedRIGHT();
207  break;
208 
209  case T_pin_names:
210  parsePinNames( symbol );
211  break;
212 
213  case T_pin_numbers:
214  token = NextTok();
215 
216  if( token != T_hide )
217  Expecting( "hide" );
218 
219  symbol->SetShowPinNumbers( false );
220  NeedRIGHT();
221  break;
222 
223  case T_in_bom:
224  symbol->SetIncludeInBom( parseBool() );
225  NeedRIGHT();
226  break;
227 
228  case T_on_board:
229  symbol->SetIncludeOnBoard( parseBool() );
230  NeedRIGHT();
231  break;
232 
233  case T_property:
234  parseProperty( symbol );
235  break;
236 
237  case T_extends:
238  {
239  token = NextTok();
240 
241  if( !IsSymbol( token ) )
242  {
243  THROW_PARSE_ERROR( _( "Invalid parent symbol name" ), CurSource(), CurLine(),
244  CurLineNumber(), CurOffset() );
245  }
246 
247  name = FromUTF8();
248  auto it = aSymbolLibMap.find( name );
249 
250  if( it == aSymbolLibMap.end() )
251  {
252  error.Printf( _( "No parent for extended symbol %s" ), name.c_str() );
253  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
254  }
255 
256  symbol->SetParent( it->second );
257  NeedRIGHT();
258  break;
259  }
260 
261  case T_symbol:
262  {
263  token = NextTok();
264 
265  if( !IsSymbol( token ) )
266  {
267  THROW_PARSE_ERROR( _( "Invalid symbol unit name" ), CurSource(), CurLine(),
268  CurLineNumber(), CurOffset() );
269  }
270 
271  name = FromUTF8();
272 
273  if( !name.StartsWith( m_symbolName ) )
274  {
275  error.Printf( _( "Invalid symbol unit name prefix %s" ), name.c_str() );
276  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
277  }
278 
279  name = name.Right( name.Length() - m_symbolName.Length() - 1 );
280 
281  wxStringTokenizer tokenizer( name, "_" );
282 
283  if( tokenizer.CountTokens() != 2 )
284  {
285  error.Printf( _( "Invalid symbol unit name suffix %s" ), name.c_str() );
286  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
287  }
288 
289  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
290  {
291  error.Printf( _( "Invalid symbol unit number %s" ), name.c_str() );
292  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
293  }
294 
295  m_unit = static_cast<int>( tmp );
296 
297  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
298  {
299  error.Printf( _( "Invalid symbol convert number %s" ), name.c_str() );
300  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
301  }
302 
303  m_convert = static_cast<int>( tmp );
304 
305  if( m_convert > 1 )
306  symbol->SetConversion( true, false );
307 
308  if( m_unit > symbol->GetUnitCount() )
309  symbol->SetUnitCount( m_unit, false );
310 
311  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
312  {
313  if( token != T_LEFT )
314  Expecting( T_LEFT );
315 
316  token = NextTok();
317 
318  switch( token )
319  {
320  case T_arc:
321  case T_bezier:
322  case T_circle:
323  case T_pin:
324  case T_polyline:
325  case T_rectangle:
326  case T_text:
327  item = ParseDrawItem();
328 
329  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
330 
331  item->SetParent( symbol.get() );
332  symbol->AddDrawItem( item, false );
333  break;
334 
335  default:
336  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
337  };
338  }
339 
340  m_unit = 1;
341  m_convert = 1;
342  break;
343  }
344 
345  case T_arc:
346  case T_bezier:
347  case T_circle:
348  case T_pin:
349  case T_polyline:
350  case T_rectangle:
351  case T_text:
352  item = ParseDrawItem();
353 
354  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
355 
356  item->SetParent( symbol.get() );
357  symbol->AddDrawItem( item, false );
358  break;
359 
360  default:
361  Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
362  "rectangle, or text" );
363  }
364  }
365 
366  symbol->GetDrawItems().sort();
367  m_symbolName.clear();
368 
369  return symbol.release();
370 }
int m_fieldId
The current field ID.
LIB_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
int m_unit
The current unit being parsed.
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:115
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
wxString m_symbolName
The current symbol name.
int m_convert
The current body style being parsed.
#define _(s)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
LIB_ITEM * ParseDrawItem()
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
int m_requiredVersion
Set to the symbol library file version required.
const char * name
Definition: DXF_plotter.cpp:56
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)

References _, m_convert, m_fieldId, m_fieldIDsRead, m_requiredVersion, m_symbolName, m_unit, MANDATORY_FIELDS, name, parseBool(), ParseDrawItem(), parsePinNames(), parseProperty(), EDA_ITEM::SetParent(), and THROW_PARSE_ERROR.

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

◆ parseText()

LIB_TEXT * SCH_SEXPR_PARSER::parseText ( )
private

Definition at line 1499 of file sch_sexpr_parser.cpp.

1500 {
1501  wxCHECK_MSG( CurTok() == T_text, nullptr,
1502  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1503 
1504  T token;
1505  wxString tmp;
1506  std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( nullptr );
1507 
1508  text->SetUnit( m_unit );
1509  text->SetConvert( m_convert );
1510  token = NextTok();
1511 
1512  if( !IsSymbol( token ) )
1513  {
1514  THROW_PARSE_ERROR( _( "Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1515  CurOffset() );
1516  }
1517 
1518  text->SetText( FromUTF8() );
1519 
1520  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1521  {
1522  if( token != T_LEFT )
1523  Expecting( T_LEFT );
1524 
1525  token = NextTok();
1526 
1527  switch( token )
1528  {
1529  case T_at:
1530  text->SetPosition( parseXY() );
1531  text->SetTextAngle( parseDouble( "text angle" ) );
1532  NeedRIGHT();
1533  break;
1534 
1535  case T_effects:
1536  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
1537  break;
1538 
1539  default:
1540  Expecting( "at or effects" );
1541  }
1542  }
1543 
1544  return text.release();
1545 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
int m_unit
The current unit being parsed.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
int m_convert
The current body style being parsed.
#define _(s)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

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

Referenced by ParseDrawItem().

◆ parseTITLE_BLOCK()

void SCH_SEXPR_PARSER::parseTITLE_BLOCK ( TITLE_BLOCK aTitleBlock)
private

Definition at line 1600 of file sch_sexpr_parser.cpp.

1601 {
1602  wxCHECK_RET( CurTok() == T_title_block,
1603  "Cannot parse " + GetTokenString( CurTok() ) + " as a TITLE_BLOCK." );
1604 
1605  T token;
1606 
1607  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1608  {
1609  if( token != T_LEFT )
1610  Expecting( T_LEFT );
1611 
1612  token = NextTok();
1613 
1614  switch( token )
1615  {
1616  case T_title:
1617  NextTok();
1618  aTitleBlock.SetTitle( FromUTF8() );
1619  break;
1620 
1621  case T_date:
1622  NextTok();
1623  aTitleBlock.SetDate( FromUTF8() );
1624  break;
1625 
1626  case T_rev:
1627  NextTok();
1628  aTitleBlock.SetRevision( FromUTF8() );
1629  break;
1630 
1631  case T_company:
1632  NextTok();
1633  aTitleBlock.SetCompany( FromUTF8() );
1634  break;
1635 
1636  case T_comment:
1637  {
1638  int commentNumber = parseInt( "comment" );
1639 
1640  switch( commentNumber )
1641  {
1642  case 1:
1643  NextTok();
1644  aTitleBlock.SetComment( 0, FromUTF8() );
1645  break;
1646 
1647  case 2:
1648  NextTok();
1649  aTitleBlock.SetComment( 1, FromUTF8() );
1650  break;
1651 
1652  case 3:
1653  NextTok();
1654  aTitleBlock.SetComment( 2, FromUTF8() );
1655  break;
1656 
1657  case 4:
1658  NextTok();
1659  aTitleBlock.SetComment( 3, FromUTF8() );
1660  break;
1661 
1662  case 5:
1663  NextTok();
1664  aTitleBlock.SetComment( 4, FromUTF8() );
1665  break;
1666 
1667  case 6:
1668  NextTok();
1669  aTitleBlock.SetComment( 5, FromUTF8() );
1670  break;
1671 
1672  case 7:
1673  NextTok();
1674  aTitleBlock.SetComment( 6, FromUTF8() );
1675  break;
1676 
1677  case 8:
1678  NextTok();
1679  aTitleBlock.SetComment( 7, FromUTF8() );
1680  break;
1681 
1682  case 9:
1683  NextTok();
1684  aTitleBlock.SetComment( 8, FromUTF8() );
1685  break;
1686 
1687  default:
1688  THROW_PARSE_ERROR( _( "Invalid title block comment number" ), CurSource(),
1689  CurLine(), CurLineNumber(), CurOffset() );
1690  }
1691 
1692  break;
1693  }
1694 
1695  default:
1696  Expecting( "title, date, rev, company, or comment" );
1697  }
1698 
1699  NeedRIGHT();
1700  }
1701 }
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
#define _(s)
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 146 of file sch_sexpr_parser.h.

147  {
148  wxPoint xy;
149 
150  xy.x = parseInternalUnits( "X coordinate" );
151  xy.y = parseInternalUnits( "Y coordinate" );
152 
153  return xy;
154  }

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 81 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 79 of file sch_sexpr_parser.h.

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ m_fieldIDsRead

std::set<int> SCH_SEXPR_PARSER::m_fieldIDsRead
private

Field IDs that have been read so far for the current symbol.

Definition at line 85 of file sch_sexpr_parser.h.

Referenced by parseProperty(), and ParseSymbol().

◆ m_lastProgressLine

unsigned SCH_SEXPR_PARSER::m_lastProgressLine
private

Definition at line 91 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineCount

unsigned SCH_SEXPR_PARSER::m_lineCount
private

Definition at line 92 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineReader

const LINE_READER* SCH_SEXPR_PARSER::m_lineReader
private

Definition at line 90 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_progressReporter

PROGRESS_REPORTER* SCH_SEXPR_PARSER::m_progressReporter
private

Definition at line 89 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_requiredVersion

int SCH_SEXPR_PARSER::m_requiredVersion
private

Set to the symbol library file version required.

Definition at line 78 of file sch_sexpr_parser.h.

Referenced by parseBusAlias(), parseEDA_TEXT(), parseHeader(), ParseLib(), parsePAGE_INFO(), parsePin(), ParseSchematic(), parseSchematicSymbol(), parseSheet(), and ParseSymbol().

◆ m_symbolName

wxString SCH_SEXPR_PARSER::m_symbolName
private

The current symbol name.

Definition at line 82 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 80 of file sch_sexpr_parser.h.

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

◆ m_uuids

std::set<KIID> SCH_SEXPR_PARSER::m_uuids
private

Definition at line 87 of file sch_sexpr_parser.h.

Referenced by parseKIID().


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