15 for (int64_t i =
tokens.size() - 1; i >= 0; --i) {
23 std::string lineNumberStr;
26 if (!ch.has_value()) {
36 if (!ch.has_value() || !isdigit(*ch)) {
41 return !lineNumberStr.empty() ? std::stoull(lineNumberStr) : 1;
48 if (!ch.has_value() || !isspace(*ch)) {
49 if (ch.has_value() && *ch ==
'\"')
55 if (!ch.has_value() || *ch ==
'\"')
59 return fileName.empty() ?
"unknown" : fileName;
75 token.set_filename(filename);
84 if (next.has_value() && *next ==
'\n') {
91 if (
token.has_value()) {
97 if (ch.has_value() && *ch ==
'#') {
100 }
while (ch.has_value() && *ch !=
'\n');
103 }
else if (ch.has_value() && *ch ==
'/') {
105 if (ch2.has_value() && *ch2 ==
'/') {
109 }
while (ch_ln.has_value() && *ch_ln !=
'\n');
111 }
else if (ch2.has_value() && *ch2 ==
'*') {
115 if (!ch_in.has_value())
119 if (ch_ex.has_value() && *ch_ex ==
'/') {
128 if (ch.has_value()) {
130 if (t_ch.has_value()) {
134 if (tok.has_value()) {
140 if (tok.has_value()) {
146 if (tok.has_value()) {
152 if (tok.has_value()) {
158 if (tok.has_value()) {
165 if (next.has_value() && (*next ==
' ' || *next ==
'\t' || *next ==
'\r')) {
197 if (!std::isalnum(*c) && *c !=
'_')
214 auto is_op = [](
char ch) {
215 return ch ==
'+' || ch ==
'-' || ch ==
'*' || ch ==
'/' ||
216 ch ==
'%' || ch ==
'^' || ch ==
'|' || ch ==
'&' ||
217 ch ==
'(' || ch ==
')';
219 auto is_hex_digit = [](
char ch) {
220 return std::isdigit(ch) ||
221 (ch >=
'a' && ch <=
'f') ||
222 (ch >=
'A' && ch <=
'F');
227 std::string tok_value;
230 if (!first_opt.has_value())
232 char first = *first_opt;
237 if (nx.has_value() && (*nx ==
'x' || *nx ==
'X')) {
241 if (!p.has_value() || !is_hex_digit(*p))
246 token.set_filename(filename);
252 int decimal_dots = 0;
258 if (std::isspace(c) || is_op(c))
262 if (!std::isdigit(c) && c !=
'.')
267 if (++decimal_dots > 1) {
268 std::ostringstream err;
270 err <<
"File: " << filename <<
" Line: " << lp.first <<
" Col: " << lp.second <<
" -> Too many decimal points in number.";
278 token.set_filename(filename);
284 static const std::set<std::string> c_op = {
285 "++",
"--",
">>=",
"<<=",
"+=",
"-=",
"*=",
"/=",
"%=",
"&=",
"|=",
"^=",
286 "==",
"!=",
">=",
"<=",
">>",
"<<",
"&&",
"||",
"->",
".",
"&",
"*",
"+",
287 "-",
"~",
"!",
"/",
"%",
">",
"<",
"=",
"^",
"|",
"?",
":",
";",
",",
288 "(",
")",
"[",
"]",
"{",
"}",
"->",
".",
"::",
"$",
":=",
"<>",
".."};
289 return c_op.find(str) != c_op.end();
294 std::string tok_value;
305 if (next.has_value() && *next ==
'-') {
307 std::string arg_value =
"--";
310 if (peeked.has_value() && (isalnum(*peeked) || *peeked ==
'_')) {
317 token.set_filename(filename);
322 token.set_filename(filename);
331 token.set_filename(filename);
337 std::string temp_value = tok_value;
346 tok_value = temp_value;
357 if (found && look != 0) {
362 token.set_filename(filename);
369 std::string tok_value;
374 if (!ch.has_value()) {
375 std::ostringstream stream;
377 stream <<
"File: " <<
string_buffer.cur_file() <<
" Line: " << cpos.first <<
" Col:" << cpos.second <<
" Double quote not terminated.";
382 if (!next_ch.has_value())
405 tok_value += *next_ch;
408 }
else if (*ch ==
'\"') {
415 token.set_filename(filename);
422 std::string tok_value;
427 if (!ch.has_value()) {
428 std::ostringstream stream;
430 stream <<
"File: " <<
string_buffer.cur_file() <<
" Line: " << cpos.first <<
" Col:" << cpos.second <<
" String quote not terminated.";
435 if (!next_ch.has_value())
458 tok_value += *next_ch;
461 }
else if (*ch ==
'\'') {
475 token.set_filename(filename);
483 std::ostringstream stream;
484 stream <<
"Token index: index out of bounds, Scanner Exception: " << index <<
"\n";
Exception thrown during scanning errors.
std::optional< TToken > grabSingle()
Try to grab a single-quoted character literal token.
std::optional< TToken > grabDigits()
Try to grab a numeric literal token.
uint64_t parseLineNumber()
Parse a line directive line number.
size_t size() const
Return the total number of scanned tokens.
TToken & operator[](size_t index)
Access a token by index.
std::optional< TToken > grabId()
Try to grab an identifier or keyword token.
std::string parseFileName()
Parse a line directive filename.
TString string_buffer
source text buffer
std::optional< TToken > grabString()
Try to grab a double-quoted string literal token.
std::vector< TToken > tokens
scanned token list
Scanner(const TString &b)
Construct a scanner from a string buffer.
uint64_t scan()
Tokenize the entire source buffer.
void removeEOL()
Remove end-of-line tokens from the token list.
bool is_c_sym(const StringType &str)
Check if a string is a recognized C-style symbol.
std::optional< TToken > grabSymbols()
Try to grab one or more symbol characters as a token.
TMap token_map
character classification map
void set_filename(const std::string &filename)
Set the source filename for this token.
void set_pos(const std::pair< uint64_t, uint64_t > &p)
Set the source position from a (line, column) pair.
void setToken(const types::TokenType &type, const String &value)
Set the token's type and value.
int64_t pos(const char *substr, const char *s)
buffer::StringBuffer< char >::string_type StringType
Underlying string type.
token::Token< char > TToken
Default token type.
buffer::StringBuffer< char > TString
Default character string buffer.
@ TT_SYM
symbol / operator token
@ TT_HEX
hexadecimal numeric literal
@ TT_ID
identifier or keyword
@ TT_NUM
decimal numeric literal
@ TT_ARG
argument token (e.g. $1)
@ TT_CHAR
alphabetic character
@ TT_SINGLE
single-char operator
@ TT_SYMBOL
multi-char symbol start
@ TT_DIGIT
digit character
@ TT_STRING
string delimiter (quote)
Lexical scanner that tokenizes source text into typed tokens.