OpenASIP  2.0
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"
41 IGNORE_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 
53 using 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 
66 using 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 
81 typedef char char_t;
82 typedef file_iterator <char_t> iterator_t;
83 typedef scanner<iterator_t> scanner_t;
84 typedef rule <scanner_t> rule_t;
85 
86 /**
87  * Temporary structure, where all data is parsed before copying
88  * it to right place.
89  */
90 struct ParserTemp {
91  ParserTemp() : lastNumber(0), lineNumber(1), codeLineCount(0) {}
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  */
195 class PrintString {
196 public:
197  PrintString(const char *aStr);
198  PrintString(std::string &string);
199  void operator() (const char*, const char*) const;
200 
201 private:
202  const char *str_;
203 };
204 
205 /**
206  * Actor for adding new code section.
207  */
209 public:
211  UValue& startAddress);
212 
213  void operator() (const char*, const char*) const;
214 
215 private:
218 };
219 
220 /**
221  * Actor for adding moves to creator.
222  */
224 public:
226  const ParserMove& move);
227 
228  void operator() (const char*, const char*) const;
229 
230 private:
233 };
234 
235 /**
236  * Actor for setting next start address.
237  */
239 public:
241  UValue& startAddress);
242 
243  void operator() (const char*, const char*) const;
244 
245 private:
248 };
249 
250 /**
251  * Actor for adding data lines.
252  */
254 public:
256  const DataLine& dataLine);
257 
258  void operator() (const char*, const char*) const;
259 
260 private:
263 };
264 
265 /**
266  * Actor for adding labels.
267  */
269 public:
270  AddLabelActor(LabelManager& manager,
271  TPEF::ASpaceElement& aSpace,
272  std::string& name, UValue& value);
273 
274  void operator() (const char*, const char*) const;
275 
276 private:
279  std::string& name_;
281 };
282 
283 /**
284  * Actor for adding procedures.
285  */
287 public:
289  LabelManager& manager,
290  std::string& name, UValue& value);
291 
292  void operator() (const char*, const char*) const;
293 
294 private:
296  std::string& name_;
298 };
299 
300 /**
301  * Actor for setting label global.
302  */
304 public:
305  SetGlobalActor(LabelManager &manager);
306 
307  void operator() (const char* start, const char* end) const;
308 
309 private:
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 
316 const bool MY_TRUE = true;
317 const bool MY_FALSE = false;
318 const UValue MY_ZERO = 0;
319 
323 
327 
328 /// Empty parser move with isBegin flag set.
330 
331 struct 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  // ------------------------------------------------------------
409  uLiteral = binNumber|hexNumber|uNumber;
410 
411  // ------------------------------------------------------------
412  // convert backslashed character " and also
413  // accept plain \-character
414  // ------------------------------------------------------------
415  backslashedChars =
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 
428  +(backslashedChars |
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  // ------------------------------------------------------------
439  literal = uLiteral|sNumber|sLiteral;
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 =
501  indexTerm
502  [assign_a(self.parserTemp_.regTerm.indexTerm,
503  self.parserTemp_.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 
525  uLiteral
526  [assign_a(self.parserTemp_.expression.offset,
527  self.parserTemp_.lastNumber)];
528 
529  // ------------------------------------------------------------
530  // name[(+|-)offset] stored to parserTemp_.expression
531  // ------------------------------------------------------------
532  symExpression =
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 
547  symExpression >>
548 
549  !(*my_space >> '=' >> *my_space >> literal)
550  [assign_a(self.parserTemp_.expression.value,
551  self.parserTemp_.lastNumber)]
552  [assign_a(self.parserTemp_.expression.hasValue, MY_TRUE)];
553 
554  // ------------------------------------------------------------
555  // either literal or expression
556  // ------------------------------------------------------------
557  literalOrExpression =
558  literal
559  [assign_a(self.parserTemp_.litOrExpr.value,
560  self.parserTemp_.lastNumber)]
561  [assign_a(self.parserTemp_.litOrExpr.isExpression, MY_FALSE)]
562  [assign_a(self.parserTemp_.litOrExpr.isSigned,
563  self.parserTemp_.isLastSigned)]|
564 
565  expression
566  [assign_a(self.parserTemp_.litOrExpr.expression,
567  self.parserTemp_.expression)]
568  [assign_a(self.parserTemp_.litOrExpr.isExpression, MY_TRUE)];
569 
570  // ------------------------------------------------------------
571  // store immediate term of move to parserTemp_.move
572  // ------------------------------------------------------------
573  immTerm =
574  literalOrExpression
575  [assign_a(self.parserTemp_.move.source.immTerm,
576  self.parserTemp_.litOrExpr)];
577 
578  // ------------------------------------------------------------
579  // store destination
580  // ------------------------------------------------------------
581  destination =
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 =
612  invertFlag >> *my_space >> regTerm
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  // ------------------------------------------------------------
620  initDataField =
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 
628  literalOrExpression
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 >>
647  initDataField[push_back_a(self.parserTemp_.annotation.payload,
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(
669  self.parserTemp_.move.annotationes,
670  self.parserTemp_.annotation)]);
671 
672  // ------------------------------------------------------------
673  // long immediates
674  // ------------------------------------------------------------
675  immediateSpec =
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
686  literalOrExpression
687  [assign_a(self.parserTemp_.move.source.immTerm,
688  self.parserTemp_.litOrExpr)]
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(
695  self.parserTemp_.move.annotationes,
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 =
706  emptyMove
707  [assign_a(self.parserTemp_.move.type, EMPTY_MOVE)] |
708 
709  transport
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,
719  self.parserTemp_.lineNumber)]
720  [AddMoveActor(
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,
727  self.parserTemp_.lineNumber)]
728  [AddMoveActor(
729  self.codeSectionCreator_, self.parserTemp_.move)]);
730 
731  // ------------------------------------------------------------
732  // empty instruction
733  // ------------------------------------------------------------
734  emptyInstruction =
735  str_p(". . .");
736 
737  // ------------------------------------------------------------
738  // empty or populated instruction
739  // ------------------------------------------------------------
740  instruction =
741  emptyInstruction
742  [AddMoveActor(
743  self.codeSectionCreator_, EMPTY_BEGIN_MOVE)] |
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
758  [AddLabelActor(
759  self.labelManager_,
760  *self.resourceManager_.codeAddressSpace(),
761  self.parserTemp_.label,
762  self.parserTemp_.codeLineCount)];
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_,
775  self.parserTemp_.directive,
776  self.parserTemp_.codeLineCount)]) |
777 
778  (str_p("global") >> +my_space >>
779  name[SetGlobalActor(self.labelManager_)]));
780 
781  // ------------------------------------------------------------
782  // one code line terminated by semicolon
783  // ------------------------------------------------------------
784  codeLine =
785  *(codeLabel >> *my_space) >>
786 
787  instruction
788  [increment_a(self.parserTemp_.codeLineCount)] >>
789 
790  // immediate encoding from dedicated instruction slots
791  *(*my_space >> immediateSpec)
792  [assign_a(self.parserTemp_.move.type, LONG_IMM)]
793  [AddMoveActor(
794  self.codeSectionCreator_, self.parserTemp_.move)];
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 =
817  codeHeader
819  self.codeSectionCreator_, self.parserTemp_.lastNumber)] >>
820 
821  +my_space >> codeLines;
822 
823  // ------------------------------------------------------------
824  // all init data fields of data line
825  // ------------------------------------------------------------
826  initData =
827  *(+my_space >>
828  initDataField
829  [push_back_a(self.parserTemp_.dataLine.initData,
830  self.parserTemp_.initDataField)]);
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,
859  self.parserTemp_.lineNumber)]
861  self.dataSectionCreator_, self.parserTemp_.dataLine)]
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)
879  [SetStartAddressActor(self.dataSectionCreator_,
880  self.parserTemp_.lastNumber)] >>
881 
882  *my_space >> ';';
883 
884  // ------------------------------------------------------------
885  // data section definition (header and boby)
886  // ------------------------------------------------------------
887  dataArea =
888  dataHeader >>
889  +my_space >> dataLines;
890 
891  // ------------------------------------------------------------
892  // one data or code section
893  // ------------------------------------------------------------
894  area =
895  dataArea | codeArea;
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>
906  comment, my_space, port, name, program, area, dataArea,
907  dataHeader, dataLines, dataLine, initData,
908  uLiteral, literal, codeArea, codeHeader, codeLines, codeLine,
909  literalOrExpression, label,codeLabel, instruction,
910  emptyInstruction, moves, move, emptyMove, directive,
911  immediateSpec, transport, annotation, initDataField, guard,
912  invertFlag, source, destination, dataLabel, uNumber, sNumber,
913  hexNumber, binNumber, index, fuTerm,
914  indexTerm, sLiteral, backslashedChars, regTerm, offset,
915  symExpression, expression, immTerm, busTerm;
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 
929 public:
930  bool compile(const std::string& asmCode) const;
931 
932  void finalize(bool littleEndian) const;
933 
934  void cleanup();
935 
936  UValue errorLine();
937 
938  bool codeLinesOnly() const { return codeLinesOnly_; }
939 
940 private:
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
AssemblerParser
Definition: AssemblerParser.hh:331
PrintString::str_
const char * str_
Definition: AssemblerParser.hh:202
SetStartAddressActor::creator_
DataSectionCreator & creator_
Definition: AssemblerParser.hh:246
rule_t
rule< scanner_t > rule_t
Definition: AssemblerParser.hh:84
MachineResourceManager.hh
NewCodeSectionActor
Definition: AssemblerParser.hh:208
AddProcedureActor
Definition: AssemblerParser.hh:286
ParserTemp::index
UValue index
Last parsed index.
Definition: AssemblerParser.hh:103
iterator_t
file_iterator< char_t > iterator_t
Definition: AssemblerParser.hh:82
ParserTemp::indexTerm
IndexTerm indexTerm
Last parsed rf[.port].index or fu.operation.index reference.
Definition: AssemblerParser.hh:112
ParserTemp::expression
Expression expression
Last parsed label reference form: name[(+|-)offset][=literal].
Definition: AssemblerParser.hh:119
Exception.hh
AssemblerParser::labelManager_
LabelManager labelManager_
Creates symbol and relocation sections.
Definition: AssemblerParser.hh:952
ParserTemp::initDataField
InitDataField initDataField
Last init data field.
Definition: AssemblerParser.hh:134
AssemblyParserDiagnostic.hh
ParserTemp::lastNumber
UValue lastNumber
Last parsed numeric value.
Definition: AssemblerParser.hh:97
TPEF::Binary
Definition: Binary.hh:49
AddDataLineActor::creator_
DataSectionCreator & creator_
Definition: AssemblerParser.hh:261
ParserTemp::dataLine
DataLine dataLine
Last data line.
Definition: AssemblerParser.hh:137
ParserTemp::litOrExpr
LiteralOrExpression litOrExpr
Last parsed literal or expression.
Definition: AssemblerParser.hh:122
AddLabelActor::manager_
LabelManager & manager_
Definition: AssemblerParser.hh:277
ParserTemp::busTerm
BusTerm busTerm
Last parsed bus reference.
Definition: AssemblerParser.hh:106
BUS_TERM
const RegisterTerm::TermType BUS_TERM
Definition: AssemblerParser.hh:324
CodeSectionCreator
Definition: CodeSectionCreator.hh:58
ParserStructs.hh
Expression
Definition: ParserStructs.hh:198
AddProcedureActor::value_
UValue & value_
Definition: AssemblerParser.hh:297
AddMoveActor::move_
const ParserMove & move_
Definition: AssemblerParser.hh:232
ParserTemp
Definition: AssemblerParser.hh:90
FUNCTION_UNIT_TERM
const RegisterTerm::TermType FUNCTION_UNIT_TERM
Definition: AssemblerParser.hh:325
LONG_IMM
const ParserMove::MoveType LONG_IMM
Definition: AssemblerParser.hh:322
SetStartAddressActor
Definition: AssemblerParser.hh:238
CodeSectionCreator.hh
AddProcedureActor::manager_
LabelManager & manager_
Definition: AssemblerParser.hh:295
ParserTemp::move
ParserMove move
Last parsed source, destination and guard.
Definition: AssemblerParser.hh:125
AddMoveActor
Definition: AssemblerParser.hh:223
ParserTemp::annotation
Annotation annotation
Last annotation.
Definition: AssemblerParser.hh:146
AssemblyParserDiagnostic
Definition: AssemblyParserDiagnostic.hh:68
LabelManager
Definition: LabelManager.hh:64
RegisterTerm::INDEX
@ INDEX
Index term.
Definition: ParserStructs.hh:145
ParserTemp::fuTerm
FUTerm fuTerm
Last parsed unit.port[.operation] reference.
Definition: AssemblerParser.hh:109
ParserTemp::ParserTemp
ParserTemp()
Definition: AssemblerParser.hh:91
NewCodeSectionActor::startAddress_
UValue & startAddress_
Definition: AssemblerParser.hh:217
ParserTemp::isLastSigned
bool isLastSigned
Should lastNumber be interpret as signed or unsigned value.
Definition: AssemblerParser.hh:100
IndexTerm
Definition: ParserStructs.hh:105
SetStartAddressActor::startAddress_
UValue & startAddress_
Definition: AssemblerParser.hh:247
AddLabelActor::name_
std::string & name_
Definition: AssemblerParser.hh:279
AssemblerParser::definition::start
rule< ScannerT > const & start() const
Definition: AssemblerParser.hh:920
AddLabelActor::value_
UValue & value_
Definition: AssemblerParser.hh:280
AssemblerParser::codeLinesOnly
bool codeLinesOnly() const
Definition: AssemblerParser.hh:938
ParserMove::LONG_IMMEDIATE
@ LONG_IMMEDIATE
Encoding of one long immediate slot.
Definition: ParserStructs.hh:396
NewCodeSectionActor::creator_
CodeSectionCreator & creator_
Definition: AssemblerParser.hh:216
AssemblerParser::definition::moves
rule< ScannerT > moves
Definition: AssemblerParser.hh:910
SetGlobalActor::manager_
LabelManager & manager_
Definition: AssemblerParser.hh:310
ParserTemp::codeLineCount
UValue codeLineCount
Line number of currently parsed code line.
Definition: AssemblerParser.hh:143
UValue
unsigned long UValue
Definition: ParserStructs.hh:44
scanner_t
scanner< iterator_t > scanner_t
Definition: AssemblerParser.hh:83
TPEF::ASpaceElement
Definition: ASpaceElement.hh:48
MachineResourceManager
Definition: MachineResourceManager.hh:76
InitDataField
Definition: ParserStructs.hh:339
ParserTemp::lineNumber
UValue lineNumber
Line number of currently parsed line.
Definition: AssemblerParser.hh:140
RegisterTerm::BUS
@ BUS
Bus term.
Definition: ParserStructs.hh:143
AssemblerParser::definition::program
rule< ScannerT > program
Definition: AssemblerParser.hh:906
LiteralOrExpression
Definition: ParserStructs.hh:245
AssemblerParser::definition::index
rule< ScannerT > index
Definition: AssemblerParser.hh:913
ParserTemp::sLiteral
std::string sLiteral
Definition: AssemblerParser.hh:94
ParserMove::EMPTY
@ EMPTY
Empty move slot.
Definition: ParserStructs.hh:395
EMPTY_BEGIN_MOVE
const ParserMove EMPTY_BEGIN_MOVE(ParserMove::EMPTY, true)
Empty parser move with isBegin flag set.
AssemblerParser::definition::transport
rule< ScannerT > transport
Definition: AssemblerParser.hh:911
AssemblerParser::dataSectionCreator_
DataSectionCreator dataSectionCreator_
Creates data sections.
Definition: AssemblerParser.hh:948
char_t
POP_COMPILER_DIAGS typedef char char_t
Definition: AssemblerParser.hh:81
DataSectionCreator.hh
RegisterTerm::FUNCTION_UNIT
@ FUNCTION_UNIT
FU term.
Definition: ParserStructs.hh:144
BusTerm
Definition: ParserStructs.hh:53
ParserMove
Definition: ParserStructs.hh:391
AddDataLineActor::dataLine_
const DataLine & dataLine_
Definition: AssemblerParser.hh:262
DataLine
Definition: ParserStructs.hh:477
INDEX_TERM
const RegisterTerm::TermType INDEX_TERM
Definition: AssemblerParser.hh:326
AddDataLineActor
Definition: AssemblerParser.hh:253
AssemblerParser::resourceManager_
MachineResourceManager resourceManager_
Generates string, resource, null and address space sections.
Definition: AssemblerParser.hh:946
PrintString
Definition: AssemblerParser.hh:195
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
ParserMove::TRANSPORT
@ TRANSPORT
Data transport (move).
Definition: ParserStructs.hh:397
AssemblerParser::parserTemp_
ParserTemp parserTemp_
Temp-structure containing most recent parsed tokens.
Definition: AssemblerParser.hh:955
MY_TRUE
const bool MY_TRUE
Definition: AssemblerParser.hh:316
MY_ZERO
const UValue MY_ZERO
Definition: AssemblerParser.hh:318
AssemblerParser::definition::sLiteral
rule< ScannerT > sLiteral
Definition: AssemblerParser.hh:914
AssemblerParser::definition::symExpression
rule< ScannerT > symExpression
Definition: AssemblerParser.hh:915
LabelManager.hh
ParserMove::MoveType
MoveType
Types of instruction slots.
Definition: ParserStructs.hh:394
AddLabelActor::aSpace_
TPEF::ASpaceElement & aSpace_
Definition: AssemblerParser.hh:278
AssemblerParser::definition::uNumber
rule< ScannerT > uNumber
Definition: AssemblerParser.hh:912
AssemblerParser::definition::literalOrExpression
rule< ScannerT > literalOrExpression
Definition: AssemblerParser.hh:909
POP_COMPILER_DIAGS
#define POP_COMPILER_DIAGS
Definition: CompilerWarnings.hh:68
cleanup
void cleanup()
Definition: EstimatorCmdLineUI.cc:179
DataSectionCreator
Definition: DataSectionCreator.hh:52
AddMoveActor::creator_
CodeSectionCreator & creator_
Definition: AssemblerParser.hh:231
AssemblerParser::definition::definition
definition(AssemblerParser const &self)
Definition: AssemblerParser.hh:364
AssemblerParser::definition::initData
rule< ScannerT > initData
Definition: AssemblerParser.hh:907
AssemblerParser::codeSectionCreator_
CodeSectionCreator codeSectionCreator_
Creates code section.
Definition: AssemblerParser.hh:950
AddProcedureActor::name_
std::string & name_
Definition: AssemblerParser.hh:296
MY_FALSE
const bool MY_FALSE
Definition: AssemblerParser.hh:317
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
RegisterTerm
Definition: ParserStructs.hh:136
AssemblerParser::definition::parent_
const AssemblerParser & parent_
Definition: AssemblerParser.hh:352
TRANSPORT_MOVE
const ParserMove::MoveType TRANSPORT_MOVE
Definition: AssemblerParser.hh:321
Annotation
Definition: ParserStructs.hh:364
AddLabelActor
Definition: AssemblerParser.hh:268
RegisterTerm::TermType
TermType
Definition: ParserStructs.hh:142
AssemblerParser::definition
Definition: AssemblerParser.hh:350
SetGlobalActor
Definition: AssemblerParser.hh:303
AssemblerParser::definition::uLiteral
rule< ScannerT > uLiteral
Definition: AssemblerParser.hh:908
FUTerm
Definition: ParserStructs.hh:76
CompilerWarnings.hh
TTAMachine::Machine
Definition: Machine.hh:73
AssemblerParser::bin_
TPEF::Binary & bin_
TPEF where to program is compiled.
Definition: AssemblerParser.hh:943
EMPTY_MOVE
const ParserMove::MoveType EMPTY_MOVE
Definition: AssemblerParser.hh:320
ParserTemp::regTerm
RegisterTerm regTerm
Last parsed register term (copy of most recent parsed bus, fu or index term).
Definition: AssemblerParser.hh:116
ParserTemp::label
std::string label
Last label name.
Definition: AssemblerParser.hh:128
ParserTemp::directive
std::string directive
Last directive parameter string.
Definition: AssemblerParser.hh:131