KiCad PCB EDA Suite
dsnlexer.cpp
Go to the documentation of this file.
1 
2 /*
3  * This program source code file is part of KiCad, a free EDA CAD application.
4  *
5  * Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2007-2020 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 #include <cstdarg>
28 #include <cstdio>
29 #include <cstdlib> // bsearch()
30 #include <cctype>
31 
32 #include <macros.h>
33 #include <fctsys.h>
34 #include <dsnlexer.h>
35 
36 
37 //#define STANDALONE 1 // enable this for stand alone testing.
38 
39 #define FMT_CLIPBOARD _( "clipboard" )
40 
41 
42 //-----<DSNLEXER>-------------------------------------------------------------
43 
45 {
46  curTok = DSN_NONE;
47  prevTok = DSN_NONE;
48 
49  stringDelimiter = '"';
50 
51  specctraMode = false;
52  space_in_quoted_tokens = false;
53  commentsAreTokens = false;
54 
55  curOffset = 0;
56 
57 #if 1
58  if( keywordCount > 11 )
59  {
60  // resize the hashtable bucket count
61  keyword_hash.reserve( keywordCount );
62  }
63 
64  // fill the specialized "C string" hashtable from keywords[]
65  const KEYWORD* it = keywords;
66  const KEYWORD* end = it + keywordCount;
67 
68  for( ; it < end; ++it )
69  {
70  keyword_hash[it->name] = it->token;
71  }
72 #endif
73 }
74 
75 
76 DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount,
77  FILE* aFile, const wxString& aFilename ) :
78  iOwnReaders( true ),
79  start( NULL ),
80  next( NULL ),
81  limit( NULL ),
82  reader( NULL ),
83  keywords( aKeywordTable ),
84  keywordCount( aKeywordCount )
85 {
86  FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename );
87  PushReader( fileReader );
88  init();
89 }
90 
91 
92 DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount,
93  const std::string& aClipboardTxt, const wxString& aSource ) :
94  iOwnReaders( true ),
95  start( NULL ),
96  next( NULL ),
97  limit( NULL ),
98  reader( NULL ),
99  keywords( aKeywordTable ),
100  keywordCount( aKeywordCount )
101 {
102  STRING_LINE_READER* stringReader = new STRING_LINE_READER( aClipboardTxt, aSource.IsEmpty() ?
103  wxString( FMT_CLIPBOARD ) : aSource );
104  PushReader( stringReader );
105  init();
106 }
107 
108 
109 DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount,
110  LINE_READER* aLineReader ) :
111  iOwnReaders( false ),
112  start( NULL ),
113  next( NULL ),
114  limit( NULL ),
115  reader( NULL ),
116  keywords( aKeywordTable ),
117  keywordCount( aKeywordCount )
118 {
119  if( aLineReader )
120  PushReader( aLineReader );
121  init();
122 }
123 
124 
125 static const KEYWORD empty_keywords[1] = {};
126 
127 DSNLEXER::DSNLEXER( const std::string& aSExpression, const wxString& aSource ) :
128  iOwnReaders( true ),
129  start( NULL ),
130  next( NULL ),
131  limit( NULL ),
132  reader( NULL ),
133  keywords( empty_keywords ),
134  keywordCount( 0 )
135 {
136  STRING_LINE_READER* stringReader = new STRING_LINE_READER( aSExpression, aSource.IsEmpty() ?
137  wxString( FMT_CLIPBOARD ) : aSource );
138  PushReader( stringReader );
139  init();
140 }
141 
142 
144 {
145  if( iOwnReaders )
146  {
147  // delete the LINE_READERs from the stack, since I own them.
148  for( READER_STACK::iterator it = readerStack.begin(); it!=readerStack.end(); ++it )
149  delete *it;
150  }
151 }
152 
153 void DSNLEXER::SetSpecctraMode( bool aMode )
154 {
155  specctraMode = aMode;
156  if( aMode )
157  {
158  // specctra mode defaults, some of which can still be changed in this mode.
159  space_in_quoted_tokens = true;
160  }
161  else
162  {
163  space_in_quoted_tokens = false;
164  stringDelimiter = '"';
165  }
166 }
167 
168 
170 {
171  // Synchronize the pointers handling the data read by the LINE_READER
172  // only if aLexer shares the same LINE_READER, because only in this case
173  // the char buffer is be common
174 
175  if( reader != aLexer.reader )
176  return false;
177 
178  // We can synchronize the pointers which handle the data currently read
179  start = aLexer.start;
180  next = aLexer.next;
181  limit = aLexer.limit;
182 
183  // Sync these parameters is not mandatory, but could help
184  // for instance in debug
185  curText = aLexer.curText;
186  curOffset = aLexer.curOffset;
187 
188  return true;
189 }
190 
191 
192 void DSNLEXER::PushReader( LINE_READER* aLineReader )
193 {
194  readerStack.push_back( aLineReader );
195  reader = aLineReader;
196  start = (const char*) (*reader);
197 
198  // force a new readLine() as first thing.
199  limit = start;
200  next = start;
201 }
202 
203 
205 {
206  LINE_READER* ret = 0;
207 
208  if( readerStack.size() )
209  {
210  ret = reader;
211  readerStack.pop_back();
212 
213  if( readerStack.size() )
214  {
215  reader = readerStack.back();
216  start = reader->Line();
217 
218  // force a new readLine() as first thing.
219  limit = start;
220  next = start;
221  }
222  else
223  {
224  reader = 0;
225  start = dummy;
226  limit = dummy;
227  }
228  }
229  return ret;
230 }
231 
232 
233 int DSNLEXER::findToken( const std::string& tok )
234 {
235  KEYWORD_MAP::const_iterator it = keyword_hash.find( tok.c_str() );
236 
237  if( it != keyword_hash.end() )
238  return it->second;
239 
240  return DSN_SYMBOL; // not a keyword, some arbitrary symbol.
241 }
242 
243 
244 const char* DSNLEXER::Syntax( int aTok )
245 {
246  const char* ret;
247 
248  switch( aTok )
249  {
250  case DSN_NONE:
251  ret = "NONE";
252  break;
253  case DSN_STRING_QUOTE:
254  ret = "string_quote"; // a special DSN syntax token, see specctra spec.
255  break;
256  case DSN_QUOTE_DEF:
257  ret = "quoted text delimiter";
258  break;
259  case DSN_DASH:
260  ret = "-";
261  break;
262  case DSN_SYMBOL:
263  ret = "symbol";
264  break;
265  case DSN_NUMBER:
266  ret = "number";
267  break;
268  case DSN_RIGHT:
269  ret = ")";
270  break;
271  case DSN_LEFT:
272  ret = "(";
273  break;
274  case DSN_STRING:
275  ret = "quoted string";
276  break;
277  case DSN_EOF:
278  ret = "end of input";
279  break;
280  default:
281  ret = "???";
282  }
283 
284  return ret;
285 }
286 
287 
288 const char* DSNLEXER::GetTokenText( int aTok )
289 {
290  const char* ret;
291 
292  if( aTok < 0 )
293  {
294  return Syntax( aTok );
295  }
296  else if( (unsigned) aTok < keywordCount )
297  {
298  ret = keywords[aTok].name;
299  }
300  else
301  ret = "token too big";
302 
303  return ret;
304 }
305 
306 
307 wxString DSNLEXER::GetTokenString( int aTok )
308 {
309  wxString ret;
310 
311  ret << wxT("'") << wxString::FromUTF8( GetTokenText(aTok) ) << wxT("'");
312 
313  return ret;
314 }
315 
316 
317 bool DSNLEXER::IsSymbol( int aTok )
318 {
319  // This is static and not inline to reduce code space.
320 
321  // if aTok is >= 0, then it is a coincidental match to a keyword.
322  return aTok==DSN_SYMBOL || aTok==DSN_STRING || aTok>=0;
323 }
324 
325 
326 void DSNLEXER::Expecting( int aTok )
327 {
328  wxString errText = wxString::Format(
329  _( "Expecting %s" ), GetChars( GetTokenString( aTok ) ) );
331 }
332 
333 
334 void DSNLEXER::Expecting( const char* text )
335 {
336  wxString errText = wxString::Format(
337  _( "Expecting '%s'" ), GetChars( wxString::FromUTF8( text ) ) );
339 }
340 
341 
342 void DSNLEXER::Unexpected( int aTok )
343 {
344  wxString errText = wxString::Format(
345  _( "Unexpected %s" ), GetChars( GetTokenString( aTok ) ) );
347 }
348 
349 
350 void DSNLEXER::Duplicate( int aTok )
351 {
352  wxString errText = wxString::Format(
353  _("%s is a duplicate"), GetTokenString( aTok ).GetData() );
355 }
356 
357 
358 void DSNLEXER::Unexpected( const char* text )
359 {
360  wxString errText = wxString::Format(
361  _( "Unexpected '%s'" ), GetChars( wxString::FromUTF8( text ) ) );
363 }
364 
365 
367 {
368  int tok = NextTok();
369  if( tok != DSN_LEFT )
370  Expecting( DSN_LEFT );
371 }
372 
373 
375 {
376  int tok = NextTok();
377  if( tok != DSN_RIGHT )
378  Expecting( DSN_RIGHT );
379 }
380 
381 
383 {
384  int tok = NextTok();
385  if( !IsSymbol( tok ) )
387  return tok;
388 }
389 
390 
392 {
393  int tok = NextTok();
394  if( !IsSymbol( tok ) && tok!=DSN_NUMBER )
395  Expecting( "a symbol or number" );
396  return tok;
397 }
398 
399 
400 int DSNLEXER::NeedNUMBER( const char* aExpectation )
401 {
402  int tok = NextTok();
403  if( tok != DSN_NUMBER )
404  {
405  wxString errText = wxString::Format(
406  _( "need a number for '%s'" ), wxString::FromUTF8( aExpectation ).GetData() );
408  }
409  return tok;
410 }
411 
412 
419 static bool isSpace( char cc )
420 {
421  // cc is signed, so it is often negative.
422  // Treat negative as large positive to exclude rapidly.
423  if( (unsigned char) cc <= ' ' )
424  {
425  switch( (unsigned char) cc )
426  {
427  case ' ':
428  case '\n':
429  case '\r':
430  case '\t':
431  case '\0': // PCAD s-expression files have this.
432  return true;
433  }
434  }
435  return false;
436 }
437 
438 
439 inline bool isDigit( char cc )
440 {
441  return '0' <= cc && cc <= '9';
442 }
443 
444 
446 inline bool isSep( char cc )
447 {
448  return isSpace( cc ) || cc=='(' || cc==')';
449 }
450 
451 
463 static bool isNumber( const char* cp, const char* limit )
464 {
465  // regex for a float: "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?" i.e. any number,
466  // code traversal manually here:
467 
468  bool sawNumber = false;
469 
470  if( cp < limit && ( *cp=='-' || *cp=='+' ) )
471  ++cp;
472 
473  while( cp < limit && isDigit( *cp ) )
474  {
475  ++cp;
476  sawNumber = true;
477  }
478 
479  if( cp < limit && *cp == '.' )
480  {
481  ++cp;
482 
483  while( cp < limit && isDigit( *cp ) )
484  {
485  ++cp;
486  sawNumber = true;
487  }
488  }
489 
490  if( sawNumber )
491  {
492  if( cp < limit && ( *cp=='E' || *cp=='e' ) )
493  {
494  ++cp;
495 
496  sawNumber = false; // exponent mandates at least one digit thereafter.
497 
498  if( cp < limit && ( *cp=='-' || *cp=='+' ) )
499  ++cp;
500 
501  while( cp < limit && isDigit( *cp ) )
502  {
503  ++cp;
504  sawNumber = true;
505  }
506  }
507  }
508 
509  return sawNumber && cp==limit;
510 }
511 
512 
514 {
515  const char* cur = next;
516  const char* head = cur;
517 
518  prevTok = curTok;
519 
520  if( curTok == DSN_EOF )
521  goto exit;
522 
523  if( cur >= limit )
524  {
525 L_read:
526  // blank lines are returned as "\n" and will have a len of 1.
527  // EOF will have a len of 0 and so is detectable.
528  int len = readLine();
529  if( len == 0 )
530  {
531  cur = start; // after readLine(), since start can change, set cur offset to start
532  curTok = DSN_EOF;
533  goto exit;
534  }
535 
536  cur = start; // after readLine() since start can change.
537 
538  // skip leading whitespace
539  while( cur<limit && isSpace( *cur ) )
540  ++cur;
541 
542  // If the first non-blank character is #, this line is a comment.
543  // Comments cannot follow any other token on the same line.
544  if( cur<limit && *cur=='#' )
545  {
546  if( commentsAreTokens )
547  {
548  // Grab the entire current line [excluding end of line char(s)] as the
549  // current token. The '#' character may not be at offset zero.
550 
551  while( limit[-1] == '\n' || limit[-1] == '\r' )
552  --limit;
553 
554  curText.clear();
555  curText.append( start, limit );
556 
557  cur = start; // ensure a good curOffset below
559  head = limit; // do a readLine() on next call in here.
560  goto exit;
561  }
562  else
563  goto L_read;
564  }
565  }
566  else
567  {
568  // skip leading whitespace
569  while( cur<limit && isSpace( *cur ) )
570  ++cur;
571  }
572 
573  if( cur >= limit )
574  goto L_read;
575 
576  if( *cur == '(' )
577  {
578  curText = *cur;
579  curTok = DSN_LEFT;
580  head = cur+1;
581  goto exit;
582  }
583 
584  if( *cur == ')' )
585  {
586  curText = *cur;
587  curTok = DSN_RIGHT;
588  head = cur+1;
589  goto exit;
590  }
591 
592  // Non-specctraMode, understands and deciphers escaped \, \r, \n, and \".
593  // Strips off leading and trailing double quotes
594  if( !specctraMode )
595  {
596  // a quoted string, will return DSN_STRING
597  if( *cur == stringDelimiter )
598  {
599  // copy the token, character by character so we can remove doubled up quotes.
600  curText.clear();
601 
602  ++cur; // skip over the leading delimiter, which is always " in non-specctraMode
603 
604  head = cur;
605 
606  while( head<limit )
607  {
608  // ESCAPE SEQUENCES:
609  if( *head =='\\' )
610  {
611  char tbuf[8];
612  char c;
613  int i;
614 
615  if( ++head >= limit )
616  break; // throw exception at L_unterminated
617 
618  switch( *head++ )
619  {
620  case '"':
621  case '\\': c = head[-1]; break;
622  case 'a': c = '\x07'; break;
623  case 'b': c = '\x08'; break;
624  case 'f': c = '\x0c'; break;
625  case 'n': c = '\n'; break;
626  case 'r': c = '\r'; break;
627  case 't': c = '\x09'; break;
628  case 'v': c = '\x0b'; break;
629 
630  case 'x': // 1 or 2 byte hex escape sequence
631  for( i=0; i<2; ++i )
632  {
633  if( !isxdigit( head[i] ) )
634  break;
635  tbuf[i] = head[i];
636  }
637  tbuf[i] = '\0';
638  if( i > 0 )
639  c = (char) strtoul( tbuf, NULL, 16 );
640  else
641  c = 'x'; // a goofed hex escape sequence, interpret as 'x'
642  head += i;
643  break;
644 
645  default: // 1-3 byte octal escape sequence
646  --head;
647  for( i=0; i<3; ++i )
648  {
649  if( head[i] < '0' || head[i] > '7' )
650  break;
651  tbuf[i] = head[i];
652  }
653  tbuf[i] = '\0';
654  if( i > 0 )
655  c = (char) strtoul( tbuf, NULL, 8 );
656  else
657  c = '\\'; // a goofed octal escape sequence, interpret as '\'
658  head += i;
659  break;
660  }
661 
662  curText += c;
663  }
664 
665  else if( *head == '"' ) // end of the non-specctraMode DSN_STRING
666  {
667  curTok = DSN_STRING;
668  ++head; // omit this trailing double quote
669  goto exit;
670  }
671 
672  else
673  curText += *head++;
674 
675  } // while
676 
677  // L_unterminated:
678  wxString errtxt( _( "Un-terminated delimited string" ) );
680  }
681  }
682 
683  else // is specctraMode, tests in this block should not occur in KiCad mode.
684  {
685  /* get the dash out of a <pin_reference> which is embedded for example
686  like: U2-14 or "U2"-"14"
687  This is detectable by a non-space immediately preceeding the dash.
688  */
689  if( *cur == '-' && cur>start && !isSpace( cur[-1] ) )
690  {
691  curText = '-';
692  curTok = DSN_DASH;
693  head = cur+1;
694  goto exit;
695  }
696 
697  // switching the string_quote character
698  if( prevTok == DSN_STRING_QUOTE )
699  {
700  static const wxString errtxt( _("String delimiter must be a single character of ', \", or $"));
701 
702  char cc = *cur;
703  switch( cc )
704  {
705  case '\'':
706  case '$':
707  case '"':
708  break;
709  default:
711  }
712 
713  curText = cc;
714 
715  head = cur+1;
716 
717  if( head<limit && !isSep( *head ) )
718  {
720  }
721 
723  goto exit;
724  }
725 
726  // specctraMode DSN_STRING
727  if( *cur == stringDelimiter )
728  {
729  ++cur; // skip over the leading delimiter: ",', or $
730 
731  head = cur;
732 
733  while( head<limit && !isStringTerminator( *head ) )
734  ++head;
735 
736  if( head >= limit )
737  {
738  wxString errtxt( _( "Un-terminated delimited string" ) );
740  }
741 
742  curText.clear();
743  curText.append( cur, head );
744 
745  ++head; // skip over the trailing delimiter
746 
747  curTok = DSN_STRING;
748  goto exit;
749  }
750  } // specctraMode
751 
752  // non-quoted token, read it into curText.
753  curText.clear();
754 
755  head = cur;
756  while( head<limit && !isSep( *head ) )
757  curText += *head++;
758 
759  if( isNumber( curText.c_str(), curText.c_str() + curText.size() ) )
760  {
761  curTok = DSN_NUMBER;
762  goto exit;
763  }
764 
765  if( specctraMode && curText == "string_quote" )
766  {
768  goto exit;
769  }
770 
771  curTok = findToken( curText );
772 
773 exit: // single point of exit, no returns elsewhere please.
774 
775  curOffset = cur - start;
776 
777  next = head;
778 
779  return curTok;
780 }
781 
782 
784 {
785  wxArrayString* ret = 0;
786  bool cmt_setting = SetCommentsAreTokens( true );
787  int tok = NextTok();
788 
789  if( tok == DSN_COMMENT )
790  {
791  ret = new wxArrayString();
792 
793  do
794  {
795  ret->Add( FromUTF8() );
796  }
797  while( ( tok = NextTok() ) == DSN_COMMENT );
798  }
799 
800  SetCommentsAreTokens( cmt_setting );
801 
802  return ret;
803 }
int curOffset
offset within current line of the current token
Definition: dsnlexer.h:106
CITER next(CITER it)
Definition: ptree.cpp:126
int NeedNUMBER(const char *aExpectation)
Function NeedNUMBER calls NextTok() and then verifies that the token read is type DSN_NUMBER.
Definition: dsnlexer.cpp:400
bool commentsAreTokens
true if should return comments as tokens
Definition: dsnlexer.h:103
bool SetCommentsAreTokens(bool val)
Function SetCommentsAreTokens changes the handling of comments.
Definition: dsnlexer.h:381
LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived to re...
Definition: richio.h:81
void PushReader(LINE_READER *aLineReader)
Function PushReader manages a stack of LINE_READERs in order to handle nested file inclusion.
Definition: dsnlexer.cpp:192
bool isSep(char cc)
return true if cc is an s-expression separator character
Definition: dsnlexer.cpp:446
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
int NeedSYMBOLorNUMBER()
Function NeedSYMBOLorNUMBER calls NextTok() and then verifies that the token read in satisfies bool I...
Definition: dsnlexer.cpp:391
const char * GetTokenText(int aTok)
Function GetTokenText returns the C string representation of a DSN_T value.
Definition: dsnlexer.cpp:288
const KEYWORD * keywords
table sorted by CMake for bsearch()
Definition: dsnlexer.h:111
virtual ~DSNLEXER()
Definition: dsnlexer.cpp:143
int findToken(const std::string &aToken)
Function findToken takes aToken string and looks up the string in the keywords table.
Definition: dsnlexer.cpp:233
void Unexpected(int aTok)
Function Unexpected throws an IO_ERROR exception with an input file specific error message.
Definition: dsnlexer.cpp:342
const char * name
unique keyword.
Definition: dsnlexer.h:42
wxArrayString * ReadCommentLines()
Function ReadCommentLines checks the next sequence of tokens and reads them into a wxArrayString if t...
Definition: dsnlexer.cpp:783
KEYWORD_MAP keyword_hash
fast, specialized "C string" hashtable
Definition: dsnlexer.h:113
wxString FromUTF8()
Function FromUTF8 returns the current token text as a wxString, assuming that the input byte stream i...
Definition: dsnlexer.h:507
static bool isNumber(const char *cp, const char *limit)
Function isNumber returns true if the next sequence of text is a number: either an integer,...
Definition: dsnlexer.cpp:463
void SetSpecctraMode(bool aMode)
Function SetSpecctraMode changes the behavior of this lexer into or out of "specctra mode".
Definition: dsnlexer.cpp:153
bool space_in_quoted_tokens
blank spaces within quoted strings
Definition: dsnlexer.h:101
This file contains miscellaneous commonly used macros and functions.
const wxString & CurSource()
Function CurFilename returns the current LINE_READER source.
Definition: dsnlexer.h:537
const char * next
Definition: dsnlexer.h:85
int NeedSYMBOL()
Function NeedSYMBOL calls NextTok() and then verifies that the token read in satisfies bool IsSymbol(...
Definition: dsnlexer.cpp:382
LINE_READER * PopReader()
Function PopReader deletes the top most LINE_READER from an internal stack of LINE_READERs and in the...
Definition: dsnlexer.cpp:204
void NeedLEFT()
Function NeedLEFT calls NextTok() and then verifies that the token read in is a DSN_LEFT.
Definition: dsnlexer.cpp:366
FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
const char * limit
Definition: dsnlexer.h:86
#define NULL
bool isDigit(char cc)
Definition: dsnlexer.cpp:439
static bool IsSymbol(int aTok)
Function IsSymbol tests a token to see if it is a symbol.
Definition: dsnlexer.cpp:317
static bool isSpace(char cc)
Function isSpace tests for whitespace.
Definition: dsnlexer.cpp:419
int CurOffset()
Function CurOffset returns the byte offset within the current line, using a 1 based index.
Definition: dsnlexer.h:547
bool iOwnReaders
on readerStack, should I delete them?
Definition: dsnlexer.h:83
void Expecting(int aTok)
Function Expecting throws an IO_ERROR exception with an input file specific error message.
Definition: dsnlexer.cpp:326
READER_STACK readerStack
all the LINE_READERs by pointer.
Definition: dsnlexer.h:91
static const KEYWORD empty_keywords[1]
Definition: dsnlexer.cpp:125
LINE_READER * reader
no ownership. ownership is via readerStack, maybe, if iOwnReaders
Definition: dsnlexer.h:92
bool specctraMode
if true, then: 1) stringDelimiter can be changed 2) Kicad quoting protocol is not in effect 3) space_...
Definition: dsnlexer.h:94
const char * CurLine()
Function CurLine returns the current line of text, from which the CurText() would return its token.
Definition: dsnlexer.h:526
int prevTok
curTok from previous NextTok() call.
Definition: dsnlexer.h:105
int readLine()
Definition: dsnlexer.h:117
const char * start
Definition: dsnlexer.h:84
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
bool SyncLineReaderWith(DSNLEXER &aLexer)
Useable only for DSN lexers which share the same LINE_READER Synchronizes the pointers handling the d...
Definition: dsnlexer.cpp:169
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
void Duplicate(int aTok)
Function Duplicate throws an IO_ERROR exception with a message saying specifically that aTok is a dup...
Definition: dsnlexer.cpp:350
#define _(s)
Definition: 3d_actions.cpp:33
#define FMT_CLIPBOARD
Definition: dsnlexer.cpp:39
std::string curText
the text of the current token
Definition: dsnlexer.h:109
int NextTok()
Function NextTok returns the next token found in the input file or DSN_EOF when reaching the end of f...
Definition: dsnlexer.cpp:513
int CurLineNumber()
Function CurLineNumber returns the current line number within my LINE_READER.
Definition: dsnlexer.h:516
wxString GetTokenString(int aTok)
Function GetTokenString returns a quote wrapped wxString representation of a token value.
Definition: dsnlexer.cpp:307
void NeedRIGHT()
Function NeedRIGHT calls NextTok() and then verifies that the token read in is a DSN_RIGHT.
Definition: dsnlexer.cpp:374
unsigned keywordCount
count of keywords table
Definition: dsnlexer.h:112
char dummy[1]
when there is no reader.
Definition: dsnlexer.h:87
int curTok
the current token obtained on last NextTok()
Definition: dsnlexer.h:108
STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
Struct KEYWORD holds a keyword string and its unique integer token.
Definition: dsnlexer.h:40
bool isStringTerminator(char cc)
Definition: dsnlexer.h:147
void init()
Definition: dsnlexer.cpp:44
DSNLEXER implements a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:79
char stringDelimiter
Definition: dsnlexer.h:100
DSNLEXER(const KEYWORD *aKeywordTable, unsigned aKeywordCount, FILE *aFile, const wxString &aFileName)
Constructor ( FILE*, const wxString& ) intializes a DSN lexer and prepares to read from aFile which i...
Definition: dsnlexer.cpp:76
int token
a zero based index into an array of KEYWORDs
Definition: dsnlexer.h:43
static const char * Syntax(int aTok)
Definition: dsnlexer.cpp:244