123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*
- * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- %{ /* -*- C++ -*- */
- # include <cerrno>
- # include <climits>
- # include <cstdlib>
- # include <cstring>
- # include <string>
- # include "pio_assembler.h"
- # include "parser.hpp"
- #ifdef _MSC_VER
- #pragma warning(disable : 4996) // fopen
- #endif
- %}
- %option noyywrap nounput noinput batch debug never-interactive case-insensitive noline
- %{
- yy::parser::symbol_type make_INT(const std::string &s, const yy::parser::location_type& loc);
- yy::parser::symbol_type make_HEX(const std::string &s, const yy::parser::location_type& loc);
- yy::parser::symbol_type make_BINARY(const std::string &s, const yy::parser::location_type& loc);
- %}
- blank [ \t]
- whitesp {blank}+
- comment (";"|"//")[^\n]*
- digit [0-9]
- id [a-zA-Z_][a-zA-Z0-9_]*
- binary "0b"[01]+
- int {digit}+
- hex "0x"[0-9a-fA-F]+
- directive \.{id}
- output_fmt [^%\n]+
- %{
- // Code run each time a pattern is matched.
- # define YY_USER_ACTION loc.columns (yyleng);
- %}
- %x code_block
- %x c_comment
- %x lang_opt
- %%
- std::string code_block_contents;
- yy::location code_block_start;
- %{
- // A handy shortcut to the location held by the pio_assembler.
- yy::location& loc = pioasm.location;
- // Code run each time yylex is called.
- loc.step();
- %}
- {blank}+ loc.step();
- \n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); return yy::parser::make_NEWLINE(loc_newline); }
- "%"{blank}*{output_fmt}{blank}*"{" {
- BEGIN(code_block);
- code_block_contents = "";
- code_block_start = loc;
- std::string tmp(yytext);
- tmp = tmp.substr(1, tmp.length() - 2);
- tmp = tmp.erase(0, tmp.find_first_not_of(" \t"));
- tmp = tmp.erase(tmp.find_last_not_of(" \t") + 1);
- return yy::parser::make_CODE_BLOCK_START( tmp, loc);
- }
- <code_block>{
- {blank}+ loc.step();
- \n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); }
- "%}" { BEGIN(INITIAL); auto loc2 = loc; loc2.begin = code_block_start.begin; return yy::parser::make_CODE_BLOCK_CONTENTS(code_block_contents, loc2); }
- .* { code_block_contents += std::string(yytext) + "\n"; }
- }
- <c_comment>{
- {blank}+ loc.step();
- "*/" { BEGIN(INITIAL); }
- "*" { }
- [^\n\*]* { }
- \n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); }
- }
- <lang_opt>{
- \"[^\n]*\" return yy::parser::make_STRING(yytext, loc);
- {blank}+ loc.step();
- "=" return yy::parser::make_EQUAL(loc);
- {int} return make_INT(yytext, loc);
- {hex} return make_HEX(yytext, loc);
- {binary} return make_BINARY(yytext, loc);
- [^ \t\n\"=]+ return yy::parser::make_NON_WS(yytext, loc);
- \n+ { BEGIN(INITIAL); auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); return yy::parser::make_NEWLINE(loc_newline); }
- . { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
- }
- "/*" { BEGIN(c_comment); }
- "," return yy::parser::make_COMMA(loc);
- "::" return yy::parser::make_REVERSE(loc);
- ":" return yy::parser::make_COLON(loc);
- "[" return yy::parser::make_LBRACKET(loc);
- "]" return yy::parser::make_RBRACKET(loc);
- "(" return yy::parser::make_LPAREN(loc);
- ")" return yy::parser::make_RPAREN(loc);
- "+" return yy::parser::make_PLUS(loc);
- "--" return yy::parser::make_POST_DECREMENT(loc);
- "−−" return yy::parser::make_POST_DECREMENT(loc);
- "-" return yy::parser::make_MINUS(loc);
- "*" return yy::parser::make_MULTIPLY(loc);
- "/" return yy::parser::make_DIVIDE(loc);
- "|" return yy::parser::make_OR(loc);
- "&" return yy::parser::make_AND(loc);
- "^" return yy::parser::make_XOR(loc);
- "!=" return yy::parser::make_NOT_EQUAL(loc);
- "!" return yy::parser::make_NOT(loc);
- "~" return yy::parser::make_NOT(loc);
- ".program" return yy::parser::make_PROGRAM(loc);
- ".wrap_target" return yy::parser::make_WRAP_TARGET(loc);
- ".wrap" return yy::parser::make_WRAP(loc);
- ".word" return yy::parser::make_WORD(loc);
- ".define" return yy::parser::make_DEFINE(loc);
- ".side_set" return yy::parser::make_SIDE_SET(loc);
- ".origin" return yy::parser::make_ORIGIN(loc);
- ".lang_opt" { BEGIN(lang_opt); return yy::parser::make_LANG_OPT(loc); }
- {directive} return yy::parser::make_UNKNOWN_DIRECTIVE(yytext, loc);
- "JMP" return yy::parser::make_JMP(loc);
- "WAIT" return yy::parser::make_WAIT(loc);
- "IN" return yy::parser::make_IN(loc);
- "OUT" return yy::parser::make_OUT(loc);
- "PUSH" return yy::parser::make_PUSH(loc);
- "PULL" return yy::parser::make_PULL(loc);
- "MOV" return yy::parser::make_MOV(loc);
- "IRQ" return yy::parser::make_IRQ(loc);
- "SET" return yy::parser::make_SET(loc);
- "NOP" return yy::parser::make_NOP(loc);
- "PUBLIC" return yy::parser::make_PUBLIC(loc);
- "OPTIONAL" return yy::parser::make_OPTIONAL(loc);
- "OPT" return yy::parser::make_OPTIONAL(loc);
- "SIDE" return yy::parser::make_SIDE(loc);
- "SIDESET" return yy::parser::make_SIDE(loc);
- "SIDE_SET" return yy::parser::make_SIDE(loc);
- "PIN" return yy::parser::make_PIN(loc);
- "GPIO" return yy::parser::make_GPIO(loc);
- "OSRE" return yy::parser::make_OSRE(loc);
- "PINS" return yy::parser::make_PINS(loc);
- "NULL" return yy::parser::make_NULL(loc);
- "PINDIRS" return yy::parser::make_PINDIRS(loc);
- "X" return yy::parser::make_X(loc);
- "Y" return yy::parser::make_Y(loc);
- "PC" return yy::parser::make_PC(loc);
- "EXEC" return yy::parser::make_EXEC(loc);
- "ISR" return yy::parser::make_ISR(loc);
- "OSR" return yy::parser::make_OSR(loc);
- "STATUS" return yy::parser::make_STATUS(loc);
- "BLOCK" return yy::parser::make_BLOCK(loc);
- "NOBLOCK" return yy::parser::make_NOBLOCK(loc);
- "IFFULL" return yy::parser::make_IFFULL(loc);
- "IFEMPTY" return yy::parser::make_IFEMPTY(loc);
- "REL" return yy::parser::make_REL(loc);
- "CLEAR" return yy::parser::make_CLEAR(loc);
- "NOWAIT" return yy::parser::make_NOWAIT(loc);
- "ONE" return yy::parser::make_INT(1, loc);
- "ZERO" return yy::parser::make_INT(0, loc);
- <<EOF>> return yy::parser::make_END(loc);
- {int} return make_INT(yytext, loc);
- {hex} return make_HEX(yytext, loc);
- {binary} return make_BINARY(yytext, loc);
- {id} return yy::parser::make_ID(yytext, loc);
- {comment} { }
- . { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
- %%
- yy::parser::symbol_type make_INT(const std::string &s, const yy::parser::location_type& loc)
- {
- errno = 0;
- long n = strtol (s.c_str(), NULL, 10);
- if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
- throw yy::parser::syntax_error (loc, "integer is out of range: " + s);
- return yy::parser::make_INT((int) n, loc);
- }
- yy::parser::symbol_type make_HEX(const std::string &s, const yy::parser::location_type& loc)
- {
- errno = 0;
- long n = strtol (s.c_str() + 2, NULL, 16);
- if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
- throw yy::parser::syntax_error (loc, "hex is out of range: " + s);
- return yy::parser::make_INT((int) n, loc);
- }
- yy::parser::symbol_type make_BINARY(const std::string &s, const yy::parser::location_type& loc)
- {
- errno = 0;
- long n = strtol (s.c_str()+2, NULL, 2);
- if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
- throw yy::parser::syntax_error (loc, "binary is out of range: " + s);
- return yy::parser::make_INT((int) n, loc);
- }
- void pio_assembler::scan_begin ()
- {
- yy_flex_debug = false;
- if (source.empty () || source == "-")
- yyin = stdin;
- else if (!(yyin = fopen (source.c_str (), "r")))
- {
- std::cerr << "cannot open " << source << ": " << strerror(errno) << '\n';
- exit (EXIT_FAILURE);
- }
- }
- void pio_assembler::scan_end ()
- {
- fclose (yyin);
- }
|