Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
parse_utils.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
105#ifndef PARSE_UTILS_H
106#define PARSE_UTILS_H
107
108#include <string>
109#include <fstream>
110#include <sstream>
111#include <iostream>
112#include <cstdlib>
113#include <cctype>
114#include <cmath>
115#include <utility>
116#include <vector>
117#include <stdexcept>
118#include <algorithm>
119#include <aleph.H>
120#include <ah-errors.H>
121#include <ah-string-utils.H>
122
123namespace Aleph {
124// ============================================================================
125// Global State (inline for header-only)
126// ============================================================================
127
134inline constexpr size_t Buffer_Size = 512;
135
142inline int current_line_number = 1;
143
150inline int current_col_number = 1;
151
158inline int previous_line_number = 1;
159
166inline int previous_col_number = 1;
167
174inline std::string token_instance;
175
176// ============================================================================
177// Buffer Management
178// ============================================================================
179
204inline void put_char_in_buffer(char *&start_addr, const char *end_addr, int c)
205{
206 if (start_addr >= end_addr)
207 AH_ERROR("String too long (buffer overflow in parse_utils)");
208
209 *start_addr++ = static_cast<char>(c);
210}
211
212// ============================================================================
213// Token Scanning
214// ============================================================================
215
237
250inline void close_token_scanning(const char *buffer, char *&start_addr, const char *end_addr)
251{
252 put_char_in_buffer(start_addr, end_addr, '\0');
253 token_instance = buffer;
254}
255
256// ============================================================================
257// Stream Reading
258// ============================================================================
259
282inline int read_char_from_stream(std::ifstream &input_stream)
283{
284 ah_out_of_range_error_if(input_stream.eof()) << "end of file has been reached";
285
286 const int c = input_stream.get();
287
288 if (c == '\n')
289 {
292 }
293 else
295
296 return c;
297}
298
317inline void skip_white_spaces(std::ifstream &input_stream)
318{
319 while (std::isspace(read_char_from_stream(input_stream)))
320 {
321 } // Skip whitespace
322 input_stream.unget();
323}
324
325// ============================================================================
326// Token Loading
327// ============================================================================
328
356inline long load_number(std::ifstream &input_stream)
357{
358 char buffer[Buffer_Size];
359 char *start_addr = buffer;
360 const char *end_addr = buffer + Buffer_Size;
361
363
364 try
365 {
368
369 // Handle optional minus sign
370 if (c == '-')
371 {
372 put_char_in_buffer(start_addr, end_addr, c);
374
375 if (not std::isdigit(c))
376 {
377 input_stream.unget();
378 close_token_scanning(buffer, start_addr, end_addr);
379 return std::strtol(buffer, nullptr, 10);
380 }
381 }
382
383 while (true)
384 {
385 // Read digits
386 while (std::isdigit(c))
387 {
388 put_char_in_buffer(start_addr, end_addr, c);
390 }
391
392 // Number ends at whitespace
393 if (std::isspace(c))
394 {
395 close_token_scanning(buffer, start_addr, end_addr);
396 return std::strtol(buffer, nullptr, 10);
397 }
398
399 ah_domain_error_if(true) << "Invalid number format";
400 }
401 }
402 catch (const std::out_of_range &)
403 {
404 // EOF reached - return what we have
405 close_token_scanning(buffer, start_addr, end_addr);
406 return std::strtol(buffer, nullptr, 10);
407 }
408}
409
439inline std::string load_string(std::ifstream &input_stream)
440{
441 char buffer[Buffer_Size];
442 char *start_addr = buffer;
443 const char *end_addr = buffer + Buffer_Size;
444
445 bool quoted = false;
446
449
451
452 if (c == '\"')
453 quoted = true;
454 else
455 put_char_in_buffer(start_addr, end_addr, c);
456
457 while (true)
458 {
460
461 // End of quoted string
462 if (c == '\"' and quoted)
463 break;
464
465 // End of unquoted string
466 if (not quoted and (std::isblank(c) or c == '\n' or c == EOF))
467 break;
468
469 put_char_in_buffer(start_addr, end_addr, c);
470 }
471
472 close_token_scanning(buffer, start_addr, end_addr);
473 return {buffer};
474}
475
476// ============================================================================
477// Error Reporting
478// ============================================================================
479
499[[noreturn]]
500inline void print_parse_error_and_exit(const std::string &str)
501{
502 std::cout << "Parse error " << previous_line_number << ":" << previous_col_number << " " << str
503 << std::endl
504 << "Last token seen is: " << token_instance << std::endl;
505 std::exit(1);
506}
507
524inline void print_parse_warning(const std::string &str)
525{
526 std::cout << "Parse warning " << previous_line_number << ":" << previous_col_number << " " << str
527 << std::endl
528 << "Last token seen is: " << token_instance << std::endl;
529}
530
531// ============================================================================
532// Utility Functions
533// ============================================================================
534
556inline std::string command_line_to_string(int argc, char *argv[])
557{
558 std::string command_line;
559
560 for (int i = 0; i < argc; ++i)
561 {
562 command_line += " ";
563 command_line += argv[i];
564 }
565
566 return command_line;
567}
568
582inline void reset_parse_state()
583{
588 token_instance.clear();
589}
590
591// ============================================================================
592// Source Location and Parse Errors
593// ============================================================================
594
602{
603 std::string filename;
604 int line = 1;
605 int column = 1;
606
608 SourceLocation() = default;
609
611 SourceLocation(std::string file, const int ln, const int col)
612 : filename(std::move(file)), line(ln), column(col)
613 {}
614
616 static SourceLocation current(const std::string &file = "")
617 {
619 }
620
622 static SourceLocation previous(const std::string &file = "")
623 {
625 }
626
631 [[nodiscard]] std::string to_string() const
632 {
633 std::ostringstream oss;
634 if (not filename.empty())
635 oss << filename << ":";
636 oss << line << ":" << column;
637 return oss.str();
638 }
639};
640
653class ParseError : public std::runtime_error
654{
656
657public:
663 ParseError(const std::string &message, const SourceLocation &location)
664 : std::runtime_error(location.to_string() + ": " + message), loc_(location)
665 {}
666
671 explicit ParseError(const std::string &message)
672 : std::runtime_error(std::to_string(previous_line_number) + ":" +
675 {}
676
679 {
680 return loc_;
681 }
682};
683
690#define ah_parse_error() \
691 Aleph::ExceptionBuilder<Aleph::ParseError>(), \
692 std::ostringstream() << "(" << __FILE__ << ":" << __LINE__ << ") | "
693
699#define ah_parse_error_if(C) \
700 if (C) [[unlikely]] \
701 Aleph::ExceptionBuilder<Aleph::ParseError>(), \
702 std::ostringstream() << "(" << __FILE__ << ":" << __LINE__ << ") | "
703
709#define ah_parse_error_unless(C) \
710 if (not (C)) [[unlikely]] \
711 Aleph::ExceptionBuilder<Aleph::ParseError>(), \
712 std::ostringstream() << "(" << __FILE__ << ":" << __LINE__ << ") | "
713
714// ============================================================================
715// Lookahead and Backtracking
716// ============================================================================
717
722{
723 std::streampos pos;
724 int line{};
725 int column{};
726};
727
744inline int peek_char(std::ifstream &input_stream)
745{
746 return input_stream.peek();
747}
748
761{
763 sp.pos = input_stream.tellg();
764 sp.line = current_line_number;
765 sp.column = current_col_number;
766 return sp;
767}
768
780inline void restore_position(std::ifstream &input_stream, const StreamPosition &pos)
781{
782 input_stream.seekg(pos.pos);
785}
786
787// ============================================================================
788// Comment Handling
789// ============================================================================
790
808inline void skip_line_comment(std::ifstream &input_stream)
809{
810 while (not input_stream.eof())
811 {
812 if (const int c = input_stream.get(); c == '\n')
813 {
816 return;
817 }
819 }
820}
821
837inline void skip_block_comment(std::ifstream &input_stream,
838 const std::string &open =
839 "/"
840 "*",
841 const std::string &close =
842 "*"
843 "/")
844{
845 (void) open; // Documented for clarity; opening sequence already consumed.
846 size_t match_pos = 0;
847
848 while (not input_stream.eof())
849 {
850 if (const int c = input_stream.get(); c == '\n')
851 {
854 match_pos = 0;
855 }
856 else
857 {
859
860 if (c == close[match_pos])
861 {
862 match_pos++;
863 if (match_pos == close.size())
864 return; // Found closing sequence
865 }
866 else
867 match_pos = (c == close[0]) ? 1 : 0;
868 }
869 }
870
871 ah_parse_error() << "Unterminated block comment";
872}
873
889{
890 while (not input_stream.eof())
891 {
892 if (const int c = peek_char(input_stream); std::isspace(c))
894 else if (c == '/')
895 {
896 // Peek ahead for // or /* ... */
897 input_stream.get();
899 if (const int next = peek_char(input_stream); next == '/')
900 {
901 input_stream.get();
904 }
905 else if (next == '*')
906 {
907 input_stream.get();
910 }
911 else
912 {
913 // Not a comment, put back the '/'
914 input_stream.unget();
916 return;
917 }
918 }
919 else if (c == '#')
920 {
921 // Shell/Python style line comment
924 }
925 else
926 return; // Non-whitespace, non-comment found
927 }
928}
929
930// ============================================================================
931// Numeric Parsing (Extended)
932// ============================================================================
933
958inline double load_double(std::ifstream &input_stream)
959{
960 char buffer[Buffer_Size];
961 char *ptr = buffer;
962 char *end = buffer + Buffer_Size;
963
966
968
969 // Optional sign
970 if (c == '-' or c == '+')
971 {
972 put_char_in_buffer(ptr, end, c);
974 }
975
976 bool has_digits = false;
977
978 // Integer part
979 while (std::isdigit(c))
980 {
981 has_digits = true;
982 put_char_in_buffer(ptr, end, c);
984 }
985
986 // Decimal part
987 if (c == '.')
988 {
989 put_char_in_buffer(ptr, end, c);
991
992 while (std::isdigit(c))
993 {
994 has_digits = true;
995 put_char_in_buffer(ptr, end, c);
997 }
998 }
999
1000 ah_parse_error_unless(has_digits) << "Invalid floating-point number: no digits";
1001
1002 // Exponent part
1003 if (c == 'e' or c == 'E')
1004 {
1005 put_char_in_buffer(ptr, end, c);
1007
1008 if (c == '+' or c == '-')
1009 {
1010 put_char_in_buffer(ptr, end, c);
1012 }
1013
1014 ah_parse_error_unless(std::isdigit(c)) << "Invalid exponent in floating-point number";
1015
1016 while (std::isdigit(c))
1017 {
1018 put_char_in_buffer(ptr, end, c);
1020 }
1021 }
1022
1023 // Put back the terminating character (only if it is a real character, not EOF)
1024 if (c != EOF)
1025 {
1026 input_stream.unget();
1027 if (c != '\n')
1029 }
1030
1031 close_token_scanning(buffer, ptr, end);
1032 return std::strtod(buffer, nullptr);
1033}
1034
1049inline long load_hex_number(std::ifstream &input_stream)
1050{
1051 char buffer[Buffer_Size];
1052 char *ptr = buffer;
1053 char *end = buffer + Buffer_Size;
1054
1057
1059
1060 // Expect '0'
1061 ah_parse_error_unless(c == '0') << "Hexadecimal number must start with 0x";
1062
1064 ah_parse_error_unless(c == 'x' or c == 'X') << "Hexadecimal number must start with 0x";
1065
1067
1068 ah_parse_error_unless(std::isxdigit(c)) << "Invalid hexadecimal number";
1069
1070 while (std::isxdigit(c))
1071 {
1072 put_char_in_buffer(ptr, end, c);
1074 }
1075
1076 input_stream.unget();
1077 if (c != '\n')
1079
1080 close_token_scanning(buffer, ptr, end);
1081 return std::strtol(buffer, nullptr, 16);
1082}
1083
1098inline long load_octal_number(std::ifstream &input_stream)
1099{
1100 char buffer[Buffer_Size];
1101 char *ptr = buffer;
1102 char *end = buffer + Buffer_Size;
1103
1106
1108
1109 ah_parse_error_unless(c == '0') << "Octal number must start with 0";
1110
1112
1113 // Check it's not hex (0x)
1114 ah_parse_error_if(c == 'x' or c == 'X') << "Expected octal number, got hexadecimal";
1115
1116 while (c >= '0' and c <= '7')
1117 {
1118 put_char_in_buffer(ptr, end, c);
1120 }
1121
1122 input_stream.unget();
1123 if (c != '\n')
1125
1126 close_token_scanning(buffer, ptr, end);
1127
1128 if (ptr == buffer)
1129 return 0; // Just "0"
1130
1131 return std::strtol(buffer, nullptr, 8);
1132}
1133
1148inline long load_binary_number(std::ifstream &input_stream)
1149{
1150 char buffer[Buffer_Size];
1151 char *ptr = buffer;
1152 const char *end = buffer + Buffer_Size;
1153
1156
1158
1159 ah_parse_error_unless(c == '0') << "Binary number must start with 0b";
1160
1162 ah_parse_error_unless(c == 'b' or c == 'B') << "Binary number must start with 0b";
1163
1165
1166 ah_parse_error_unless(c == '0' or c == '1') << "Invalid binary number";
1167
1168 while (c == '0' or c == '1')
1169 {
1170 put_char_in_buffer(ptr, end, c);
1172 }
1173
1174 input_stream.unget();
1175 if (c != '\n')
1177
1178 close_token_scanning(buffer, ptr, end);
1179 return std::strtol(buffer, nullptr, 2);
1180}
1181
1182// ============================================================================
1183// Identifier and Keyword Parsing
1184// ============================================================================
1185
1201inline std::string load_identifier(std::ifstream &input_stream)
1202{
1203 char buffer[Buffer_Size];
1204 char *ptr = buffer;
1205 const char *end = buffer + Buffer_Size;
1206
1209
1211
1212 // Must start with a letter or underscore
1213 ah_parse_error_unless(std::isalpha(c) or c == '_')
1214 << "Identifier must start with letter or underscore";
1215
1216 put_char_in_buffer(ptr, end, c);
1217
1218 while (true)
1219 {
1221
1222 if (std::isalnum(c) or c == '_')
1223 put_char_in_buffer(ptr, end, c);
1224 else
1225 break;
1226 }
1227
1228 input_stream.unget();
1229 if (c != '\n')
1231
1232 close_token_scanning(buffer, ptr, end);
1233 return {buffer};
1234}
1235
1251inline bool is_keyword(const std::string &s, const std::vector<std::string> &keywords)
1252{
1253 return std::find(keywords.begin(), keywords.end(), s) != keywords.end();
1254}
1255
1256// ============================================================================
1257// Expectation Functions
1258// ============================================================================
1259
1278inline void expect_char(std::ifstream &input_stream, char expected)
1279{
1281 const int c = read_char_from_stream(input_stream);
1283 << "Expected '" << expected << "' but found '" << static_cast<char>(c) << "'";
1284}
1285
1303inline void expect(std::ifstream &input_stream, const std::string &expected)
1304{
1307
1308 for (const char ch : expected)
1309 {
1310 const int c = read_char_from_stream(input_stream);
1311 ah_parse_error_unless(c == ch) << "Expected '" << expected << "'";
1312 }
1313
1315}
1316
1328inline bool try_char(std::ifstream &input_stream, char ch)
1329{
1332
1333 if (const int c = read_char_from_stream(input_stream); c == ch)
1334 return true;
1335
1337 return false;
1338}
1339
1340// ============================================================================
1341// String Parsing (Extended)
1342// ============================================================================
1343
1362inline char process_escape(const int c)
1363{
1364 switch (c)
1365 {
1366 case 'n':
1367 return '\n';
1368 case 't':
1369 return '\t';
1370 case 'r':
1371 return '\r';
1372 case '\\':
1373 return '\\';
1374 case '"':
1375 return '"';
1376 case '\'':
1377 return '\'';
1378 case '0':
1379 return '\0';
1380 case 'a':
1381 return '\a';
1382 case 'b':
1383 return '\b';
1384 case 'f':
1385 return '\f';
1386 case 'v':
1387 return '\v';
1388 default:
1389 return static_cast<char>(c); // Unknown escape, keep as-is
1390 }
1391}
1392
1411inline std::string load_escaped_string(std::ifstream &input_stream)
1412{
1413 char buffer[Buffer_Size];
1414 char *ptr = buffer;
1415 const char *end = buffer + Buffer_Size;
1416
1419
1421
1422 ah_parse_error_unless(c == '"') << "Expected '\"' to start string";
1423
1424 while (true)
1425 {
1427
1428 ah_parse_error_if(c == EOF) << "Unterminated string literal";
1429
1430 if (c == '"')
1431 break;
1432
1433 if (c == '\\')
1434 {
1436 ah_parse_error_if(c == EOF) << "Unterminated escape sequence";
1437 c = static_cast<unsigned char>(process_escape(c));
1438 }
1439
1440 put_char_in_buffer(ptr, end, c);
1441 }
1442
1443 const size_t len = ptr - buffer;
1444 close_token_scanning(buffer, ptr, end);
1445 return std::string(buffer, len);
1446}
1447
1464inline char load_char_literal(std::ifstream &input_stream)
1465{
1468
1470
1471 ah_parse_error_unless(c == '\'') << "Expected single quote to start character literal";
1472
1474
1475 if (c == '\\')
1476 {
1478 c = static_cast<unsigned char>(process_escape(c));
1479 }
1480
1481 char result = static_cast<char>(c);
1482
1484 ah_parse_error_unless(c == '\'') << "Expected single quote to end character literal";
1485
1486 token_instance = "'";
1487 token_instance += result;
1488 token_instance += "'";
1489
1490 return result;
1491}
1492
1493// ============================================================================
1494// Token Types (for lexer support)
1495// ============================================================================
1496
1500enum class TokenType
1501{
1502 END_OF_FILE,
1503 IDENTIFIER,
1504 INTEGER,
1505 FLOAT,
1506 STRING,
1507 CHAR,
1508 OPERATOR,
1509 PUNCTUATION,
1510 KEYWORD,
1511 COMMENT,
1512 UNKNOWN
1513};
1514
1518inline std::string token_type_to_string(TokenType type)
1519{
1520 switch (type)
1521 {
1523 return "EOF";
1525 return "IDENTIFIER";
1526 case TokenType::INTEGER:
1527 return "INTEGER";
1528 case TokenType::FLOAT:
1529 return "FLOAT";
1530 case TokenType::STRING:
1531 return "STRING";
1532 case TokenType::CHAR:
1533 return "CHAR";
1535 return "OPERATOR";
1537 return "PUNCTUATION";
1538 case TokenType::KEYWORD:
1539 return "KEYWORD";
1540 case TokenType::COMMENT:
1541 return "COMMENT";
1542 case TokenType::UNKNOWN:
1543 return "UNKNOWN";
1544 default:
1545 return "???";
1546 }
1547}
1548
1552struct Token
1553{
1555 std::string value;
1557
1559 Token() = default;
1560
1563 : type(t), value(std::move(v)), location(std::move(loc))
1564 {}
1565
1567 [[nodiscard]] bool is_eof() const
1568 {
1569 return type == TokenType::END_OF_FILE;
1570 }
1571
1573 [[nodiscard]] std::string to_string() const
1574 {
1575 return token_type_to_string(type) + "(\"" + value + "\") at " + location.to_string();
1576 }
1577};
1578
1579// ============================================================================
1580// File Utilities
1581// ============================================================================
1582
1591inline std::string load_file_contents(const std::string &filename)
1592{
1593 std::ifstream file(filename);
1594 ah_runtime_error_unless(file.is_open()) << "Cannot open file: " << filename;
1595
1596 std::ostringstream ss;
1597 ss << file.rdbuf();
1598 return ss.str();
1599}
1600
1609inline DynList<std::string> load_file_lines(const std::string &filename)
1610{
1611 std::ifstream file(filename);
1612 ah_runtime_error_unless(file.is_open()) << "Cannot open file: " << filename;
1613
1615 std::string line;
1616
1617 while (std::getline(file, line))
1618 lines.append(line);
1619
1620 return lines;
1621}
1622
1630inline DynList<std::string> split_string(const std::string &str, char delimiter)
1631{
1632 DynList<std::string> result;
1633 std::istringstream iss(str);
1634 std::string token;
1635
1636 while (std::getline(iss, token, delimiter))
1637 result.append(token);
1638
1639 return result;
1640}
1641} // namespace Aleph
1642
1643// ============================================================================
1644// Global namespace compatibility (for existing code)
1645// ============================================================================
1646
1647// Note: input_file_name is NOT exported to global namespace because
1648// many applications define their own variable with this name.
1649// Use Aleph::input_file_name if needed.
1650
1651// Global state
1652using Aleph::Buffer_Size;
1658
1659// Core functions
1663using Aleph::load_number;
1664using Aleph::load_string;
1671
1672// Source location and errors
1673using Aleph::ParseError;
1675
1676// Lookahead and backtracking
1678using Aleph::peek_char;
1681
1682// Comments
1686
1687// Extended numeric parsing
1689using Aleph::load_double;
1692
1693// Identifiers and keywords
1694using Aleph::is_keyword;
1696
1697// Expectations
1698using Aleph::expect;
1699using Aleph::expect_char;
1700using Aleph::try_char;
1701
1702// Extended string parsing
1706
1707// Tokens
1708using Aleph::Token;
1710using Aleph::TokenType;
1711
1712// File utilities
1716using Aleph::trim;
1717
1718// ============================================================================
1719// Legacy Macro (preserved for backward compatibility)
1720// ============================================================================
1721
1735#define PRINT_ERROR(...) \
1736 ((std::cout << input_file_name << "(" << Aleph::previous_line_number << "," \
1737 << Aleph::previous_col_number << "): " << '\n'), \
1738 (std::cout << "Last token: " << Aleph::token_instance << '\n'), AH_ERROR(__VA_ARGS__))
1739
1740#endif // PARSE_UTILS_H
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Definition ah-errors.H:255
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
String manipulation utilities.
#define AH_ERROR(...)
Print an error message (always enabled).
Definition ahDefs.H:270
Core header for the Aleph-w library.
string command_line
Definition btreepic.C:403
size_t size_t col
Definition ca-c-api.h:116
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
Exception class for parsing errors with location information.
ParseError(const std::string &message, const SourceLocation &location)
Construct a parse error with message and location.
ParseError(const std::string &message)
Construct a parse error with message only.
const SourceLocation & location() const
Get the source location of the error.
SourceLocation loc_
Minimal std::expected-style result type for C++20.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void restore_position(std::ifstream &input_stream, const StreamPosition &pos)
Restore a previously marked position.
int current_line_number
Current line number in the input stream.
char load_char_literal(std::ifstream &input_stream)
Load a character literal.
bool is_keyword(const std::string &s, const std::vector< std::string > &keywords)
Check if a string is in a list of keywords.
void message(const char *file, int line, const char *format,...)
Print an informational message with file and line info.
Definition ahDefs.C:95
void skip_block_comment(std::ifstream &input_stream, const std::string &open="/" "*", const std::string &close="*" "/")
Skip a block comment (C-style)
std::string load_file_contents(const std::string &filename)
Load entire file contents into a string.
void init_token_scanning()
Initialize token scanning by recording current position.
void close_token_scanning(const char *buffer, char *&start_addr, const char *end_addr)
Finalize token scanning by null-terminating and saving the token.
Container< std::string > split_string(const std::string &s, const std::string &delim)
Split a std::string by a set of delimiter characters.
and
Check uniqueness with explicit hash + equality functors.
int read_char_from_stream(std::ifstream &input_stream)
Read a single character from an input stream with position tracking.
void expect_char(std::ifstream &input_stream, char expected)
Expect and consume a specific character.
void expect(std::ifstream &input_stream, const std::string &expected)
Expect and consume a specific string/keyword.
void print_parse_error_and_exit(const std::string &str)
Print a parse error message and terminate the program.
StreamPosition mark_position(std::ifstream &input_stream)
Mark the current position for potential backtracking.
double load_double(std::ifstream &input_stream)
Load a floating-point number from the input stream.
int current_col_number
Current column number in the input stream.
int previous_col_number
Column number at the start of the current token.
std::string trim(const std::string &s)
Return a trimmed copy of a std::string (leading + trailing whitespace removed).
std::string token_instance
The most recently scanned token.
void put_char_in_buffer(char *&start_addr, const char *end_addr, int c)
Append a character to a buffer with bounds checking.
bool try_char(std::ifstream &input_stream, char ch)
Try to match a character without throwing.
char process_escape(const int c)
Process an escape sequence.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
long load_binary_number(std::ifstream &input_stream)
Load a binary number from the input stream.
std::string command_line_to_string(int argc, char *argv[])
Convert command line arguments to a single string.
std::string load_identifier(std::ifstream &input_stream)
Load an identifier from the input stream.
void reset_parse_state()
Reset the parsing state to initial values.
int previous_line_number
Line number at the start of the current token.
void skip_white_spaces(std::ifstream &input_stream)
Skip whitespace characters in the input stream.
std::string token_type_to_string(TokenType type)
Convert TokenType to string for debugging.
DynList< std::string > load_file_lines(const std::string &filename)
Load file as a list of lines.
long load_octal_number(std::ifstream &input_stream)
Load an octal number from the input stream.
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:171
std::string load_escaped_string(std::ifstream &input_stream)
Load a string with escape sequence processing.
constexpr size_t Buffer_Size
Default buffer size for token parsing.
TokenType
Enumeration of basic token types.
@ CHAR
Character literal.
@ END_OF_FILE
End of input.
@ INTEGER
Integer literal.
@ STRING
String literal.
@ UNKNOWN
Unknown/invalid token.
@ IDENTIFIER
Variable/function name.
@ KEYWORD
Reserved keyword.
@ PUNCTUATION
Punctuation (;, {, }, etc.)
@ OPERATOR
Operator (+, -, etc.)
@ FLOAT
Floating-point literal.
@ COMMENT
Comment (if preserving)
std::string load_string(std::ifstream &input_stream)
Load a string from the input stream.
void skip_whitespace_and_comments(std::ifstream &input_stream)
Skip whitespace and comments (C/C++ style)
int peek_char(std::ifstream &input_stream)
Peek at the next character without consuming it.
long load_hex_number(std::ifstream &input_stream)
Load a hexadecimal number from the input stream.
void skip_line_comment(std::ifstream &input_stream)
Skip a line comment (// style or # style)
void print_parse_warning(const std::string &str)
Print a parse warning message.
long load_number(std::ifstream &input_stream)
Load an integer number from the input stream.
STL namespace.
#define ah_parse_error_if(C)
Throws a ParseError if condition holds.
#define ah_parse_error_unless(C)
Throws a ParseError if condition does NOT hold.
#define ah_parse_error()
Throws a ParseError unconditionally.
Represents a location in source code.
int column
Column number (1-based)
SourceLocation(std::string file, const int ln, const int col)
Construct with all fields.
SourceLocation()=default
Default constructor.
int line
Line number (1-based)
std::string filename
Name of the source file.
std::string to_string() const
Convert to human-readable string.
static SourceLocation previous(const std::string &file="")
Construct from the previous (token start) global parsing state.
static SourceLocation current(const std::string &file="")
Construct from the current global parsing state.
Structure to save stream position for backtracking.
int column
Column number at this position.
int line
Line number at this position.
std::streampos pos
Stream position.
Structure representing a lexical token.
Token(TokenType t, std::string v, SourceLocation loc)
Construct with all fields.
bool is_eof() const
Check if this is an end-of-file token.
std::string value
String value/content.
Token()=default
Default constructor.
std::string to_string() const
String representation for debugging.
SourceLocation location
Where token appeared.
TokenType type
Type of the token.
ofstream file
Definition writeRb.C:51