OpenASIP 2.2
Loading...
Searching...
No Matches
AssemblerParser.hh
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2017 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file AssemblerParser.hh
26 *
27 * Syntax declarations and callbacks of assembler language.
28 *
29 * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2009
31 * @author Henry Linjamäki 2017 (henry.linjamaki-no.spam-tut.fi)
32 * @note rating: yellow
33 */
34
35#ifndef TCEASM_ASSEMBLER_PARSER_HH
36#define TCEASM_ASSEMBLER_PARSER_HH
37
38#include <boost/version.hpp>
39
40#include "CompilerWarnings.hh"
41IGNORE_COMPILER_WARNING("-Wunused-parameter")
42#if BOOST_VERSION >= 103800
43
44#include <boost/spirit/include/classic.hpp>
45#include <boost/spirit/include/classic_push_back_actor.hpp>
46#include <boost/spirit/include/classic_clear_actor.hpp>
47#include <boost/spirit/include/classic_assign_actor.hpp>
48#include <boost/spirit/include/classic_increment_actor.hpp>
49#include <boost/spirit/include/classic_assign_key_actor.hpp>
50#include <boost/spirit/include/classic_insert_at_actor.hpp>
51#include <boost/spirit/include/classic_file_iterator.hpp>
52
53using namespace boost::spirit::classic;
54
55#else
56
57#include <boost/spirit.hpp>
58#include <boost/spirit/actor/push_back_actor.hpp>
59#include <boost/spirit/actor/clear_actor.hpp>
60#include <boost/spirit/actor/assign_actor.hpp>
61#include <boost/spirit/actor/increment_actor.hpp>
62#include <boost/spirit/actor/assign_key_actor.hpp>
63#include <boost/spirit/actor/insert_at_actor.hpp>
64#include <boost/spirit/iterator/file_iterator.hpp>
65
66using namespace boost::spirit;
67
68#endif
70
71#include "Exception.hh"
72
73#include "ParserStructs.hh"
75#include "DataSectionCreator.hh"
76#include "CodeSectionCreator.hh"
77#include "LabelManager.hh"
78
80
81typedef char char_t;
82typedef file_iterator <char_t> iterator_t;
83typedef scanner<iterator_t> scanner_t;
84typedef rule <scanner_t> rule_t;
85
86/**
87 * Temporary structure, where all data is parsed before copying
88 * it to right place.
89 */
90struct ParserTemp {
92
93 // Last parsed string literal.
94 std::string sLiteral;
95
96 /// Last parsed numeric value.
98
99 /// Should lastNumber be interpret as signed or unsigned value.
101
102 /// Last parsed index.
104
105 /// Last parsed bus reference.
107
108 /// Last parsed unit.port[.operation] reference.
110
111 /// Last parsed rf[.port].index or fu.operation.index reference.
113
114 /// Last parsed register term
115 /// (copy of most recent parsed bus, fu or index term).
117
118 /// Last parsed label reference form: name[(+|-)offset][=literal]
120
121 /// Last parsed literal or expression.
123
124 /// Last parsed source, destination and guard.
126
127 /// Last label name.
128 std::string label;
129
130 /// Last directive parameter string.
131 std::string directive;
132
133 /// Last init data field
135
136 /// Last data line.
138
139 /// Line number of currently parsed line.
141
142 /// Line number of currently parsed code line.
144
145 /// Last annotation
147};
148
149/**
150 * Something about functors from Sprit manual
151 * (those little classes below that can be used as like callback functions
152 * with Spirit).
153 *
154 * With functors, take note that the operator() should be const. This
155 * implies that functors are immutable. One may wish to have some member
156 * variables that are modified when the action gets called. This is not a
157 * good idea. First of all, functors are preferably lightweight. Functors
158 * are passed around a lot and it would incur a lot of overhead if the
159 * functors are heavily laden. Second, functors are passed by value. Thus,
160 * the actual functor object that finally attaches to the parser, will
161 * surely not be the original instance supplied by the client. What this
162 * means is that changes to a functor's state will not affect the original
163 * functor that the client passed in since they are distinct copies. If a
164 * functor needs to update some state variables, which is often the case, it
165 * is better to use references to external data.
166 *
167 * Personal notes:
168 *
169 * I preferred to use predefined functors, which can do some stl
170 * container operations and assignments...
171 *
172 * I came across with few problems with spirit, I tried to do parser that
173 * would have used pointer assignments and dynamic binding. Parser seems
174 * to hard code some addresses, because address pointers and copy
175 * parameters didn't seen to work too well.
176 *
177 * Here is some examples that didn't work.
178 *
179 * [assign_a(pointer, &object)] in this case I tried to set destination for
180 * parsing to be object. I manage do this kind of assignment when I wrote
181 * special actor for that.
182 *
183 * [assign_a(pointer->structField)] This doesn't work either. If you
184 * want to set field through pointer, you have to create actor for that.
185 *
186 * Copying by passing pointers and references and and dynamic
187 * binding is seems to be possible with Spirit, but you have to
188 * write a lot more code. So I always copied parsed values that I used.
189 */
190
191
192/**
193 * Prints given string to std::cerr. Used for syntax error.
194 */
196public:
197 PrintString(const char *aStr);
198 PrintString(std::string &string);
199 void operator() (const char*, const char*) const;
200
201private:
202 const char *str_;
203};
204
205/**
206 * Actor for adding new code section.
207 */
209public:
211 UValue& startAddress);
212
213 void operator() (const char*, const char*) const;
214
215private:
218};
219
220/**
221 * Actor for adding moves to creator.
222 */
224public:
226 const ParserMove& move);
227
228 void operator() (const char*, const char*) const;
229
230private:
233};
234
235/**
236 * Actor for setting next start address.
237 */
239public:
241 UValue& startAddress);
242
243 void operator() (const char*, const char*) const;
244
245private:
248};
249
250/**
251 * Actor for adding data lines.
252 */
254public:
256 const DataLine& dataLine);
257
258 void operator() (const char*, const char*) const;
259
260private:
263};
264
265/**
266 * Actor for adding labels.
267 */
269public:
271 TPEF::ASpaceElement& aSpace,
272 std::string& name, UValue& value);
273
274 void operator() (const char*, const char*) const;
275
276private:
279 std::string& name_;
281};
282
283/**
284 * Actor for adding procedures.
285 */
287public:
289 LabelManager& manager,
290 std::string& name, UValue& value);
291
292 void operator() (const char*, const char*) const;
293
294private:
296 std::string& name_;
298};
299
300/**
301 * Actor for setting label global.
302 */
304public:
306
307 void operator() (const char* start, const char* end) const;
308
309private:
311};
312
313// Spirit parser didn't work with literals like ParserInstruction::EMPTY,
314// true, false, 0 etc. So I defined variables for literal assignments.
315
316const bool MY_TRUE = true;
317const bool MY_FALSE = false;
318const UValue MY_ZERO = 0;
319
323
327
328/// Empty parser move with isBegin flag set.
330
331struct AssemblerParser : public grammar<AssemblerParser>
332{
333
334 /**
335 * Grammar constructor.
336 *
337 * @param aBin TPEF where to program is compiled.
338 * @param aMach Machine which for program is compiled.
339 * @param parent Error message manager of the compiler.
340 * @param codeLinesOnly If true start symbol for the grammar is
341 * 'codeLines'. The option is suitable for inline
342 * assembly parsing. Default is false.
343 */
345 TPEF::Binary &aBin, const TTAMachine::Machine &aMach,
346 AssemblyParserDiagnostic* parserDiagnostic,
347 bool codeLinesOnly = false);
348
349 template <typename ScannerT>
350 struct definition {
351
353
354 // assembly grammar
355 // for spirit syntax, see:
356 // http://www.boost.org/libs/spirit/doc/quickref.html
357
358 // if you define new patterns and it doesn't seem to work, try
359 // adding parenthesis... this works quite weird some times.
360
361 // NOTE! Coding guidelines does not apply for this part... NOTE!
362 // because code is more like BNF description than C
363
364 definition(AssemblerParser const& self) : parent_(self) {
365
366 // ------------------------------------------------------------
367 // omits comments and update current line couter
368 // ------------------------------------------------------------
369 comment = str_p("#") >>
370 (*(anychar_p - '\n') >> ch_p('\n'))
371 [increment_a(self.parserTemp_.lineNumber)]
372 ;
373
374 // ------------------------------------------------------------
375 // comment or any white empty space
376 // ------------------------------------------------------------
377 my_space =
378 comment
379 |
380
381 str_p("\n")
382 [increment_a(self.parserTemp_.lineNumber)]
383 |
384
385 space_p;
386
387 // ------------------------------------------------------------
388 // all literals are stored to parserTemp_.lastNumber field
389 // ------------------------------------------------------------
390 binNumber = str_p("0b") >> bin_p
391 [assign_a(self.parserTemp_.lastNumber)]
392 [assign_a(self.parserTemp_.isLastSigned, MY_FALSE)];
393
394 hexNumber = str_p("0x") >> hex_p
395 [assign_a(self.parserTemp_.lastNumber)]
396 [assign_a(self.parserTemp_.isLastSigned, MY_FALSE)];
397
398 uNumber = uint_p
399 [assign_a(self.parserTemp_.lastNumber)]
400 [assign_a(self.parserTemp_.isLastSigned, MY_FALSE)];
401
402 sNumber = int_p
403 [assign_a(self.parserTemp_.lastNumber)]
404 [assign_a(self.parserTemp_.isLastSigned, MY_TRUE)];
405
406 // ------------------------------------------------------------
407 // unsigned literal
408 // ------------------------------------------------------------
410
411 // ------------------------------------------------------------
412 // convert backslashed character " and also
413 // accept plain \-character
414 // ------------------------------------------------------------
416 str_p("\\\"")
417 ;
418
419 // ------------------------------------------------------------
420 // string literal
421 // ------------------------------------------------------------
422 sLiteral =
423 eps_p
424 [assign_a(self.parserTemp_.sLiteral, "")] >>
425
426 (ch_p('\"') >>
427
429 (anychar_p - ch_p('\"')) ) >>
430
431 ch_p('\"'))
432 [PrintString(std::string(
433 "String literals are not supported yet!\n").c_str())]
434 ;
435
436 // ------------------------------------------------------------
437 // any literal
438 // ------------------------------------------------------------
440
441 // ------------------------------------------------------------
442 // any valid string
443 // NOTE: we are not as liberal as ADF specification,
444 // we don't allow ':'
445 // ------------------------------------------------------------
446 name = (alpha_p | chset_p("_")) >> *(alnum_p | chset_p("_"));
447
448 // ------------------------------------------------------------
449 // index is unsigned number and stored to parserTemp_.index field.
450 // ------------------------------------------------------------
451 index = uNumber[assign_a(self.parserTemp_.index,
452 self.parserTemp_.lastNumber)];
453
454 // ------------------------------------------------------------
455 // {prev} and {next} reference which are not yet supported
456 // ------------------------------------------------------------
457 busTerm = '{' >>
458 (str_p("prev")
459 [assign_a(self.parserTemp_.busTerm.prev, MY_TRUE)]|
460 str_p("next")
461 [assign_a(self.parserTemp_.busTerm.prev, MY_FALSE)]) >> '}';
462
463 // ------------------------------------------------------------
464 // unit.port[.operation] is stored to parserTemp_.fuTerm field
465 // ------------------------------------------------------------
466 fuTerm =
467 eps_p
468 [assign_a(self.parserTemp_.fuTerm.part3Used, MY_FALSE)] >>
469
470 name
471 [assign_a(self.parserTemp_.fuTerm.part1)] >> '.' >>
472
473 name
474 [assign_a(self.parserTemp_.fuTerm.part2)] >>
475
476 !('.' >> name[assign_a(self.parserTemp_.fuTerm.part3)])
477 [assign_a(self.parserTemp_.fuTerm.part3Used, MY_TRUE)];
478
479 // ------------------------------------------------------------
480 // rf[.port].index and fu.operation.index is stored to
481 // parserTemp_.indexTerm field
482 // ------------------------------------------------------------
483 indexTerm =
484 eps_p
485 [assign_a(self.parserTemp_.indexTerm.part2Used, MY_FALSE)] >>
486
487 name
488 [assign_a(self.parserTemp_.indexTerm.part1)] >> '.' >>
489
490 !(name[assign_a(self.parserTemp_.indexTerm.part2)] >> '.')
491 [assign_a(self.parserTemp_.indexTerm.part2Used, MY_TRUE)] >>
492
493 index
494 [assign_a(self.parserTemp_.indexTerm.index,
495 self.parserTemp_.index)];
496
497 // ------------------------------------------------------------
498 // copy last parsed term and its type to regTerm
499 // ------------------------------------------------------------
500 regTerm =
502 [assign_a(self.parserTemp_.regTerm.indexTerm,
504 [assign_a(self.parserTemp_.regTerm.type, INDEX_TERM)]|
505
506 fuTerm
507 [assign_a(self.parserTemp_.regTerm.fuTerm,
508 self.parserTemp_.fuTerm)]
509 [assign_a(self.parserTemp_.regTerm.type, FUNCTION_UNIT_TERM)]|
510
511 busTerm
512 [assign_a(self.parserTemp_.regTerm.busTerm,
513 self.parserTemp_.busTerm)]
514 [assign_a(self.parserTemp_.regTerm.type, BUS_TERM)];
515
516
517 // ------------------------------------------------------------
518 // offset part of expression stored to parserTemp_.expression
519 // ------------------------------------------------------------
520 offset =
521 sign_p[assign_a(self.parserTemp_.expression.isMinus)] >>
522
523 *my_space >>
524
526 [assign_a(self.parserTemp_.expression.offset,
527 self.parserTemp_.lastNumber)];
528
529 // ------------------------------------------------------------
530 // name[(+|-)offset] stored to parserTemp_.expression
531 // ------------------------------------------------------------
533 name
534 [assign_a(self.parserTemp_.expression.label)] >>
535
536 !(*my_space >> offset)
537 [assign_a(self.parserTemp_.expression.hasOffset, MY_TRUE)];
538
539 // ------------------------------------------------------------
540 // name[(+|-)offset][=literal] stored to parserTemp_.expression
541 // ------------------------------------------------------------
542 expression =
543 eps_p
544 [assign_a(self.parserTemp_.expression.hasValue, MY_FALSE)]
545 [assign_a(self.parserTemp_.expression.hasOffset, MY_FALSE)] >>
546
548
549 !(*my_space >> '=' >> *my_space >> literal)
550 [assign_a(self.parserTemp_.expression.value,
552 [assign_a(self.parserTemp_.expression.hasValue, MY_TRUE)];
553
554 // ------------------------------------------------------------
555 // either literal or expression
556 // ------------------------------------------------------------
558 literal
559 [assign_a(self.parserTemp_.litOrExpr.value,
562 [assign_a(self.parserTemp_.litOrExpr.isSigned,
564
566 [assign_a(self.parserTemp_.litOrExpr.expression,
568 [assign_a(self.parserTemp_.litOrExpr.isExpression, MY_TRUE)];
569
570 // ------------------------------------------------------------
571 // store immediate term of move to parserTemp_.move
572 // ------------------------------------------------------------
573 immTerm =
575 [assign_a(self.parserTemp_.move.source.immTerm,
576 self.parserTemp_.litOrExpr)];
577
578 // ------------------------------------------------------------
579 // store destination
580 // ------------------------------------------------------------
582 regTerm
583 [assign_a(self.parserTemp_.move.destination,
584 self.parserTemp_.regTerm)];
585
586 // ------------------------------------------------------------
587 // store source
588 // ------------------------------------------------------------
589 source =
590 regTerm
591 [assign_a(self.parserTemp_.move.source.regTerm,
592 self.parserTemp_.regTerm)]
593 [assign_a(self.parserTemp_.move.source.isRegister, MY_TRUE)]|
594
595 immTerm
596 [assign_a(self.parserTemp_.move.source.isRegister, MY_FALSE)];
597
598 // ------------------------------------------------------------
599 // guards type
600 // ------------------------------------------------------------
601 invertFlag =
602 ch_p('?')[assign_a(self.parserTemp_.move.guard.isInverted,
603 MY_FALSE)]|
604
605 ch_p('!')[assign_a(self.parserTemp_.move.guard.isInverted,
606 MY_TRUE)];
607
608 // ------------------------------------------------------------
609 // port or register guard
610 // ------------------------------------------------------------
611 guard =
613 [assign_a(self.parserTemp_.move.guard.regTerm,
614 self.parserTemp_.regTerm)];
615
616 // ------------------------------------------------------------
617 // [field-size:]init-value one init data field of data area
618 // definition
619 // ------------------------------------------------------------
621 eps_p
622 [assign_a(self.parserTemp_.initDataField.width, MY_ZERO)] >>
623
624 !(uNumber >> *my_space >> ':' >> *my_space)
625 [assign_a(self.parserTemp_.initDataField.width,
626 self.parserTemp_.lastNumber)] >>
627
629 [assign_a(self.parserTemp_.initDataField.litOrExpr,
630 self.parserTemp_.litOrExpr)];
631
632 // ------------------------------------------------------------
633 // annotationes
634 //
635 // Only supported syntax for annotation is
636 // "{hexId value value ...}"
637 // ------------------------------------------------------------
638 annotation =
639 eps_p
640 [clear_a(self.parserTemp_.annotation.payload)] >>
641
642 (ch_p('{') >> *my_space >>
643 hexNumber[assign_a(self.parserTemp_.annotation.id,
644 self.parserTemp_.lastNumber)] >>
645
646 *(+my_space >>
648 self.parserTemp_.initDataField)]) >>
649
650 *my_space >> ch_p('}'));
651
652 // ------------------------------------------------------------
653 // one move that moves data through a bus
654 // ------------------------------------------------------------
655 transport =
656 eps_p
657 [assign_a(self.parserTemp_.move.guard.isGuarded, MY_FALSE)]
658 [clear_a(self.parserTemp_.move.annotationes)] >>
659
660 !(guard >> *my_space)
661 [assign_a(self.parserTemp_.move.guard.isGuarded, MY_TRUE)] >>
662
663 source >>
664 *my_space >> str_p("->") >> *my_space >>
665
666 destination >>
667
668 *(*my_space >> annotation[push_back_a(
670 self.parserTemp_.annotation)]);
671
672 // ------------------------------------------------------------
673 // long immediates
674 // ------------------------------------------------------------
676 // moves destination stores immediate unit and register.
677 eps_p
678 [clear_a(self.parserTemp_.move.annotationes)] >>
679
680 ch_p('[') >> *my_space >>
681 destination >>
682
683 *my_space >> '=' >> *my_space >>
684
685 // moves source is used as a value
687 [assign_a(self.parserTemp_.move.source.immTerm,
689 [assign_a(self.parserTemp_.move.source.isRegister,
690 MY_FALSE)] >>
691
692 *my_space >> ch_p(']') >>
693
694 *(*my_space >> annotation[push_back_a(
696 self.parserTemp_.annotation)]);
697 // ------------------------------------------------------------
698 // empty move
699 // ------------------------------------------------------------
700 emptyMove = str_p("...");
701
702 // ------------------------------------------------------------
703 // one immediate, transport or empty move
704 // ------------------------------------------------------------
705 move =
707 [assign_a(self.parserTemp_.move.type, EMPTY_MOVE)] |
708
710 [assign_a(self.parserTemp_.move.type, TRANSPORT_MOVE)];
711
712 // ------------------------------------------------------------
713 // parses instruction and adds moves to CodeSectionCreator
714 // ------------------------------------------------------------
715 moves =
716 move
717 [assign_a(self.parserTemp_.move.isBegin, MY_TRUE)]
718 [assign_a(self.parserTemp_.move.asmLineNumber,
721 self.codeSectionCreator_, self.parserTemp_.move)] >>
722
723 *(*my_space >> ',' >> *my_space >>
724 move
725 [assign_a(self.parserTemp_.move.isBegin, MY_FALSE)]
726 [assign_a(self.parserTemp_.move.asmLineNumber,
730
731 // ------------------------------------------------------------
732 // empty instruction
733 // ------------------------------------------------------------
735 str_p(". . .");
736
737 // ------------------------------------------------------------
738 // empty or populated instruction
739 // ------------------------------------------------------------
744 moves;
745
746 // ------------------------------------------------------------
747 // label definitions
748 // ------------------------------------------------------------
749 label =
750 (name[assign_a(self.parserTemp_.label)] >> *my_space >> ':') ;
751
752 // ------------------------------------------------------------
753 // code labels can be added straight to label manager,
754 // since we don't have to resolve address of label separately
755 // ------------------------------------------------------------
756 codeLabel =
757 label
759 self.labelManager_,
761 self.parserTemp_.label,
763
764 // ------------------------------------------------------------
765 // directive definitions
766 // ------------------------------------------------------------
767 directive =
768 ch_p(':') >> *my_space >>
769
770 ((str_p("procedure") >> +my_space >>
771 (name[assign_a(self.parserTemp_.directive)])
772
774 self.labelManager_,
776 self.parserTemp_.codeLineCount)]) |
777
778 (str_p("global") >> +my_space >>
780
781 // ------------------------------------------------------------
782 // one code line terminated by semicolon
783 // ------------------------------------------------------------
784 codeLine =
785 *(codeLabel >> *my_space) >>
786
788 [increment_a(self.parserTemp_.codeLineCount)] >>
789
790 // immediate encoding from dedicated instruction slots
792 [assign_a(self.parserTemp_.move.type, LONG_IMM)]
795
796 // ------------------------------------------------------------
797 // body of code section (instructions and directives)
798 // ------------------------------------------------------------
799 codeLines =
800 *((codeLine|directive) >>
801 *my_space >> ';' >> *my_space);
802
803 // ------------------------------------------------------------
804 // code header with start address
805 // ------------------------------------------------------------
806 codeHeader =
807 eps_p
808 [assign_a(self.parserTemp_.lastNumber, MY_ZERO)] >>
809
810 str_p("CODE") >>
811 !(+my_space >> literal) >> *my_space >> ';';
812
813 // ------------------------------------------------------------
814 // code section (header and body)
815 // ------------------------------------------------------------
816 codeArea =
820
822
823 // ------------------------------------------------------------
824 // all init data fields of data line
825 // ------------------------------------------------------------
826 initData =
827 *(+my_space >>
829 [push_back_a(self.parserTemp_.dataLine.initData,
831
832 // ------------------------------------------------------------
833 // data label definitions
834 // ------------------------------------------------------------
835 dataLabel =
836 label
837 [push_back_a(self.parserTemp_.dataLine.labels,
838 self.parserTemp_.label)];
839
840 // ------------------------------------------------------------
841 // one data line with data are definition and label
842 // ------------------------------------------------------------
843 dataLine =
844 *(dataLabel >> *my_space) >>
845
846 str_p("DA") >> +my_space >>
847
848 uNumber[assign_a(self.parserTemp_.dataLine.width,
849 self.parserTemp_.lastNumber)] >>
850
851 initData;
852
853 // ------------------------------------------------------------
854 // body of data section
855 // ------------------------------------------------------------
856 dataLines =
857 *((dataLine
858 [assign_a(self.parserTemp_.dataLine.asmLineNumber,
862 [clear_a(self.parserTemp_.dataLine.initData)]
863 [clear_a(self.parserTemp_.dataLine.labels)] |
864
865 directive) >>
866
867 *my_space >> ';' >> *my_space);
868
869 // ------------------------------------------------------------
870 // data section header with address space name and start address
871 // ------------------------------------------------------------
872 dataHeader =
873 str_p("DATA") >>
874 +my_space >>
875
876 name[assign_a(self.parserTemp_.dataLine.dataSpace)] >>
877
878 !(+my_space >> literal)
880 self.parserTemp_.lastNumber)] >>
881
882 *my_space >> ';';
883
884 // ------------------------------------------------------------
885 // data section definition (header and boby)
886 // ------------------------------------------------------------
887 dataArea =
888 dataHeader >>
890
891 // ------------------------------------------------------------
892 // one data or code section
893 // ------------------------------------------------------------
894 area =
896
897 // ------------------------------------------------------------
898 // whole program (multiple sections)
899 // ------------------------------------------------------------
900 program =
901 (*(*my_space >> area) >> *my_space);
902 }
903
904 // all recoginition patterns
905 rule<ScannerT>
916
917 /**
918 * Spirits grammar interface.
919 */
920 rule<ScannerT> const& start() const {
921 if (parent_.codeLinesOnly()) {
922 return codeLines;
923 } else {
924 return program;
925 }
926 }
927 };
928
929public:
930 bool compile(const std::string& asmCode) const;
931
932 void finalize(bool littleEndian) const;
933
934 void cleanup();
935
937
938 bool codeLinesOnly() const { return codeLinesOnly_; }
939
940private:
941
942 /// TPEF where to program is compiled.
944
945 /// Generates string, resource, null and address space sections.
947 /// Creates data sections.
949 /// Creates code section.
951 /// Creates symbol and relocation sections.
953
954 /// Temp-structure containing most recent parsed tokens.
956
957 /// Controls start symbol of the grammar. False: the default symbol
958 /// (program) for parsing assembly files. True: 'codeLines' symbol
959 /// suitable for inline assembly parsing.
960 bool codeLinesOnly_ = false;
961};
962
963#endif
const ParserMove::MoveType LONG_IMM
const ParserMove::MoveType TRANSPORT_MOVE
const ParserMove::MoveType EMPTY_MOVE
const RegisterTerm::TermType INDEX_TERM
scanner< iterator_t > scanner_t
const RegisterTerm::TermType FUNCTION_UNIT_TERM
const ParserMove EMPTY_BEGIN_MOVE(ParserMove::EMPTY, true)
Empty parser move with isBegin flag set.
POP_COMPILER_DIAGS typedef char char_t
const UValue MY_ZERO
rule< scanner_t > rule_t
const bool MY_TRUE
const RegisterTerm::TermType BUS_TERM
const bool MY_FALSE
file_iterator< char_t > iterator_t
#define IGNORE_COMPILER_WARNING(X)
#define POP_COMPILER_DIAGS
unsigned long UValue
const DataLine & dataLine_
DataSectionCreator & creator_
void operator()(const char *, const char *) const
LabelManager & manager_
void operator()(const char *, const char *) const
TPEF::ASpaceElement & aSpace_
std::string & name_
const ParserMove & move_
CodeSectionCreator & creator_
void operator()(const char *, const char *) const
LabelManager & manager_
void operator()(const char *, const char *) const
std::vector< InitDataField > payload
bool prev
Previous or next bus register.
UValue width
Number of MAUs initialized by this data line.
std::vector< InitDataField > initData
Init data fields of data line. Uninitilized data line, if empty.
std::vector< std::string > labels
Labels of this data line.
std::string dataSpace
Address space whose MAUs are initialized.
UValue asmLineNumber
Line number where in source code this DA line is found.
bool hasOffset
Is offset defined.
bool isMinus
Is offset minus.
UValue value
Resolved value.
bool hasValue
Is resolved value defined in struct.
std::string label
Name of the label.
UValue offset
Value of offset.
std::string part3
Operation name.
std::string part2
Port name.
std::string part1
Unit name.
bool part3Used
Is operation part of the term used.
std::string part1
Unit name.
std::string part2
Port or operation name.
bool part2Used
Is port name used.
UValue index
Register or operand index.
LiteralOrExpression litOrExpr
Initialisation value.
UValue width
Number of MAUs that are initialized by the init field.
bool isExpression
Does object contain expression or literal.
UValue value
If literal, the literal. Otherwise not used.
bool isSigned
Sign of the value.
Expression expression
If expression the expression, Otherwise not used.
TPEF::ASpaceElement * codeAddressSpace()
CodeSectionCreator & creator_
void operator()(const char *, const char *) const
RegisterTerm regTerm
Guard port or register.
bool isInverted
Is guard inverted.
bool isGuarded
Is guard used.
MoveType
Types of instruction slots.
@ TRANSPORT
Data transport (move).
@ EMPTY
Empty move slot.
@ LONG_IMMEDIATE
Encoding of one long immediate slot.
std::vector< Annotation > annotationes
MoveType type
Type of move.
ParserSource source
Source field.
bool isBegin
Tells whether the slot is the first of the instruction.
UValue asmLineNumber
Line number of source code for errors.
ParserGuard guard
Guard field.
RegisterTerm destination
Destination field.
bool isRegister
Is source register or immediate reference.
LiteralOrExpression immTerm
If immediate value, the literal or expression. Otherwise not used.
RegisterTerm regTerm
If register, the register. Otherwise not used.
void operator()(const char *, const char *) const
const char * str_
@ BUS
Bus term.
@ FUNCTION_UNIT
FU term.
@ INDEX
Index term.
FUTerm fuTerm
The fu term, if type field is FUNCTION_UNIT. Otherwise not used.
IndexTerm indexTerm
The index term, if type field is INDEX. Otherwise not used.
TermType type
Type of terminal that is represented by this object.
BusTerm busTerm
The bus term, if type field is BUS. Otherwise not used.
void operator()(const char *start, const char *end) const
LabelManager & manager_
DataSectionCreator & creator_
void operator()(const char *, const char *) const
rule< ScannerT > const & start() const
rule< ScannerT > literalOrExpression
const AssemblerParser & parent_
definition(AssemblerParser const &self)
LabelManager labelManager_
Creates symbol and relocation sections.
void finalize(bool littleEndian) const
ParserTemp parserTemp_
Temp-structure containing most recent parsed tokens.
MachineResourceManager resourceManager_
Generates string, resource, null and address space sections.
bool codeLinesOnly() const
TPEF::Binary & bin_
TPEF where to program is compiled.
bool codeLinesOnly_
Controls start symbol of the grammar. False: the default symbol (program) for parsing assembly files....
DataSectionCreator dataSectionCreator_
Creates data sections.
CodeSectionCreator codeSectionCreator_
Creates code section.
bool compile(const std::string &asmCode) const
RegisterTerm regTerm
Last parsed register term (copy of most recent parsed bus, fu or index term).
bool isLastSigned
Should lastNumber be interpret as signed or unsigned value.
std::string directive
Last directive parameter string.
std::string sLiteral
UValue codeLineCount
Line number of currently parsed code line.
DataLine dataLine
Last data line.
Expression expression
Last parsed label reference form: name[(+|-)offset][=literal].
UValue index
Last parsed index.
ParserMove move
Last parsed source, destination and guard.
InitDataField initDataField
Last init data field.
UValue lineNumber
Line number of currently parsed line.
IndexTerm indexTerm
Last parsed rf[.port].index or fu.operation.index reference.
LiteralOrExpression litOrExpr
Last parsed literal or expression.
BusTerm busTerm
Last parsed bus reference.
std::string label
Last label name.
Annotation annotation
Last annotation.
FUTerm fuTerm
Last parsed unit.port[.operation] reference.
UValue lastNumber
Last parsed numeric value.