1 /* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef _PIO_ASSEMBLER_H 8 #define _PIO_ASSEMBLER_H 9 10 #include <algorithm> 11 #include "parser.hpp" 12 #include "output_format.h" 13 14 // Give Flex the prototype of yylex we want ... 15 # define YY_DECL \ 16 yy::parser::symbol_type yylex (pio_assembler& pioasm) 17 // ... and declare it for the parser's sake. 18 YY_DECL; 19 20 struct pio_assembler { 21 public: 22 using syntax_error = yy::parser::syntax_error; 23 using location_type = yy::parser::location_type; 24 using position = yy::position; 25 26 std::shared_ptr<program> dummy_global_program; 27 std::vector<program> programs; 28 int error_count = 0; 29 30 pio_assembler(); 31 32 std::shared_ptr<output_format> format; 33 // The name of the file being parsed. 34 std::string source; 35 // name of the output file or "-" for stdout 36 std::string dest; 37 std::vector<std::string> options; 38 int default_pio_version = 0; 39 40 int write_output(); 41 add_programpio_assembler42 bool add_program(const yy::location &l, const std::string &name) { 43 if (std::find_if(programs.begin(), programs.end(), [&](const program &p) { return p.name == name; }) == 44 programs.end()) { 45 programs.emplace_back(this, l, name); 46 programs[programs.size()-1].pio_version = get_default_pio_version(); 47 return true; 48 } else { 49 return false; 50 } 51 } 52 get_dummy_global_programpio_assembler53 program &get_dummy_global_program() { 54 if (!dummy_global_program) { 55 dummy_global_program = std::shared_ptr<program>(new program(this, yy::location(&source), "")); 56 dummy_global_program->pio_version = default_pio_version; 57 } 58 return *dummy_global_program; 59 } 60 61 program &get_current_program(const location_type &l, const std::string &requiring_program, 62 bool before_any_instructions = false, bool disallow_global = true) { 63 if (programs.empty()) { 64 if (disallow_global) { 65 std::stringstream msg; 66 msg << requiring_program << " is invalid outside of a program"; 67 throw syntax_error(l, msg.str()); 68 } 69 return get_dummy_global_program(); 70 } 71 auto &p = programs[programs.size() - 1]; 72 if (before_any_instructions && !p.instructions.empty()) { 73 std::stringstream msg; 74 msg << requiring_program << " must precede any program instructions"; 75 throw syntax_error(l, msg.str()); 76 } 77 return p; 78 } 79 get_default_pio_versionpio_assembler80 int get_default_pio_version() { 81 return get_dummy_global_program().pio_version; 82 } 83 get_current_pio_versionpio_assembler84 int get_current_pio_version() { 85 if (!programs.empty()) { 86 auto &p = programs[programs.size() - 1]; 87 return p.pio_version; 88 } 89 return get_default_pio_version(); 90 } 91 92 // note p may be null for global symbols only get_symbolpio_assembler93 std::shared_ptr<symbol> get_symbol(const std::string &name, const program *p) { 94 const auto &i = get_dummy_global_program().symbols.find(name); 95 if (i != get_dummy_global_program().symbols.end()) 96 return i->second; 97 98 if (p) { 99 const auto &i2 = p->symbols.find(name); 100 if (i2 != p->symbols.end()) 101 return i2->second; 102 } 103 return nullptr; 104 } 105 check_versionpio_assembler106 void check_version(int min_version, const location_type &l, std::string feature) { 107 if (get_current_pio_version() < min_version) { 108 std::stringstream msg; 109 msg << "PIO version " << min_version << " is required for '" << feature << "'"; 110 throw syntax_error(l, msg.str()); 111 } 112 } 113 version_stringpio_assembler114 std::string version_string(int min_version, std::string a, std::string b) { 115 return get_current_pio_version() >= min_version ? a : b; 116 } 117 118 std::vector<compiled_source::symbol> public_symbols(program &program); 119 int generate(std::shared_ptr<output_format> _format, const std::string &_source, const std::string &_dest, 120 const std::vector<std::string> &_options = std::vector<std::string>()); 121 122 // Handling the scanner. 123 void scan_begin(); 124 void scan_end(); 125 126 // The token's location used by the scanner. 127 yy::location location; 128 }; 129 130 #endif