diff options
| author | 2026-02-22 03:18:01 +0000 | |
|---|---|---|
| committer | 2026-02-22 03:18:01 +0000 | |
| commit | f404d75c6050223a3cbbe9b7775700ca291ff93d (patch) | |
| tree | cbcec3fec884901b11e32def54f539d3a8a6eb3b /examples | |
| parent | add lexer implementation (diff) | |
| download | rs274ngc-f404d75c6050223a3cbbe9b7775700ca291ff93d.tar.gz | |
add lex example
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/lex.c | 67 | ||||
| -rw-r--r-- | examples/utils.c | 77 | ||||
| -rw-r--r-- | examples/utils.h | 64 |
3 files changed, 208 insertions, 0 deletions
diff --git a/examples/lex.c b/examples/lex.c new file mode 100644 index 0000000..a0f33e7 --- /dev/null +++ b/examples/lex.c | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | // examples/lex.c | ||
| 2 | |||
| 3 | #include <stddef.h> | ||
| 4 | #include <stdio.h> | ||
| 5 | #include <fcntl.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | |||
| 8 | #define CMMM__RS274NGC__LEXEME__STRIP_VENDOR | ||
| 9 | #define CMMM__RS274NGC__LEXER__STRIP_VENDOR | ||
| 10 | |||
| 11 | #include "utils.h" | ||
| 12 | #include "cmmm/rs274ngc/lexer.h" | ||
| 13 | |||
| 14 | int | ||
| 15 | main (int argc, char *argv[]) | ||
| 16 | { | ||
| 17 | const char *filename; | ||
| 18 | struct cmmm__sv rs274ngc; | ||
| 19 | struct cmmm__arena a = {0}; | ||
| 20 | |||
| 21 | if (argc == 1) { | ||
| 22 | filename = "-"; | ||
| 23 | rs274ngc = read_until_eof (&a, 0); | ||
| 24 | } else if (argc == 2) { | ||
| 25 | filename = argv[1]; | ||
| 26 | int fd = open (filename, O_RDONLY); | ||
| 27 | rs274ngc = mmap_whole (fd); | ||
| 28 | } else { | ||
| 29 | exit (EXIT_FAILURE); // TODO(cmmm): better DIE | ||
| 30 | } | ||
| 31 | |||
| 32 | // printf (SV_FMT, SV_FMTA (rs274ngc)); | ||
| 33 | // return 0; | ||
| 34 | |||
| 35 | struct rs274ngc__lexer lexer = | ||
| 36 | rs274ngc__lexer__from_string_view (rs274ngc, filename); | ||
| 37 | |||
| 38 | int line = 1; | ||
| 39 | const char *bol = lexer.lexeme.sv.begin; | ||
| 40 | for (;; rs274ngc__lexer__next_lexeme (&lexer)) { | ||
| 41 | struct rs274ngc__lexeme lexeme = lexer.lexeme; | ||
| 42 | |||
| 43 | if (lexeme.kind == RS274NGC__LEXEME__KIND__END_OF_FILE) { | ||
| 44 | printf ("%s:%d:%ld: %s\n", | ||
| 45 | lexer.filename, line, lexeme.sv.begin - bol, | ||
| 46 | rs274ngc__lexeme__kind_names[lexeme.kind]); | ||
| 47 | break; | ||
| 48 | }; | ||
| 49 | |||
| 50 | if (lexeme.kind == RS274NGC__LEXEME__KIND__END_OF_LINE) { | ||
| 51 | printf ("%s:%d:%ld: %s\n", | ||
| 52 | lexer.filename, line, lexeme.sv.begin - bol + 1, | ||
| 53 | rs274ngc__lexeme__kind_names[lexeme.kind]); | ||
| 54 | bol = lexeme.sv.end; | ||
| 55 | line += 1; | ||
| 56 | continue; | ||
| 57 | } | ||
| 58 | |||
| 59 | printf ("%s:%d:%ld-%ld: %s: |"SV_FMT"|\n", | ||
| 60 | lexer.filename, line, lexeme.sv.begin - bol + 1, lexeme.sv.end - bol, | ||
| 61 | rs274ngc__lexeme__kind_names[lexeme.kind], SV_FMTA (lexeme.sv)); | ||
| 62 | } | ||
| 63 | |||
| 64 | return EXIT_SUCCESS; | ||
| 65 | } | ||
| 66 | |||
| 67 | // examples/lex.c ends here | ||
diff --git a/examples/utils.c b/examples/utils.c new file mode 100644 index 0000000..35c8d98 --- /dev/null +++ b/examples/utils.c | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | // examples/utils.c | ||
| 2 | |||
| 3 | #include <stddef.h> | ||
| 4 | #include <sys/stat.h> | ||
| 5 | #include <sys/mman.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include <errno.h> | ||
| 8 | #include <unistd.h> | ||
| 9 | #include <fcntl.h> | ||
| 10 | |||
| 11 | #include "utils.h" | ||
| 12 | |||
| 13 | struct cmmm__sv | ||
| 14 | mmap_whole (int fd) | ||
| 15 | { | ||
| 16 | struct cmmm__sv sv; | ||
| 17 | |||
| 18 | struct stat st; | ||
| 19 | int ret = fstat (fd, &st); | ||
| 20 | UNUSED (ret); | ||
| 21 | ASSERT_MSG (ret != -1, "fstat: %s", strerror (errno)); | ||
| 22 | ASSERT (S_ISREG (st.st_mode)); | ||
| 23 | |||
| 24 | posix_fadvise (fd, 0, st.st_size, POSIX_FADV_SEQUENTIAL | | ||
| 25 | POSIX_FADV_WILLNEED | | ||
| 26 | POSIX_FADV_NOREUSE); | ||
| 27 | |||
| 28 | sv.begin = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE | | ||
| 29 | MAP_POPULATE | | ||
| 30 | MAP_NONBLOCK, fd, 0); | ||
| 31 | ASSERT_MSG (sv.begin != MAP_FAILED, "mmap: %s", strerror (errno)); | ||
| 32 | posix_madvise ((void *) sv.begin, st.st_size, MADV_HUGEPAGE | MADV_WILLNEED); | ||
| 33 | |||
| 34 | sv.end = sv.begin + st.st_size; | ||
| 35 | |||
| 36 | return sv; | ||
| 37 | } | ||
| 38 | |||
| 39 | struct cmmm__sv | ||
| 40 | read_until_eof (ARENA arena, int fd) | ||
| 41 | { | ||
| 42 | struct arena__checkpoint checkpoint = arena__checkpoint (arena); | ||
| 43 | size_t reserve = 4096; | ||
| 44 | |||
| 45 | size_t read_total = 0; | ||
| 46 | for (;;) { | ||
| 47 | arena__reserve (arena, reserve, 1); | ||
| 48 | ssize_t bytes_read = read (fd, | ||
| 49 | arena__next_free (arena, 1), | ||
| 50 | arena__room (arena, 1)); | ||
| 51 | |||
| 52 | if (bytes_read < 0) { | ||
| 53 | DEBUG ("fstat: %s", strerror (errno)); | ||
| 54 | arena__rollback_to (arena, checkpoint); | ||
| 55 | return (struct cmmm__sv) {0}; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (bytes_read == 0) | ||
| 59 | break; | ||
| 60 | |||
| 61 | read_total += bytes_read; | ||
| 62 | |||
| 63 | arena__allocate_fast (arena, bytes_read, 1); | ||
| 64 | reserve *= 2; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (arena->tail->free == checkpoint.free) | ||
| 68 | return (struct cmmm__sv) {0}; | ||
| 69 | |||
| 70 | char *ptr = arena__coalesce_from_fast (arena, checkpoint, read_total); | ||
| 71 | return (struct cmmm__sv) { | ||
| 72 | .begin = ptr, | ||
| 73 | .end = ptr + read_total, | ||
| 74 | }; | ||
| 75 | } | ||
| 76 | |||
| 77 | // examples/utils.c ends here | ||
diff --git a/examples/utils.h b/examples/utils.h new file mode 100644 index 0000000..dc48a85 --- /dev/null +++ b/examples/utils.h | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | // examples/utils.h | ||
| 2 | |||
| 3 | #ifndef INCLUDED_UTILS_H | ||
| 4 | #define INCLUDED_UTILS_H | ||
| 5 | |||
| 6 | #include <stdlib.h> | ||
| 7 | #include <stdio.h> | ||
| 8 | |||
| 9 | #define CMMM__STRING_VIEW__STRIP_VENDOR | ||
| 10 | #define CMMM__STRING_VIEW__SHORT_NAMESPACE | ||
| 11 | #define CMMM__ARENA__STRIP_VENDOR | ||
| 12 | |||
| 13 | #include "cmmm/string-view.h" | ||
| 14 | #include "cmmm/arena.h" | ||
| 15 | |||
| 16 | #define NOP() do {} while (0) | ||
| 17 | |||
| 18 | #define UNUSED(EXP) ((void) EXP) | ||
| 19 | |||
| 20 | #define ARRAY_LENGTH(ARR) (sizeof (ARR)/sizeof (*(ARR))) | ||
| 21 | |||
| 22 | #ifndef NDEBUG | ||
| 23 | #include <assert.h> | ||
| 24 | #define ASSERT assert | ||
| 25 | #else | ||
| 26 | #define ASSERT(...) NOP () | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #define STRINGIFY(ARG) #ARG | ||
| 30 | #define TO_STRING(ARG) STRINGIFY (ARG) | ||
| 31 | |||
| 32 | #ifndef NDEBUG | ||
| 33 | #define DEBUG(FMT, ...) \ | ||
| 34 | fprintf (stderr, __FILE__ ":" TO_STRING (__LINE__) ": %s: " FMT "\n", \ | ||
| 35 | __func__ __VA_OPT__ (,) __VA_ARGS__) | ||
| 36 | #define LOG(FMT, ...) \ | ||
| 37 | fprintf (stderr, __FILE__ ":" TO_STRING (__LINE__) ": %s: " FMT "\n", \ | ||
| 38 | __func__ __VA_OPT__ (,) __VA_ARGS__) | ||
| 39 | #else | ||
| 40 | #define DEBUG(...) NOP () | ||
| 41 | #define LOG(FMT, ...) \ | ||
| 42 | fprintf (stderr, FMT "\n", __VA_OPT__ (,) __VA_ARGS__) | ||
| 43 | #endif | ||
| 44 | |||
| 45 | #define ERROR(FMT, ...) LOG ("error: " FMT __VA_OPT__ (,) __VA_ARGS__) | ||
| 46 | #define WARNING(FMT, ...) LOG ("warning: " FMT __VA_OPT__ (,) __VA_ARGS__) | ||
| 47 | #define NOTICE(FMT, ...) LOG ("notice: " FMT __VA_OPT__ (,) __VA_ARGS__) | ||
| 48 | #define INFO(FMT, ...) LOG ("info: " FMT __VA_OPT__ (,) __VA_ARGS__) | ||
| 49 | |||
| 50 | #ifndef NDEBUG | ||
| 51 | #define ASSERT_MSG(EXP, FMT, ...) do if (!(EXP)) { \ | ||
| 52 | DEBUG (FMT __VA_OPT__ (,) __VA_ARGS__); \ | ||
| 53 | exit (EXIT_FAILURE); \ | ||
| 54 | } while (0) | ||
| 55 | #else | ||
| 56 | #define ASSERT_MSG(EXP, FMT, ...) NOP () | ||
| 57 | #endif | ||
| 58 | |||
| 59 | struct cmmm__sv mmap_whole (int fd); | ||
| 60 | struct cmmm__sv read_until_eof (ARENA, int fd); | ||
| 61 | |||
| 62 | #endif // INCLUDED_UTILS_H | ||
| 63 | |||
| 64 | // examples/utils.c ends here | ||
