|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to `makeup_c` are documented in this file. |
| 4 | + |
| 5 | +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), |
| 6 | +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
| 7 | + |
| 8 | +## [1.0.0] - 2026-05-08 |
| 9 | + |
| 10 | +A near-complete rewrite of the lexer's behaviour to follow C23 (ISO/IEC 9899:2024) |
| 11 | +and shed the Elixir-isms inherited from the original lexer template. The token |
| 12 | +shape (Makeup token tuples) and public API (`Makeup.Lexers.CLexer.lex/2`) are |
| 13 | +unchanged; classifications of individual tokens are not. |
| 14 | + |
| 15 | +### Added |
| 16 | + |
| 17 | +- **C23 keywords**: `constexpr`, `nullptr`, `static_assert`, `thread_local`, |
| 18 | + `typeof`, `typeof_unqual`, `restrict`, plus the underscore-capital |
| 19 | + alternative spellings (`_Atomic`, `_BitInt`, `_Generic`, `_Bool`, |
| 20 | + `_Complex`, `_Imaginary`, `_Noreturn`, `_Static_assert`, `_Thread_local`, |
| 21 | + `_Alignas`, `_Alignof`, `_Decimal32`/`_Decimal64`/`_Decimal128`). |
| 22 | +- **Standard library typedefs** highlighted as types: stdint exact-, |
| 23 | + least-, and fast-width forms (`int8_t`, `int_least16_t`, `int_fast32_t`, |
| 24 | + …), `intmax_t`/`uintmax_t`, `intptr_t`/`uintptr_t`, `size_t`/`ssize_t`/ |
| 25 | + `ptrdiff_t`/`max_align_t`/`errno_t`, the C23 `char8_t` and `nullptr_t`, |
| 26 | + and the ubiquitous `FILE` and `va_list`. |
| 27 | +- **Standard predefined macros** as `:name_builtin_pseudo`: `__func__` |
| 28 | + (C99), `__FILE__`, `__LINE__`, `__DATE__`, `__TIME__`, `__STDC__`, |
| 29 | + `__STDC_VERSION__`, `__STDC_HOSTED__`, `__STDC_UTF_16__`, |
| 30 | + `__STDC_UTF_32__`, `__VA_ARGS__`, the C23 additions `__VA_OPT__` / |
| 31 | + `__has_include` / `__has_c_attribute` / `__has_embed`, and the GCC/ |
| 32 | + Clang extensions `__FUNCTION__` / `__PRETTY_FUNCTION__`. |
| 33 | +- **Integer suffixes**: `u`/`U`, `l`/`L`, `ll`/`LL`, and the C23 |
| 34 | + `wb`/`WB` (`_BitInt`) suffix in any valid combination. |
| 35 | +- **Float suffixes**: `f`/`F`, `l`/`L`, the C23 fixed-width forms |
| 36 | + `f16`/`f32`/`f64`/`f128` (and uppercase), `bf16`/`BF16`, and the |
| 37 | + decimal forms `df`/`dd`/`dl` (and uppercase). |
| 38 | +- **Float literal forms** previously unrecognised: `5.`, `.5`, `1e10` |
| 39 | + (no decimal point but exponent), and full **hex floats** |
| 40 | + (`0x1.fp10`, `0x1p-3`, `0x.fp+5`). |
| 41 | +- **C23 digit separator** `'` between any two digits in a numeric |
| 42 | + constant (`1'000`, `0xFFFF'FFFF`, `1'234.567'89`). |
| 43 | +- **Character literals** as `:string_char`, including the encoding |
| 44 | + prefixes `L`, `u`, `U`, `u8` (C23). Octal (`\NNN`), hex (`\xNN`), |
| 45 | + and Unicode (`\u`, `\U`) escapes inside char and string literals. |
| 46 | +- **String literal prefixes**: `L"…"`, `u"…"`, `U"…"`, `u8"…"`. |
| 47 | +- **All C23 preprocessor directives**, including `#elifdef`, |
| 48 | + `#elifndef`, `#embed`, `#warning`. Whitespace is now allowed between |
| 49 | + `#` and the directive name (`# include`, `#\tdefine`). |
| 50 | +- **`#include <header.h>`** is collapsed into a single `:string` token |
| 51 | + by a postprocess pass; `<` and `>` outside an `#include` line stay |
| 52 | + ordinary operators. |
| 53 | +- **C23 `[[…]]` attribute sequences** as `:name_decorator` |
| 54 | + (`[[nodiscard]]`, `[[gnu::aligned(8)]]`, …). |
| 55 | +- **CHANGELOG.md** (this file) and a comprehensive test suite (~80 |
| 56 | + tests covering whitespace, comments, all numeric forms, all |
| 57 | + literal forms, every keyword class, attributes, and the |
| 58 | + preprocessor) modelled on `makeup_erlang`. |
| 59 | +- **Basic C++ keyword coverage** retained from the original lexer so |
| 60 | + the same tokenizer works on `.cpp` / `.h` files: `class`, |
| 61 | + `namespace`, `template`, `typename`, `try`/`catch`/`throw`, the |
| 62 | + `co_*` coroutine keywords, `*_cast` operators, `public`/`private`/ |
| 63 | + `protected`, etc. Highlighted purely as `:keyword`; no template-, |
| 64 | + namespace-, or type-aware logic. |
| 65 | + |
| 66 | +### Changed |
| 67 | + |
| 68 | +- **Elixir requirement**: bumped to `~> 1.14` from `~> 1.4`. |
| 69 | +- **CI**: Travis replaced with GitHub Actions, matrixed across Elixir |
| 70 | + 1.14 / OTP 24 (oldest supported) and Elixir 1.19 / OTP 28 (newest, |
| 71 | + with lint stage running `mix format --check-formatted`, |
| 72 | + `mix deps.unlock --check-unused`, and `mix compile --warnings-as-errors`). |
| 73 | +- **Source layout** moved to the standard makeup arrangement: |
| 74 | + `lib/makeup_c.ex` → `lib/makeup/lexers/c_lexer.ex`, plus the |
| 75 | + supporting modules under `lib/makeup/lexers/c_lexer/`. Tests |
| 76 | + moved to `test/makeup/c_lexer/`. |
| 77 | +- **Identifier rule** is now C-correct: `[A-Za-z_][A-Za-z0-9_]*`. The |
| 78 | + uppercase-vs-lowercase split (which routed names like `NULL` to |
| 79 | + `:name_constant` and so prevented postprocessor classification) is |
| 80 | + gone; both cases produce `:name` and the postprocessor decides. |
| 81 | +- **Octal numbers** use the traditional C `0` prefix (`0755`); the |
| 82 | + C23 alternative `0o`/`0O` form is also accepted. Plain `0` stays |
| 83 | + a decimal integer. |
| 84 | +- **Whitespace** now includes `\t` and `\v` per C23 6.4 (was missing |
| 85 | + both, so tabs in source produced `:error` tokens). |
| 86 | +- **`nullptr`** is classified as `:keyword_constant` (alongside |
| 87 | + `true`/`false`/`NULL`) rather than `:keyword`, matching its |
| 88 | + semantic role as a predefined constant. |
| 89 | +- **`void`** is classified as `:keyword_type` (was incorrectly listed |
| 90 | + under constants). |
| 91 | + |
| 92 | +### Removed |
| 93 | + |
| 94 | +- **Elixir-only combinators**: the `?x`/`?\x` "char literal" forms, |
| 95 | + the `key:` / `"key":` Elixir keyword-list combinators, and the |
| 96 | + trailing-`?`/`!` allowance in identifiers. |
| 97 | +- **Leading-underscore-as-comment rule**: identifiers like `_foo` are |
| 98 | + no longer rendered as `:comment`. In C a leading underscore is |
| 99 | + reserved to the implementation but still forms an ordinary |
| 100 | + identifier. |
| 101 | +- **`@operator_word`** (the `<iso646.h>` macros `and`, `or`, `not`, |
| 102 | + `xor`, `and_eq`, `or_eq`, `xor_eq`, `not_eq`, `bitand`, `bitor`). |
| 103 | + Those are *macros* expanding to C operators, not C operators |
| 104 | + themselves; they now lex as plain `:name`. (`compl` keeps its |
| 105 | + `:keyword` classification because it's also a C++ alternative- |
| 106 | + token keyword.) |
| 107 | +- **`alignoif`** (typo for `alignof`) and **`byte`** (not a C type) |
| 108 | + removed from the keyword/type lists. |
| 109 | +- **`_` digit separator**: was Elixir; replaced by the C23 `'` |
| 110 | + separator above. |
| 111 | +- **`0o`-only octal prefix**: replaced by the standard `0`-prefix |
| 112 | + form (with `0o`/`0O` accepted as a C23-compatible alternative). |
| 113 | +- **Dead `Makeup.Lexers.CLexer.Helper` module**: all of its functions |
| 114 | + (`with_optional_separator`, `escape_delim`, `sigil`, `escaped`, |
| 115 | + `keyword_matcher`) were either Elixir-only or unused. |
| 116 | + |
| 117 | +### Fixed |
| 118 | + |
| 119 | +- Tabs and form feeds in source no longer produce `:error` tokens. |
| 120 | +- The deprecated uppercase-sigil escape (`~W( ( \) [ ] { })`) that |
| 121 | + caused warnings on Elixir 1.19 is replaced by a list literal. |
| 122 | + |
| 123 | +## [0.1.1] - 2020-10-03 |
| 124 | + |
| 125 | +- Mix file updated to point to the new repository location. |
| 126 | + |
| 127 | +## [0.1.0] - 2020-09-26 |
| 128 | + |
| 129 | +- Initial release. Basic C lexer covering keywords, types, |
| 130 | + numbers (decimal/hex/binary/float), strings, single- and |
| 131 | + multi-line comments, operators, and preprocessor directives. |
0 commit comments