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  arc->SetStart( startPoint );
1017  arc->SetEnd( endPoint );
1018 
1019  if( hasMidPoint )
1020  {
1021  arc->SetCenter( (wxPoint) CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() ) );
1022  }
1023  else if( hasAngles )
1024  {
1032  if( !TRANSFORM().MapAngles( &startAngle, &endAngle ) )
1033  {
1034  wxPoint temp = arc->GetStart();
1035  arc->SetStart( arc->GetEnd() );
1036  arc->SetEnd( temp );
1037  }
1038  arc->SetCenter( center );
1039  }
1040  else
1041  {
1042  wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." );
1043  }
1044 
1045  return arc.release();
1046 }
#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...
bool MapAngles(int *aAngle1, int *aAngle2) const
Calculate new angles according to the transform.
Definition: transform.cpp:79
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:454
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

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

Referenced by ParseDrawItem().

◆ parseBezier()

LIB_SHAPE * SCH_SEXPR_PARSER::parseBezier ( )
private

Definition at line 1049 of file sch_sexpr_parser.cpp.

1050 {
1051  wxCHECK_MSG( CurTok() == T_bezier, nullptr,
1052  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
1053 
1054  T token;
1056  FILL_PARAMS fill;
1057 
1058  std::unique_ptr<LIB_SHAPE> bezier = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::BEZIER );
1059 
1060  bezier->SetUnit( m_unit );
1061  bezier->SetConvert( m_convert );
1062 
1063  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1064  {
1065  if( token != T_LEFT )
1066  Expecting( T_LEFT );
1067 
1068  token = NextTok();
1069 
1070  switch( token )
1071  {
1072  case T_pts:
1073  {
1074  int ii = 0;
1075 
1076  for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1077  {
1078  if( token != T_LEFT )
1079  Expecting( T_LEFT );
1080 
1081  token = NextTok();
1082 
1083  if( token != T_xy )
1084  Expecting( "xy" );
1085 
1086  switch( ii )
1087  {
1088  case 0: bezier->SetStart( parseXY() ); break;
1089  case 1: bezier->SetBezierC1( parseXY() ); break;
1090  case 2: bezier->SetBezierC2( parseXY() ); break;
1091  case 3: bezier->SetEnd( parseXY() ); break;
1092  default: Unexpected( "control point" ); break;
1093  }
1094 
1095  NeedRIGHT();
1096  }
1097  }
1098  break;
1099 
1100  case T_stroke:
1101  parseStroke( stroke );
1102  bezier->SetWidth( stroke.GetWidth() );
1103  break;
1104 
1105  case T_fill:
1106  parseFill( fill );
1107  bezier->SetFillMode( fill.m_FillType );
1108  break;
1109 
1110  default:
1111  Expecting( "pts, stroke, or fill" );
1112  }
1113  }
1114 
1115  bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1116 
1117  return bezier.release();
1118 }
#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 2971 of file sch_sexpr_parser.cpp.

2972 {
2973  wxCHECK_RET( CurTok() == T_bus_alias,
2974  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
2975  wxCHECK( aScreen, /* void */ );
2976 
2977  T token;
2978  std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
2979  wxString alias;
2980  wxString member;
2981 
2982  NeedSYMBOL();
2983 
2984  alias = FromUTF8();
2985 
2986  if( m_requiredVersion < 20210621 )
2987  alias = ConvertToNewOverbarNotation( alias );
2988 
2989  busAlias->SetName( alias );
2990 
2991  NeedLEFT();
2992  token = NextTok();
2993 
2994  if( token != T_members )
2995  Expecting( "members" );
2996 
2997  token = NextTok();
2998 
2999  while( token != T_RIGHT )
3000  {
3001  if( !IsSymbol( token ) )
3002  Expecting( "quoted string" );
3003 
3004  member = FromUTF8();
3005 
3006  if( m_requiredVersion < 20210621 )
3007  member = ConvertToNewOverbarNotation( member );
3008 
3009  busAlias->AddMember( member );
3010 
3011  token = NextTok();
3012  }
3013 
3014  NeedRIGHT();
3015 
3016  aScreen->AddBusAlias( busAlias );
3017 }
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 2712 of file sch_sexpr_parser.cpp.

2713 {
2714  wxCHECK_MSG( CurTok() == T_bus_entry, nullptr,
2715  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus entry." ) );
2716 
2717  T token;
2719  std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
2720 
2721  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2722  {
2723  if( token != T_LEFT )
2724  Expecting( T_LEFT );
2725 
2726  token = NextTok();
2727 
2728  switch( token )
2729  {
2730  case T_at:
2731  busEntry->SetPosition( parseXY() );
2732  NeedRIGHT();
2733  break;
2734 
2735  case T_size:
2736  {
2737  wxSize size;
2738 
2739  size.SetWidth( parseInternalUnits( "bus entry height" ) );
2740  size.SetHeight( parseInternalUnits( "bus entry width" ) );
2741  busEntry->SetSize( size );
2742  NeedRIGHT();
2743  break;
2744  }
2745 
2746  case T_stroke:
2747  parseStroke( stroke );
2748  busEntry->SetStroke( stroke );
2749  break;
2750 
2751  case T_uuid:
2752  NeedSYMBOL();
2753  const_cast<KIID&>( busEntry->m_Uuid ) = parseKIID();
2754  NeedRIGHT();
2755  break;
2756 
2757  default:
2758  Expecting( "at, size, uuid or stroke" );
2759  }
2760  }
2761 
2762  return busEntry.release();
2763 }
#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 1121 of file sch_sexpr_parser.cpp.

1122 {
1123  wxCHECK_MSG( CurTok() == T_circle, nullptr,
1124  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
1125 
1126  T token;
1127  wxPoint center( 0, 0 );
1128  int radius = 1; // defaulting to 0 could result in troublesome math....
1130  FILL_PARAMS fill;
1131 
1132  std::unique_ptr<LIB_SHAPE> circle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::CIRCLE );
1133 
1134  circle->SetUnit( m_unit );
1135  circle->SetConvert( m_convert );
1136 
1137  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1138  {
1139  if( token != T_LEFT )
1140  Expecting( T_LEFT );
1141 
1142  token = NextTok();
1143 
1144  switch( token )
1145  {
1146  case T_center:
1147  center = parseXY();
1148  NeedRIGHT();
1149  break;
1150 
1151  case T_radius:
1152  radius = parseInternalUnits( "radius length" );
1153  NeedRIGHT();
1154  break;
1155 
1156  case T_stroke:
1157  parseStroke( stroke );
1158  circle->SetWidth( stroke.GetWidth() );
1159  break;
1160 
1161  case T_fill:
1162  parseFill( fill );
1163  circle->SetFillMode( fill.m_FillType );
1164  break;
1165 
1166  default:
1167  Expecting( "center, radius, stroke, or fill" );
1168  }
1169  }
1170 
1171  circle->SetCenter( center );
1172  circle->SetEnd( wxPoint( center.x + radius, center.y ) );
1173 
1174  return circle.release();
1175 }
#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 2437 of file sch_sexpr_parser.cpp.

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

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

2767 {
2768  T token;
2770  int layer;
2771 
2772  switch( CurTok() )
2773  {
2774  case T_polyline: layer = LAYER_NOTES; break;
2775  case T_wire: layer = LAYER_WIRE; break;
2776  case T_bus: layer = LAYER_BUS; break;
2777  default:
2778  wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as a line." );
2779  }
2780 
2781  std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>( wxPoint(), layer );
2782 
2783  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2784  {
2785  if( token != T_LEFT )
2786  Expecting( T_LEFT );
2787 
2788  token = NextTok();
2789 
2790  switch( token )
2791  {
2792  case T_pts:
2793  NeedLEFT();
2794  token = NextTok();
2795 
2796  if( token != T_xy )
2797  Expecting( "xy" );
2798 
2799  line->SetStartPoint( parseXY() );
2800  NeedRIGHT();
2801  NeedLEFT();
2802  token = NextTok();
2803 
2804  if( token != T_xy )
2805  Expecting( "xy" );
2806 
2807  line->SetEndPoint( parseXY() );
2808  NeedRIGHT();
2809  NeedRIGHT();
2810  break;
2811 
2812  case T_stroke:
2813  parseStroke( stroke );
2814  line->SetStroke( stroke );
2815  break;
2816 
2817  case T_uuid:
2818  NeedSYMBOL();
2819  const_cast<KIID&>( line->m_Uuid ) = parseKIID();
2820  NeedRIGHT();
2821  break;
2822 
2823  default:
2824  Expecting( "at, uuid or stroke" );
2825  }
2826  }
2827 
2828  return line.release();
2829 }
#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 2675 of file sch_sexpr_parser.cpp.

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

References parseKIID(), and parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1547 of file sch_sexpr_parser.cpp.

1548 {
1549  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1550  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1551 
1552  T token;
1553 
1554  NeedSYMBOL();
1555 
1556  wxString pageType = FromUTF8();
1557 
1558  if( !aPageInfo.SetType( pageType ) )
1559  {
1560  THROW_PARSE_ERROR( _( "Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1561  CurOffset() );
1562  }
1563 
1564  if( pageType == PAGE_INFO::Custom )
1565  {
1566  int width = Mm2mils( parseDouble( "width" ) ); // width stored in mm so we convert to mils
1567 
1568  // Perform some controls to avoid crashes if the size is edited by hands
1569  if( width < MIN_PAGE_SIZE_MILS )
1570  width = MIN_PAGE_SIZE_MILS;
1571  else if( width > MAX_PAGE_SIZE_MILS )
1572  width = MAX_PAGE_SIZE_MILS;
1573 
1574  int height = Mm2mils( parseDouble( "height" ) ); // height stored in mm so we convert to mils
1575 
1576  if( height < MIN_PAGE_SIZE_MILS )
1577  height = MIN_PAGE_SIZE_MILS;
1578  else if( height > MAX_PAGE_SIZE_MILS )
1579  height = MAX_PAGE_SIZE_MILS;
1580 
1581  aPageInfo.SetWidthMils( width );
1582  aPageInfo.SetHeightMils( height );
1583  }
1584 
1585  token = NextTok();
1586 
1587  if( token == T_portrait )
1588  {
1589  aPageInfo.SetPortrait( true );
1590  NeedRIGHT();
1591  }
1592  else if( token != T_RIGHT )
1593  {
1594  Expecting( "portrait" );
1595  }
1596 }
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 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...
#define MAX_PAGE_SIZE_MILS
Definition: page_info.h:41
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
Definition: page_info.cpp:186

References _, PAGE_INFO::Custom, m_requiredVersion, MAX_PAGE_SIZE_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 1178 of file sch_sexpr_parser.cpp.

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

1389 {
1390  wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1391  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a poly." ) );
1392 
1393  T token;
1395  FILL_PARAMS fill;
1396  std::unique_ptr<LIB_SHAPE> poly = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::POLY );
1397 
1398  poly->SetUnit( m_unit );
1399  poly->SetConvert( m_convert );
1400 
1401  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1402  {
1403  if( token != T_LEFT )
1404  Expecting( T_LEFT );
1405 
1406  token = NextTok();
1407 
1408  switch( token )
1409  {
1410  case T_pts:
1411  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1412  {
1413  if( token != T_LEFT )
1414  Expecting( T_LEFT );
1415 
1416  token = NextTok();
1417 
1418  if( token != T_xy )
1419  Expecting( "xy" );
1420 
1421  poly->AddPoint( parseXY() );
1422 
1423  NeedRIGHT();
1424  }
1425 
1426  break;
1427 
1428  case T_stroke:
1429  parseStroke( stroke );
1430  poly->SetWidth( stroke.GetWidth() );
1431  break;
1432 
1433  case T_fill:
1434  parseFill( fill );
1435  poly->SetFillMode( fill.m_FillType );
1436  break;
1437 
1438  default:
1439  Expecting( "pts, stroke, or fill" );
1440  }
1441  }
1442 
1443  return poly.release();
1444 }
#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 1447 of file sch_sexpr_parser.cpp.

1448 {
1449  wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1450  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
1451 
1452  T token;
1454  FILL_PARAMS fill;
1455  std::unique_ptr<LIB_SHAPE> rectangle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::RECT );
1456 
1457  rectangle->SetUnit( m_unit );
1458  rectangle->SetConvert( m_convert );
1459 
1460  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1461  {
1462  if( token != T_LEFT )
1463  Expecting( T_LEFT );
1464 
1465  token = NextTok();
1466 
1467  switch( token )
1468  {
1469  case T_start:
1470  rectangle->SetPosition( parseXY() );
1471  NeedRIGHT();
1472  break;
1473 
1474  case T_end:
1475  rectangle->SetEnd( parseXY() );
1476  NeedRIGHT();
1477  break;
1478 
1479  case T_stroke:
1480  parseStroke( stroke );
1481  rectangle->SetWidth( stroke.GetWidth() );
1482  break;
1483 
1484  case T_fill:
1485  parseFill( fill );
1486  rectangle->SetFillMode( fill.m_FillType );
1487  break;
1488 
1489  default:
1490  Expecting( "start, end, stroke, or fill" );
1491  }
1492  }
1493 
1494  return rectangle.release();
1495 }
#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 2012 of file sch_sexpr_parser.cpp.

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

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

1704 {
1705  wxCHECK_MSG( CurTok() == T_property, nullptr,
1706  "Cannot parse " + GetTokenString( CurTok() ) + " as a property token." );
1707 
1708  T token = NextTok();
1709 
1710  if( !IsSymbol( token ) )
1711  {
1712  THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1713  CurOffset() );
1714  }
1715 
1716  wxString name = FromUTF8();
1717 
1718  if( name.IsEmpty() )
1719  {
1720  THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1721  CurOffset() );
1722  }
1723 
1724  token = NextTok();
1725 
1726  if( !IsSymbol( token ) )
1727  {
1728  THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1729  CurOffset() );
1730  }
1731 
1732  // Empty property values are valid.
1733  wxString value = FromUTF8();
1734 
1735  std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1,
1736  aParent, name );
1737 
1738  field->SetText( value );
1739  field->SetVisible( true );
1740 
1741  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1742  {
1743  if( token != T_LEFT )
1744  Expecting( T_LEFT );
1745 
1746  token = NextTok();
1747 
1748  switch( token )
1749  {
1750  case T_id:
1751  field->SetId( parseInt( "field ID" ) );
1752  NeedRIGHT();
1753  break;
1754 
1755  case T_at:
1756  field->SetPosition( parseXY() );
1757  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
1758  NeedRIGHT();
1759  break;
1760 
1761  case T_effects:
1762  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
1763  break;
1764 
1765  default:
1766  Expecting( "at or effects" );
1767  }
1768  }
1769 
1770  return field.release();
1771 }
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 1860 of file sch_sexpr_parser.cpp.

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

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

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

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

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

1499 {
1500  wxCHECK_MSG( CurTok() == T_text, nullptr,
1501  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1502 
1503  T token;
1504  wxString tmp;
1505  std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( nullptr );
1506 
1507  text->SetUnit( m_unit );
1508  text->SetConvert( m_convert );
1509  token = NextTok();
1510 
1511  if( !IsSymbol( token ) )
1512  {
1513  THROW_PARSE_ERROR( _( "Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1514  CurOffset() );
1515  }
1516 
1517  text->SetText( FromUTF8() );
1518 
1519  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1520  {
1521  if( token != T_LEFT )
1522  Expecting( T_LEFT );
1523 
1524  token = NextTok();
1525 
1526  switch( token )
1527  {
1528  case T_at:
1529  text->SetPosition( parseXY() );
1530  text->SetTextAngle( parseDouble( "text angle" ) );
1531  NeedRIGHT();
1532  break;
1533 
1534  case T_effects:
1535  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
1536  break;
1537 
1538  default:
1539  Expecting( "at or effects" );
1540  }
1541  }
1542 
1543  return text.release();
1544 }
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 1599 of file sch_sexpr_parser.cpp.

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