Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
scanner.cpp
Go to the documentation of this file.
1
29#include "scanner.h"
30
31#include "diagnostic.h"
32#include "loc_exception.h"
33
34#include <fstream>
35#include <string>
36#include <vector>
37
38#include <cassert> // for assert()
39#include <climits> // for UCHAR_MAX
40#include <cstdlib> // for strtol()
41#include <cstring> // for strcmp()
42
43
45{
46 ScannerContext (const char*, char = '#', char = '\\');
47
48 std::ifstream file; // file stream object
49 std::string filename; // filename
50
51 // comment and escape for current file
54
55 // current line and column for the scanner
56 int line;
57
58 // current line and position within it
59 std::string line_;
60 const char* pos_;
61
62private:
63 // not defined (not copy constructible or assignable)
65 void operator= (ScannerContext&);
66};
67
68
69// helpers
70
71static void normal_path (std::string& s)
72{
73 std::string::iterator it(s.begin ());
74
75 for (; it != s.end (); it++)
76 if (*it == '/' || *it == '\\') {
77#if defined (_WIN32)
78 *it = '\\';
79#else
80 *it = '/';
81#endif
82 }
83}
84
85
86// ScannerContext class definitions
87
89ScannerContext (const char* name, char cc, char ec)
90 : file (name), filename (name),
91 comment_char (cc), escape_char (ec),
92 line (0) // , column (0)
93{
94 // update current position
95 pos_ = line_.c_str ();
96
97 if (!file.is_open ())
98 issue_diag (500, true, 0,
99 "%s could not be opened for reading\n", name);
100
101 issue_diag (I_OPENRD, false, 0, "reading %s\n", name);
102}
103
104
105// Scanner class definitions
106
108Scanner ()
109 : context_ (0), nlines_ (0), ntokens_ (0), escaped_newline_ (false)
110{
111 // no-op
112}
113
114
116~Scanner()
117{
118 // empty the stack and destroy the current state
119 delete context_;
120
121 while (!context_stack_.empty ()) {
122 delete context_stack_.top ();
123 context_stack_.pop ();
124 }
125}
126
127
129escape_char () const
130{
131 return context_ ? context_->escape_char : 0;
132}
133
136{
137 while (next_token ().token != tok_nl);
138}
139
140
142open (std::string name, char cc, char ec)
143{
144 normal_path (name);
145
146 if (context_)
147 context_stack_.push (context_);
148
149 try {
150 context_ = new ScannerContext (name.c_str (), cc, ec);
151 }
152 catch (loc_exception&) {
153 context_ = 0;
154
155 if (!context_stack_.empty ()) {
156 context_ = context_stack_.top ();
157 context_stack_.pop ();
158 }
159
160 throw;
161 }
162
163 nlines_ = 0;
164 ntokens_ = 0;
165}
166
167
169close ()
170{
171 assert (0 != context_);
172
173 issue_diag (I_OPENRD, false, 0,
174 "%s: %u tokens, %u lines\n",
175 context_->filename.c_str (), ntokens_, nlines_);
176
177 delete context_;
178
179 if (context_stack_.empty ())
180 context_ = 0;
181 else {
182 context_ = context_stack_.top ();
183 context_stack_.pop ();
184 }
185}
186
187
188Scanner::token_id Scanner::
189process_token (const char* name)
190{
191 assert (0 != name);
192
193 if (*name == context_->escape_char) {
194 switch (name [1]) {
195 case '0': case '1': case '2': case '3':
196 case '4': case '5': case '6': case '7':
197 case 'd':
198 case 'x':
199 // escaped numeric character value
200 return tok_char_value;
201 default:
202 break;
203 }
204
205 return tok_ndef;
206 }
207
208 // look for a predefined token
209
210 static const struct {
211 const char* name;
212 Scanner::token_id token;
213 } tok_map [] = {
214 // elements must be sorted in ascending order
215 { "CHARMAP", tok_charmap },
216 { "END", tok_end },
217 { "IGNORE", tok_ignore },
218 { "LC_ADDRESS", tok_addr },
219 { "LC_COLLATE", tok_collate },
220 { "LC_CTYPE", tok_ctype },
221 { "LC_IDENTIFICATION", tok_ident },
222 { "LC_MEASUREMENT", tok_measure },
223 { "LC_MESSAGES", tok_messages },
224 { "LC_MONETARY", tok_monetary },
225 { "LC_NAME", tok_name },
226 { "LC_NUMERIC", tok_numeric },
227 { "LC_PAPER", tok_paper },
228 { "LC_TELEPHONE", tok_phone },
229 { "LC_TIME", tok_time },
230 { "UNDEFINED", tok_undefined },
231 { "WIDTH", tok_width },
232 { "abday", tok_abday },
233 { "abmon", tok_abmon },
234 { "alpha", tok_alpha },
235 { "alt_digits", tok_alt_digits },
236 { "am_pm", tok_am_pm },
237 { "backward", tok_backward },
238 { "blank", tok_blank },
239 { "cntrl", tok_cntrl },
240 { "collating-element", tok_coll_elem },
241 { "collating-symbol", tok_coll_sym },
242 { "comment_char", tok_comment_char },
243 { "copy", tok_copy },
244 { "currency_symbol", tok_currency_symbol },
245 { "d_fmt", tok_d_fmt },
246 { "d_t_fmt", tok_d_t_fmt },
247 { "day", tok_day },
248 { "decimal_point", tok_decimal_point },
249 { "digit", tok_digit },
250 { "era", tok_era },
251 { "era_d_fmt", tok_era_d_fmt },
252 { "era_d_t_fmt", tok_era_d_t_fmt },
253 { "era_t_fmt", tok_era_t_fmt },
254 { "escape_char", tok_escape_char },
255 { "falsename", tok_falsename },
256 { "forward", tok_forward },
257 { "frac_digits", tok_frac_digits },
258 { "from", tok_from },
259 { "graph", tok_graph },
260 { "grouping", tok_grouping },
261 { "include", tok_include },
262 { "int_curr_symbol", tok_int_curr_symbol },
263 { "int_frac_digits", tok_int_frac_digits },
264 { "int_n_cs_precedes", tok_int_n_cs_precedes },
265 { "int_n_sep_by_space", tok_int_n_sep_by_space },
266 { "int_n_sign_posn", tok_int_n_sign_posn },
267 { "int_p_cs_precedes", tok_int_p_cs_precedes },
268 { "int_p_sep_by_space", tok_int_p_sep_by_space },
269 { "int_p_sign_posn", tok_int_p_sign_posn },
270 { "lower", tok_lower },
271 { "mon", tok_mon },
272 { "mon_decimal_point", tok_mon_decimal_point },
273 { "mon_grouping", tok_mon_grouping },
274 { "mon_thousands_sep", tok_mon_thousands_sep },
275 { "n_cs_precedes", tok_n_cs_precedes },
276 { "n_sep_by_space", tok_n_sep_by_space },
277 { "n_sign_posn", tok_n_sign_posn },
278 { "negative_sign", tok_negative_sign },
279 { "noexpr", tok_noexpr },
280 { "order_end", tok_order_end },
281 { "order_start", tok_order_start },
282 { "p_cs_precedes", tok_p_cs_precedes },
283 { "p_sep_by_space", tok_p_sep_by_space },
284 { "p_sign_posn", tok_p_sign_posn },
285 { "position", tok_position },
286 { "positive_sign", tok_positive_sign },
287 { "print", tok_print },
288 { "punct", tok_punct },
289 { "reorder-after", tok_reorder },
290 { "reorder-end", tok_reorder_end },
291 { "reorder-section-after", tok_reorder_section },
292 { "reorder-section-end", tok_reorder_section_end },
293 { "script", tok_script },
294 { "space", tok_space },
295 { "t_fmt", tok_t_fmt },
296 { "t_fmt_ampm", tok_t_fmt_ampm },
297 { "thousands_sep", tok_thousands_sep },
298 { "tolower", tok_tolower },
299 { "toupper", tok_toupper },
300 { "translit_end", tok_xlit_end },
301 { "translit_start", tok_xlit_start },
302 { "truename", tok_truename },
303 { "upper", tok_upper },
304 { "xdigit", tok_xdigit },
305 { "yesexpr", tok_yesexpr }
306 };
307
308 int low = 0;
309 int high = sizeof tok_map / sizeof *tok_map - 1;
310
311 // this loop implements a binary search to find 'name' in the
312 // tok_map list and when found returns the token value.
313 while (low <= high) {
314
315 const int cur = (low + high) / 2;
316
317 const int cmp = std::strcmp (name, tok_map [cur].name);
318 if (0 == cmp)
319 return tok_map [cur].token;
320
321 if (cmp < 0)
322 high = cur - 1;
323 else
324 low = cur + 1;
325 }
326
327 return tok_ndef;
328}
329
330
331void Scanner::
332read_line ()
333{
334 context_->line_.clear ();
335
336 std::getline (context_->file, context_->line_);
337
338 context_->line_ += '\n';
339
340 context_->pos_ = context_->line_.c_str ();
341
342 ++context_->line;
343 // context_->column = 0;
344
345 ++nlines_;
346
347 assert (context_->line_.size ());
348}
349
350
352next_token ()
353{
354 assert (0 != context_);
355 assert (context_->file.is_open ());
356
357 // token
358 token_t next_tok;
359
360 next_tok.name = "";
361 next_tok.token = tok_ndef;
362 next_tok.line = 0;
363 next_tok.column = 0;
364 next_tok.file = 0;
365
366 while (true) {
367
368 // store the *current* file name
369 next_tok.file = context_->filename.c_str ();
370
371 // the assert above for eof checks if the caller has lost it;
372 if (context_->file.eof ()) {
373 next_tok.token = tok_end_tokens;
374 return next_tok;
375 }
376
377 // if we exhausted the current line, advance
378 if ( context_->line_.size ()
379 <= std::size_t (context_->pos_ - context_->line_.c_str ())) {
380 read_line ();
381 }
382
383 // line and column for the token start; they are set at each
384 // iteration; the finding of a token breaks and next_tok leaves
385 // this loop having the line/col info
386 next_tok.line = context_->line;
387 next_tok.column = int (context_->pos_ - context_->line_.c_str ());
388
389 // plug in the pointer to current position
390 const char*& next = context_->pos_;
391
392 if (*next != context_->comment_char)
393 escaped_newline_ = false;
394
395 if (*next == '<') {
396 // beginning of a symbolic name or keyword
397 const char* tok_begin = next++;
398
399 for (; '>' != *next; ++next) {
400
401 // if has an escaped close angular, pass
402 if (*next == context_->escape_char) {
403
404 // append symbol name up to but not including the escape
405 next_tok.name.append (tok_begin, next - tok_begin);
406
407 // advance the next pointer to skip the escape
408 tok_begin = ++next;
409 }
410 else if ('\n' == *next) {
411 // past the end of the line
412 issue_diag (E_SYNTAX, true, &next_tok,
413 " unterminated symbolic name\n");
414 break;
415 }
416 }
417
418 next_tok.name.append (tok_begin, ++next - tok_begin);
419
420 // check the name fetched so far
421 if (next_tok.name == "<code_set_name>") {
422 next_tok.token = tok_code_set_name;
423 }
424 else if ( next_tok.name == "<escape_char>"
425 || next_tok.name == "<comment_char>") {
426
427 // eat away spaces
428 while (' ' == *next || '\t' == *next) {
429 ++next;
430 }
431
432 // test for end of line
433 if (*next == '\n')
434 issue_diag (E_SYNTAX, true, &next_tok,
435 "missing value for %s\n",
436 next_tok.name.c_str ());
437
438 // store character
439 if (next_tok.name == "<escape_char>")
440 context_->escape_char = *next;
441 else
442 context_->comment_char = *next;
443
444 // adjust positions;
445 context_->pos_ =
446 context_->line_.c_str () + context_->line_.size ();
447
448 // set token to a newline
449 next_tok.name = "";
450 next_tok.token = tok_nl;
451 }
452 else if (next_tok.name == "<mb_cur_max>") {
453 next_tok.token = tok_mb_cur_max;
454 }
455 else if (next_tok.name == "<mb_cur_min>") {
456 next_tok.token = tok_mb_cur_min;
457 }
458 else {
459 next_tok.token = tok_sym_name;
460 }
461 break;
462 }
463 else if (*next == ' ' || *next == '\t' || *next == ';') {
464 // ignore whitespace and separators
465 while (*next == ' ' || *next == '\t' || *next == ';') {
466 ++next;
467 }
468 }
469 else if (*next == '\n') {
470 ++next;
471 next_tok.token = tok_nl;
472 break;
473 }
474 else if (*next == context_->comment_char) {
475 // start of a comment - check as early as necessary
476 // adjust to end of line
477 context_->pos_ = context_->line_.c_str () + context_->line_.size ();
478
479 if (escaped_newline_)
480 continue;
481
482 next_tok.token = tok_nl;
483 next_tok.name = "\n";
484 break;
485 }
486 else if (*next == '(') {
487 // push open parenthesis
488 next_tok.name.push_back (*next++);
489
490 // start of a grouping
491 while (*next != ')') {
492 // contains a symbolic name
493 if (*next == '<') {
494 // push open angular parenthesis
495 next_tok.name.push_back (*next++);
496
497 while (*next != '\n') {
498 // if has an escaped close angular, pass
499 if (next [0] == context_->escape_char) {
500 next_tok.name.push_back (*next++);
501 next_tok.name.push_back (*next++);
502 continue;
503 }
504
505 // if we have reached the end of the sym name
506 if (*next == '>') {
507 next_tok.name.push_back (*next);
508 break;
509 }
510
511 // still inside the sym name/keyword
512 next_tok.name.push_back (*next++);
513 }
514
515 // check if we have gone past the end of the line
516 if (*next == '\n')
517 issue_diag (E_SYNTAX, true, &next_tok,
518 " unterminated symbolic name");
519
520 ++next;
521 }
522 else {
523 // fetch the character
524 next_tok.name.push_back (*next++);
525 }
526
527 if (*next == '\n')
528 issue_diag (E_SYNTAX, true, &next_tok,
529 " unterminated grouping ");
530 }
531
532 next_tok.name.push_back (*next++);
533 next_tok.token = tok_grouping;
534 break;
535 }
536 else if (*next == '.') {
537 // ellipsis (see ISO/IEC TR 14652)
538 int ellipsis_count = 0;
539 // start of an interval
540 while (*next == '.') {
541 next_tok.name.push_back (*next++);
542 ++ellipsis_count;
543 }
544
545 switch (ellipsis_count) {
546 case 2: {
547 const char* tmp = next;
548 if (*tmp++ == '(' && *tmp++ == '2' && *tmp++ == ')'
549 && *tmp++ == '.' && *tmp++ == '.') {
550 // double increment hexadecimal symbolic ellipsis
551 next_tok.token = tok_dbl_ellipsis;
552 next = tmp;
553 }
554 else {
555 // hexadecimal symbolic ellipsis
556 next_tok.token = tok_hex_ellipsis;
557 }
558 break;
559 }
560
561 case 3:
562 // absolute symbolic ellipsis
563 next_tok.token = tok_abs_ellipsis;
564 break;
565
566 case 4:
567 // decimal symbolic ellipsis
568 next_tok.token = tok_dec_ellipsis;
569 break;
570
571 default:
572 issue_diag (E_SYNTAX, true, &next_tok, "illegal ellipsis\n");
573 }
574 break;
575
576 }
577 else if (*next == '\"') {
578
579 // start of a string
580 next_tok.name.push_back (*next++);
581 const char ec = context_->escape_char;
582
583 while (next[0] != '\n') {
584
585 // escaped newline; continue
586 if (next [0] == ec && next [1] == '\n') {
587 read_line ();
588 continue;
589 }
590
591 // escaped quote
592 if (next[0] == ec) {
593 next_tok.name.push_back (*next++);
594 next_tok.name.push_back (*next++);
595 continue;
596 }
597
598 if (next [0] == '\"') {
599 next_tok.name.push_back (*next);
600 break;
601 }
602
603 // still inside the string
604 next_tok.name.push_back (*next++);
605 }
606
607 // test for closure
608 if (*next == '\n')
609 issue_diag (E_SYNTAX, true, &next_tok, "unterminated string");
610
611 ++next;
612 next_tok.token = tok_string;
613 break;
614
615 }
616 else if (*next == context_->escape_char) {
617 // start of an escape sequence
618 // escaped new line
619 if (next [1] == '\n') {
620 // adjust to end of line
621 context_->pos_ =
622 context_->line_.c_str () + context_->line_.size ();
623
624 escaped_newline_ = true;
625 continue;
626 }
627
628 // or
629 while ( *next != ' ' && *next != '\t'
630 && *next != ';' && *next != '\n') {
631 next_tok.name.push_back (*next++);
632 }
633
634 // retrieve token based on value
635 next_tok.token = process_token (next_tok.name.c_str ());
636 break;
637 }
638 else {
639 // the rest of it
640 for (const char ec = context_->escape_char; ; ) {
641
642 // stop at esc-newline or at first "separator"
643 if ( (next [0] == ec && next [1] == '\n')
644 || next [0] == ' '
645 || next [0] == '\t'
646 || next [0] == '\n'
647 || next [0] == ';') {
648 // continuation of a line, separators
649 break;
650 }
651
652 // fetch characters
653 next_tok.name.push_back (*next++);
654 }
655
656 // assert length of input
657 assert (next_tok.name.size ());
658
659 // it wasn't a locale definition keyword so call process_token
660 // and add the result to the list
661 next_tok.token = process_token (next_tok.name.c_str ());
662
663
664 // an extra bit of processing since we keep comment and escape
665 // characters in the scanner for a faster processing
666 if ( next_tok.token == tok_escape_char
667 || next_tok.token == tok_comment_char) {
668
669 // eat away spaces
670 while (' ' == *next || '\t' == *next) {
671 ++next;
672 }
673
674 // test for end of line
675 if (*next == '\n')
676 issue_diag (E_SYNTAX, true, &next_tok,
677 "unterminated statement");
678
679 // store character
680 if (next_tok.token == tok_escape_char)
681 context_->escape_char = next [0];
682 else
683 context_->comment_char = next [0];
684
685 // adjust positions;
686 context_->pos_ =
687 context_->line_.c_str () + context_->line_.size ();
688
689 // return the token
690 next_tok.name = "";
691 next_tok.token = tok_nl;
692 }
693
694 break;
695 }
696 }
697
698 ++ntokens_;
699
700 return next_tok;
701}
702
703
704unsigned long Scanner::
705convert_escape (const char *esc,
706 const char **pend /* = 0 */,
707 bool multi /* = false */) const
708{
709 assert (0 != esc);
710
711 const char escape = escape_char ();
712
713 if (escape != *esc)
714 issue_diag (E_SYNTAX, true, 0,
715 "expected the escape character ('%c'), got \"%s\"\n",
716 escape, esc);
717
718 unsigned long value = 0;
719
720 for (const char *s = esc; ; ) {
721
722 // escaped characters are octal by default
723 const char *basename = "octal";
724 int base = 8;
725
726 switch (*++s) {
727 case 'd': ++s; base = 10; basename = "decimal"; break;
728 case 'x': ++s; base = 16; basename = "hexadecimal"; break;
729
730 case 'o': ++s;
731 case '0': case '1': case '2': case '3':
732 case '4': case '5': case '6': case '7':
733 break;
734
735 default:
736 issue_diag (E_SYNTAX, true, 0,
737 "one of { 'o', 'd', 'x' } expected following "
738 "the escape character: %s\n", esc);
739 }
740
741 char *end = 0;
742
743 const unsigned long byte = std::strtoul (s, &end, base);
744
745 if (pend)
746 *pend = end;
747
748 // cast away constness below to work around an MSVC 7.0 bug:
749 // causing error C2446: '==' : no conversion from 'char ** '
750 // to 'const char ** ' Conversion loses qualifiers
751 if (!multi && _RWSTD_CONST_CAST (char**, pend) == &end && **pend)
752 issue_diag (E_SYNTAX, true, 0,
753 "%s constant expected: %s\n", basename, esc);
754
755 if (UCHAR_MAX < byte)
756 issue_diag (E_INVAL, true, 0,
757 "%s byte value must be in the range [0, %d]: %s\n",
758 basename, int (UCHAR_MAX), esc);
759
760 if (value >> (sizeof (unsigned long) - 1) * CHAR_BIT)
761 issue_diag (E_INVAL, true, 0, "integer overflow: %s\n", esc);
762
763 value = (value << CHAR_BIT) | byte;
764
765 if (**pend != escape || !multi)
766 break;
767
768 s = *pend;
769 }
770
771 return value;
772}
#define cmp
Definition 17.names.cpp:458
#define line
Definition 17.names.cpp:490
#define tmp
Definition 17.names.cpp:553
#define pend
Definition 17.names.cpp:523
#define s
T value(const T &val)
const int end
const int cur
#define assert(expr)
Definition _cassert.h:40
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
void open(std::string, char='#', char='\\')
Definition scanner.cpp:142
virtual ~Scanner()
Definition scanner.cpp:116
char escape_char() const
Definition scanner.cpp:129
void close()
Definition scanner.cpp:169
void ignore_line()
Definition scanner.cpp:135
unsigned long convert_escape(const char *, const char **=0, bool=false) const
Definition scanner.cpp:705
token_t next_token()
Definition scanner.cpp:352
@ tok_punct
Definition scanner.h:76
@ tok_addr
Definition scanner.h:59
@ tok_cntrl
Definition scanner.h:75
@ tok_mon_thousands_sep
Definition scanner.h:112
@ tok_backward
Definition scanner.h:95
@ tok_int_n_sign_posn
Definition scanner.h:129
@ tok_int_frac_digits
Definition scanner.h:116
@ tok_d_t_fmt
Definition scanner.h:141
@ tok_tolower
Definition scanner.h:79
@ tok_thousands_sep
Definition scanner.h:132
@ tok_end
Definition scanner.h:66
@ tok_decimal_point
Definition scanner.h:131
@ tok_upper
Definition scanner.h:68
@ tok_numeric
Definition scanner.h:56
@ tok_int_p_sep_by_space
Definition scanner.h:126
@ tok_abday
Definition scanner.h:137
@ tok_script
Definition scanner.h:82
@ tok_int_n_sep_by_space
Definition scanner.h:127
@ tok_era_t_fmt
Definition scanner.h:148
@ tok_n_sep_by_space
Definition scanner.h:121
@ tok_n_cs_precedes
Definition scanner.h:120
@ tok_reorder_section_end
Definition scanner.h:91
@ tok_comment_char
Definition scanner.h:164
@ tok_am_pm
Definition scanner.h:144
@ tok_p_sep_by_space
Definition scanner.h:119
@ tok_sym_name
Definition scanner.h:161
@ tok_era
Definition scanner.h:146
@ tok_blank
Definition scanner.h:78
@ tok_escape_char
Definition scanner.h:165
@ tok_lower
Definition scanner.h:69
@ tok_negative_sign
Definition scanner.h:115
@ tok_mon
Definition scanner.h:140
@ tok_reorder_end
Definition scanner.h:89
@ tok_paper
Definition scanner.h:63
@ tok_int_n_cs_precedes
Definition scanner.h:125
@ tok_xdigit
Definition scanner.h:77
@ tok_include
Definition scanner.h:167
@ tok_t_fmt
Definition scanner.h:143
@ tok_string
Definition scanner.h:99
@ tok_era_d_fmt
Definition scanner.h:147
@ tok_ignore
Definition scanner.h:100
@ tok_xlit_start
Definition scanner.h:86
@ tok_messages
Definition scanner.h:54
@ tok_space
Definition scanner.h:71
@ tok_mb_cur_min
Definition scanner.h:49
@ tok_frac_digits
Definition scanner.h:117
@ tok_code_set_name
Definition scanner.h:47
@ tok_coll_sym
Definition scanner.h:84
@ tok_alt_digits
Definition scanner.h:150
@ tok_truename
Definition scanner.h:134
@ tok_p_sign_posn
Definition scanner.h:122
@ tok_forward
Definition scanner.h:94
@ tok_yesexpr
Definition scanner.h:152
@ tok_ndef
Definition scanner.h:169
@ tok_positive_sign
Definition scanner.h:114
@ tok_day
Definition scanner.h:138
@ tok_mon_grouping
Definition scanner.h:113
@ tok_undefined
Definition scanner.h:97
@ tok_grouping
Definition scanner.h:133
@ tok_phone
Definition scanner.h:64
@ tok_collate
Definition scanner.h:52
@ tok_print
Definition scanner.h:74
@ tok_monetary
Definition scanner.h:55
@ tok_digit
Definition scanner.h:70
@ tok_coll_elem
Definition scanner.h:83
@ tok_mb_cur_max
Definition scanner.h:48
@ tok_abmon
Definition scanner.h:139
@ tok_reorder
Definition scanner.h:88
@ tok_order_start
Definition scanner.h:92
@ tok_ctype
Definition scanner.h:53
@ tok_currency_symbol
Definition scanner.h:110
@ tok_copy
Definition scanner.h:166
@ tok_int_curr_symbol
Definition scanner.h:109
@ tok_time
Definition scanner.h:57
@ tok_abs_ellipsis
Definition scanner.h:103
@ tok_nl
Definition scanner.h:168
@ tok_measure
Definition scanner.h:61
@ tok_falsename
Definition scanner.h:135
@ tok_position
Definition scanner.h:96
@ tok_reorder_section
Definition scanner.h:90
@ tok_char_value
Definition scanner.h:162
@ tok_toupper
Definition scanner.h:80
@ tok_from
Definition scanner.h:85
@ tok_alpha
Definition scanner.h:72
@ tok_xlit_end
Definition scanner.h:87
@ tok_n_sign_posn
Definition scanner.h:123
@ tok_era_d_t_fmt
Definition scanner.h:149
@ tok_order_end
Definition scanner.h:93
@ tok_name
Definition scanner.h:62
@ tok_int_p_sign_posn
Definition scanner.h:128
@ tok_ident
Definition scanner.h:60
@ tok_end_tokens
Definition scanner.h:170
@ tok_charmap
Definition scanner.h:51
@ tok_noexpr
Definition scanner.h:153
@ tok_mon_decimal_point
Definition scanner.h:111
@ tok_t_fmt_ampm
Definition scanner.h:145
@ tok_dec_ellipsis
Definition scanner.h:105
@ tok_graph
Definition scanner.h:73
@ tok_width
Definition scanner.h:107
@ tok_p_cs_precedes
Definition scanner.h:118
@ tok_d_fmt
Definition scanner.h:142
@ tok_dbl_ellipsis
Definition scanner.h:106
@ tok_hex_ellipsis
Definition scanner.h:104
@ tok_int_p_cs_precedes
Definition scanner.h:124
const char * name
Definition codecvt1.cpp:72
bool issue_diag(int type, bool, const Scanner::token_t *token, const char *fmt,...)
@ I_OPENRD
Definition diagnostic.h:82
@ E_INVAL
Definition diagnostic.h:52
@ E_SYNTAX
Definition diagnostic.h:49
#define CHAR_BIT
Definition limits.h:40
#define UCHAR_MAX
Definition limits.h:60
#define false
Definition stdbool.h:26
std::string line_
Definition scanner.cpp:59
const char * pos_
Definition scanner.cpp:60
std::string filename
Definition scanner.cpp:49
std::ifstream file
Definition scanner.cpp:48
char comment_char
Definition scanner.cpp:52
ScannerContext(const char *, char='#', char='\\')
Definition scanner.cpp:89
std::string name
Definition scanner.h:178
token_id token
Definition scanner.h:179
const char * file
Definition scanner.h:186