blob: 5604b7019f7cd169011a26986f9e76bd3850e1ef [file] [log] [blame]
Austin Schuh208337d2022-01-01 14:29:11 -08001/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7%{ /* -*- C++ -*- */
8# include <cerrno>
9# include <climits>
10# include <cstdlib>
11# include <cstring>
12# include <string>
13# include "pio_assembler.h"
14# include "parser.hpp"
15
16#ifdef _MSC_VER
17#pragma warning(disable : 4996) // fopen
18#endif
19
20%}
21
22%option noyywrap nounput noinput batch debug never-interactive case-insensitive noline
23
24%{
25 yy::parser::symbol_type make_INT(const std::string &s, const yy::parser::location_type& loc);
26 yy::parser::symbol_type make_HEX(const std::string &s, const yy::parser::location_type& loc);
27 yy::parser::symbol_type make_BINARY(const std::string &s, const yy::parser::location_type& loc);
28%}
29
Ravago Jonesd208ae72023-02-13 02:24:07 -080030blank [ \t\r]
Austin Schuh208337d2022-01-01 14:29:11 -080031whitesp {blank}+
32
33comment (";"|"//")[^\n]*
34
35digit [0-9]
36id [a-zA-Z_][a-zA-Z0-9_]*
37
38binary "0b"[01]+
39int {digit}+
40hex "0x"[0-9a-fA-F]+
41directive \.{id}
42
43output_fmt [^%\n]+
44
45%{
46 // Code run each time a pattern is matched.
47 # define YY_USER_ACTION loc.columns (yyleng);
48%}
49
50%x code_block
51%x c_comment
52%x lang_opt
53
54%%
55 std::string code_block_contents;
56 yy::location code_block_start;
57%{
58 // A handy shortcut to the location held by the pio_assembler.
59 yy::location& loc = pioasm.location;
60 // Code run each time yylex is called.
61 loc.step();
62%}
63
64{blank}+ loc.step();
65\n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); return yy::parser::make_NEWLINE(loc_newline); }
66
67"%"{blank}*{output_fmt}{blank}*"{" {
68 BEGIN(code_block);
69 code_block_contents = "";
70 code_block_start = loc;
71 std::string tmp(yytext);
72 tmp = tmp.substr(1, tmp.length() - 2);
73 tmp = tmp.erase(0, tmp.find_first_not_of(" \t"));
74 tmp = tmp.erase(tmp.find_last_not_of(" \t") + 1);
75 return yy::parser::make_CODE_BLOCK_START( tmp, loc);
76 }
77<code_block>{
78 {blank}+ loc.step();
79 \n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); }
Ravago Jonesd208ae72023-02-13 02:24:07 -080080 "%}"{blank}* { BEGIN(INITIAL); auto loc2 = loc; loc2.begin = code_block_start.begin; return yy::parser::make_CODE_BLOCK_CONTENTS(code_block_contents, loc2); }
Austin Schuh208337d2022-01-01 14:29:11 -080081 .* { code_block_contents += std::string(yytext) + "\n"; }
82}
83
84<c_comment>{
85 {blank}+ loc.step();
86 "*/" { BEGIN(INITIAL); }
87 "*" { }
88 [^\n\*]* { }
89 \n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); }
90}
91
92<lang_opt>{
93\"[^\n]*\" return yy::parser::make_STRING(yytext, loc);
94{blank}+ loc.step();
95"=" return yy::parser::make_EQUAL(loc);
96{int} return make_INT(yytext, loc);
97{hex} return make_HEX(yytext, loc);
98{binary} return make_BINARY(yytext, loc);
99[^ \t\n\"=]+ return yy::parser::make_NON_WS(yytext, loc);
100\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); }
101. { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
102}
103
104"/*" { BEGIN(c_comment); }
105"," return yy::parser::make_COMMA(loc);
106"::" return yy::parser::make_REVERSE(loc);
107":" return yy::parser::make_COLON(loc);
108"[" return yy::parser::make_LBRACKET(loc);
109"]" return yy::parser::make_RBRACKET(loc);
110"(" return yy::parser::make_LPAREN(loc);
111")" return yy::parser::make_RPAREN(loc);
112"+" return yy::parser::make_PLUS(loc);
113"--" return yy::parser::make_POST_DECREMENT(loc);
114"−−" return yy::parser::make_POST_DECREMENT(loc);
115"-" return yy::parser::make_MINUS(loc);
116"*" return yy::parser::make_MULTIPLY(loc);
117"/" return yy::parser::make_DIVIDE(loc);
118"|" return yy::parser::make_OR(loc);
119"&" return yy::parser::make_AND(loc);
120"^" return yy::parser::make_XOR(loc);
121"!=" return yy::parser::make_NOT_EQUAL(loc);
122"!" return yy::parser::make_NOT(loc);
123"~" return yy::parser::make_NOT(loc);
124
125".program" return yy::parser::make_PROGRAM(loc);
126".wrap_target" return yy::parser::make_WRAP_TARGET(loc);
127".wrap" return yy::parser::make_WRAP(loc);
128".word" return yy::parser::make_WORD(loc);
129".define" return yy::parser::make_DEFINE(loc);
130".side_set" return yy::parser::make_SIDE_SET(loc);
131".origin" return yy::parser::make_ORIGIN(loc);
132".lang_opt" { BEGIN(lang_opt); return yy::parser::make_LANG_OPT(loc); }
133{directive} return yy::parser::make_UNKNOWN_DIRECTIVE(yytext, loc);
134
135"JMP" return yy::parser::make_JMP(loc);
136"WAIT" return yy::parser::make_WAIT(loc);
137"IN" return yy::parser::make_IN(loc);
138"OUT" return yy::parser::make_OUT(loc);
139"PUSH" return yy::parser::make_PUSH(loc);
140"PULL" return yy::parser::make_PULL(loc);
141"MOV" return yy::parser::make_MOV(loc);
142"IRQ" return yy::parser::make_IRQ(loc);
143"SET" return yy::parser::make_SET(loc);
144"NOP" return yy::parser::make_NOP(loc);
145
146"PUBLIC" return yy::parser::make_PUBLIC(loc);
147
148"OPTIONAL" return yy::parser::make_OPTIONAL(loc);
149"OPT" return yy::parser::make_OPTIONAL(loc);
150"SIDE" return yy::parser::make_SIDE(loc);
151"SIDESET" return yy::parser::make_SIDE(loc);
152"SIDE_SET" return yy::parser::make_SIDE(loc);
153"PIN" return yy::parser::make_PIN(loc);
154"GPIO" return yy::parser::make_GPIO(loc);
155"OSRE" return yy::parser::make_OSRE(loc);
156
157"PINS" return yy::parser::make_PINS(loc);
158"NULL" return yy::parser::make_NULL(loc);
159"PINDIRS" return yy::parser::make_PINDIRS(loc);
160"X" return yy::parser::make_X(loc);
161"Y" return yy::parser::make_Y(loc);
162"PC" return yy::parser::make_PC(loc);
163"EXEC" return yy::parser::make_EXEC(loc);
164"ISR" return yy::parser::make_ISR(loc);
165"OSR" return yy::parser::make_OSR(loc);
166"STATUS" return yy::parser::make_STATUS(loc);
167
168"BLOCK" return yy::parser::make_BLOCK(loc);
169"NOBLOCK" return yy::parser::make_NOBLOCK(loc);
170"IFFULL" return yy::parser::make_IFFULL(loc);
171"IFEMPTY" return yy::parser::make_IFEMPTY(loc);
172"REL" return yy::parser::make_REL(loc);
173
174"CLEAR" return yy::parser::make_CLEAR(loc);
175"NOWAIT" return yy::parser::make_NOWAIT(loc);
176
177"ONE" return yy::parser::make_INT(1, loc);
178"ZERO" return yy::parser::make_INT(0, loc);
179
180<<EOF>> return yy::parser::make_END(loc);
181
182{int} return make_INT(yytext, loc);
183{hex} return make_HEX(yytext, loc);
184{binary} return make_BINARY(yytext, loc);
185
186{id} return yy::parser::make_ID(yytext, loc);
187
188{comment} { }
189
190. { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
191
192%%
193
194yy::parser::symbol_type make_INT(const std::string &s, const yy::parser::location_type& loc)
195{
196 errno = 0;
197 long n = strtol (s.c_str(), NULL, 10);
198 if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
199 throw yy::parser::syntax_error (loc, "integer is out of range: " + s);
200 return yy::parser::make_INT((int) n, loc);
201}
202
203yy::parser::symbol_type make_HEX(const std::string &s, const yy::parser::location_type& loc)
204{
205 errno = 0;
206 long n = strtol (s.c_str() + 2, NULL, 16);
207 if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
208 throw yy::parser::syntax_error (loc, "hex is out of range: " + s);
209 return yy::parser::make_INT((int) n, loc);
210}
211
212yy::parser::symbol_type make_BINARY(const std::string &s, const yy::parser::location_type& loc)
213{
214 errno = 0;
215 long n = strtol (s.c_str()+2, NULL, 2);
216 if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
217 throw yy::parser::syntax_error (loc, "binary is out of range: " + s);
218 return yy::parser::make_INT((int) n, loc);
219}
220
221void pio_assembler::scan_begin ()
222{
223 yy_flex_debug = false;
224 if (source.empty () || source == "-")
225 yyin = stdin;
226 else if (!(yyin = fopen (source.c_str (), "r")))
227 {
228 std::cerr << "cannot open " << source << ": " << strerror(errno) << '\n';
229 exit (EXIT_FAILURE);
230 }
231}
232
233void pio_assembler::scan_end ()
234{
235 fclose (yyin);
236}