diff options
Diffstat (limited to 'circuitpython/ports/raspberrypi/sdk/tools/pioasm/pio_assembler.h')
-rw-r--r-- | circuitpython/ports/raspberrypi/sdk/tools/pioasm/pio_assembler.h | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/circuitpython/ports/raspberrypi/sdk/tools/pioasm/pio_assembler.h b/circuitpython/ports/raspberrypi/sdk/tools/pioasm/pio_assembler.h new file mode 100644 index 0000000..7183800 --- /dev/null +++ b/circuitpython/ports/raspberrypi/sdk/tools/pioasm/pio_assembler.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PIO_ASSEMBLER_H +#define _PIO_ASSEMBLER_H + +#include <algorithm> +#include "parser.hpp" +#include "output_format.h" + +// Give Flex the prototype of yylex we want ... +# define YY_DECL \ + yy::parser::symbol_type yylex (pio_assembler& pioasm) +// ... and declare it for the parser's sake. +YY_DECL; + + +struct pio_assembler { +public: + using syntax_error = yy::parser::syntax_error; + using location_type = yy::parser::location_type; + + std::shared_ptr<program> dummy_global_program; + std::vector<program> programs; + int error_count = 0; + + pio_assembler(); + + std::shared_ptr<output_format> format; + // The name of the file being parsed. + std::string source; + // name of the output file or "-" for stdout + std::string dest; + std::vector<std::string> options; + + int write_output(); + + bool add_program(const yy::location &l, const std::string &name) { + if (std::find_if(programs.begin(), programs.end(), [&](const program &p) { return p.name == name; }) == + programs.end()) { + programs.emplace_back(this, l, name); + return true; + } else { + return false; + } + } + + program &get_dummy_global_program() { + if (!dummy_global_program) { + dummy_global_program = std::shared_ptr<program>(new program(this, yy::location(&source), "")); + } + return *dummy_global_program; + } + + program &get_current_program(const location_type &l, const std::string &requiring_program, + bool before_any_instructions = false, bool disallow_global = true) { + if (programs.empty()) { + if (disallow_global) { + std::stringstream msg; + msg << requiring_program << " is invalid outside of a program"; + throw syntax_error(l, msg.str()); + } + return get_dummy_global_program(); + } + auto &p = programs[programs.size() - 1]; + if (before_any_instructions && !p.instructions.empty()) { + std::stringstream msg; + msg << requiring_program << " must preceed any program instructions"; + throw syntax_error(l, msg.str()); + } + return p; + } + + // note p may be null for global symbols only + std::shared_ptr<symbol> get_symbol(const std::string &name, const program *p) { + const auto &i = get_dummy_global_program().symbols.find(name); + if (i != get_dummy_global_program().symbols.end()) + return i->second; + + if (p) { + const auto &i2 = p->symbols.find(name); + if (i2 != p->symbols.end()) + return i2->second; + } + return nullptr; + } + + std::vector<compiled_source::symbol> public_symbols(program &program); + int generate(std::shared_ptr<output_format> _format, const std::string &_source, const std::string &_dest, + const std::vector<std::string> &_options = std::vector<std::string>()); + + // Handling the scanner. + void scan_begin(); + void scan_end(); + + // The token's location used by the scanner. + yy::location location; +}; + +#endif
\ No newline at end of file |