Skip to content

Commit 10c0a06

Browse files
committed
Add basic documentation about the entire library
1 parent b3a8a56 commit 10c0a06

1 file changed

Lines changed: 190 additions & 0 deletions

File tree

README.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,193 @@ Edit your `CMakeLists.txt`:
2828
add_subdirectory(modules/x4)
2929
target_link_libraries(my_app PUBLIC Iris::X4)
3030
```
31+
32+
33+
## Terminology
34+
35+
### "attribute"
36+
37+
An *attribute* is the value produced by a successful parse. It represents the semantic result of a parser after it consumes input, and is propagated through combinators, directives, and rules according to their transformation rules. Attributes may be primitive values, containers, or user-defined types, and can be constructed, transformed, or suppressed depending on the parser expression.
38+
39+
Phrases like "the attribute type of a parser" usually refer to the value type of the attribute produced by that parser class.
40+
41+
### "semantic action"
42+
43+
A *semantic action* is a user-provided invocable object (usually a lambda) that is executed when a parser successfully matches its input. It is used to inspect, transform, or validate the parsed result, and may optionally influence control flow by accepting or rejecting the match. Semantic actions operate on the current parsing context and the attribute produced by the parser, allowing fine-grained post-processing of successful parses.
44+
45+
The primary syntax for attaching a semantic action is `p.on_match(f)`, where `f` is invoked after `p` matches. The callable may observe the matched attribute, access contextual information, and optionally return a boolean to either accept the result or force the parser to treat the match as a failure, enabling backtracking when appropriate.
46+
47+
The signature of a semantic action is `[](auto&& ctx) { /* ... */ }`.
48+
49+
> While highly flexible and convenient, **it is generally discouraged to introduce semantic actions prematurely as part of a language's syntax definition,** since most grammars can be expressed purely through combinations of concrete parsers (typically `x4::rule` parsers) when they are properly structured.
50+
>
51+
> The primary intended use of semantic actions is to handle cases that require ad hoc transformation, such as constructing a binary operator object through a more complex algorithm like precedence climbing.
52+
53+
54+
## Directory Structure
55+
56+
Each parser header is organized into subdirectories as needed, but there are several special directories that contain very specific kinds of components. These are described below.
57+
58+
#### `core/`
59+
60+
The core components of X4. In contrast to the facilities in the `traits/` directory, the core components are not intended to be user-customizable.
61+
62+
> **Note for contributors:** every non-detail header in this directory must start with `#include <iris/config.hpp>`.
63+
64+
#### `traits/`
65+
66+
Customizable type traits that allow user-defined types to participate in parser logic or attribute processing. A trait may alter parser semantics, type classification, compatibility checks, attribute propagation, storage, conversion, or transformation.
67+
68+
#### `operator/`
69+
70+
Directives or combinators that use overloaded C++ operators as their composition syntax. They form the fundamental grammar-composition vocabulary, including sequence, alternative, repetition, optionality, predicates, difference, and list composition.
71+
72+
#### `directive/`
73+
74+
Parser adapters or combinators that operate on one or more subject parsers and modify parsing behavior, context, control flow, repetition, or interpretation. They do not use special C++ operators for composition, but normally use subscript syntax such as `directive[p]` to express the combination. Facilities whose primary purpose is value production or attribute representation may instead belong to `attribute/`.
75+
76+
#### Other Subdirectories
77+
78+
Remaining facilities that do not fit the categories described above are organized into additional subdirectories when a clear semantic grouping warrants it.
79+
80+
81+
## Quick Reference
82+
83+
The descriptions below focus on recognition behavior and omit many details concerning attribute propagation and customization.
84+
85+
### Operators
86+
87+
| Syntax | Meaning |
88+
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
89+
| `a \| b` | Try `a`. If it fails normally, restore the input position and try `b`. An expectation failure prevents the fallback to `b`. |
90+
| `a >> b` | Parse `a`, followed by `b`. If either parser fails normally, restore the input position to the beginning of the sequence. |
91+
| `a > b` | Parse `a`, followed by an expected `b`. Equivalent to `a >> expect[b]`. Failure of `b` records an expectation failure and prevents ordinary backtracking. |
92+
| `*p` | Parse zero or more occurrences of `p`. |
93+
| `+p` | Parse one or more occurrences of `p`. |
94+
| `p % d` | Parse one or more occurrences of `p`, separated by `d`. |
95+
| `a - b` | Parse `a` only when `b` does not match at the same input position. The test of `b` does not consume input. |
96+
| `-p` | Parse zero or one occurrence of `p`. |
97+
| `&p` | Succeed when `p` matches, without consuming input or producing its attribute. |
98+
| `!p` | Succeed when `p` does not match, without consuming input or producing an attribute. |
99+
100+
### Major Directives
101+
102+
These facilities commonly appear in production language grammars.
103+
104+
| Syntax | Meaning |
105+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
106+
| `p.on_match(f)` | After `p` matches, invoke the semantic action `f`. The action may inspect or modify the parsing context and may reject the match. |
107+
| `expect[p]` | Parse `p`. If it fails, record an expectation failure that prevents ordinary backtracking and alternative recovery. Usually invoked indirectly via the `a > b` syntax. |
108+
| `lexeme[p]` | Perform the normal pre-skip, then parse `p` with automatic skipping disabled inside it. |
109+
| `with<ID>(value)[p]` | Bind `value` to the context id `ID` while parsing `p`.<br>The instance be fetched via `x4::get<ID>(ctx)` in semantic action. |
110+
| `with_local<T>[p]` | Create a value-initialized local value of type `T` for each invocation of `p` and bind it to the context id `ID`. If `ID` is omitted, the default local-variable context id (`x4::contexts::local_var`) is used.<br>The instance be fetched via `x4::get<ID>(ctx)` or `x4::_local_var(ctx)`, respectively, in semantic action. |
111+
112+
### Minor Directives
113+
114+
These facilities are used less frequently in ordinary language grammars.
115+
116+
| Syntax | Meaning |
117+
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
118+
| `omit[p]` | Parse `p`, but suppress its attribute. |
119+
| `skip(s)[p]` | Parse `p` using `s` as its active skipper, replacing the previously active skipper within the directive. |
120+
| `no_skip[p]` | Parse `p` without performing a pre-skip and with automatic skipping disabled inside it. Most ordinary contiguous-token parsing can instead use `lexeme[p]`. |
121+
| `no_case[p]` | Apply case-insensitive character and string comparison while parsing `p`. |
122+
| `matches[p]` | Attempt to parse `p` and expose the result as `bool`: `true` when `p` matches and `false` when it fails normally. |
123+
| `repeat(n)[p]` | Parse exactly `n` occurrences of `p`. |
124+
| `repeat(min, max)[p]` | Parse between `min` and `max` occurrences of `p`, inclusive. |
125+
| `repeat(min, x4::repeat_inf)[p]` | Parse at least `min` occurrences of `p`, with no upper limit. |
126+
| `without<IDs...>[p]` | Remove every context entry whose key is one of `IDs...` while parsing `p`.<br>Useful for sanitizing the context type correlated with the `x4::rule` type required by `IRIS_X4_INSTANTIATE`. |
127+
128+
### Attribute Facilities
129+
130+
| Syntax | Meaning |
131+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
132+
| `as<T>(p)` | Force `p` to expose `T` as its attribute type. When the outer destination has another compatible type, parse into a temporary `T` and move the result into the destination. |
133+
| `fixed_value(value)` | Always succeed without consuming input and copy the stored `value` into the exposed attribute. |
134+
| `reset_value<T>` | Always succeed without consuming input and reset the exposed attribute. Containers are cleared; other values are assigned a value-initialized instance. |
135+
| `unique_ptr(p)` | Expose a `std::unique_ptr` attribute and parse `p` into its pointee. Deduce the pointee type from the attribute of `p`. |
136+
| `unique_ptr<T>(p)` | Expose a `std::unique_ptr<T>` attribute and parse `p` into its pointee. An optional deleter type `D` may also be specified. |
137+
| `shared_ptr(p)` | Expose a `std::shared_ptr` attribute and parse `p` into its pointee. Deduce the pointee type from the attribute of `p`. |
138+
| `shared_ptr<T>(p)` | Expose a `std::shared_ptr<T>` attribute and parse `p` into its pointee. An optional deleter type `D` may also be specified. |
139+
140+
### Primitives
141+
142+
| Syntax | Meaning |
143+
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
144+
| `eol` | Match and consume an end-of-line sequence: `"\n"`, `"\r"`, or `"\r\n"`. |
145+
| `eoi` | Succeed only when the input has been exhausted. |
146+
| `eps` | Always succeed without consuming input. |
147+
| `eps(cond)` | Succeed without consuming input when `cond` is `true`. |
148+
| `eps(f)` | Lazily invoke `f` and succeed without consuming input when it returns `true`. The callable may accept the parsing context or no arguments. |
149+
150+
### Character and String Parsers
151+
152+
| Syntax | Meaning |
153+
| ----------------- | -------------------------------------------------------------------------------------------- |
154+
| `lit('a')` | Match the character `'a'` without producing an attribute. |
155+
| `lit("str")` | Match the exact string `"str"` without producing an attribute. |
156+
| `char_` | Match any valid character and expose the matched character. |
157+
| `char_('a')` | Match the character `'a'` and expose it. |
158+
| `char_("abc")` | Match one character from the set `{'a', 'b', 'c'}` and expose it. |
159+
| `char_("a-zA-Z_")` | Match and expose one character from the specified character set. A hyphen defines an inclusive range, so this example matches an alphabet or underscore. |
160+
| `char_('a', 'z')` | Match one character in the inclusive range `'a'` through `'z'` and expose it. |
161+
| `~char_(...)` | Match and expose one character not accepted by the enclosed character parser, set, or range. |
162+
| `string("str")` | Match the exact string `"str"` and expose the matched string. |
163+
164+
### Numeric Parsers
165+
166+
#### Boolean Parsers
167+
168+
| Syntax | Meaning |
169+
| -------- | ---------------------------------------------------------------------- |
170+
| `bool_` | Match `"true"` or `"false"` and expose the corresponding `bool` value. |
171+
| `true_` | Match `"true"` and expose `true`. |
172+
| `false_` | Match `"false"` and expose `false`. |
173+
174+
#### Signed Integer Parsers
175+
176+
| Syntax | Meaning |
177+
| ----------- | --------------------------------------------------------------- |
178+
| `short_` | Parse a base-10 signed integer and expose it as `short`. |
179+
| `int_` | Parse a base-10 signed integer and expose it as `int`. |
180+
| `long_` | Parse a base-10 signed integer and expose it as `long`. |
181+
| `long_long` | Parse a base-10 signed integer and expose it as `long long`. |
182+
| `int8` | Parse a base-10 signed integer and expose it as `std::int8_t`. |
183+
| `int16` | Parse a base-10 signed integer and expose it as `std::int16_t`. |
184+
| `int32` | Parse a base-10 signed integer and expose it as `std::int32_t`. |
185+
| `int64` | Parse a base-10 signed integer and expose it as `std::int64_t`. |
186+
187+
#### Unsigned Integer Parsers
188+
189+
| Syntax | Meaning |
190+
| ------------ | ----------------------------------------------------------------------- |
191+
| `ushort_` | Parse a base-10 unsigned integer and expose it as `unsigned short`. |
192+
| `uint_` | Parse a base-10 unsigned integer and expose it as `unsigned int`. |
193+
| `ulong_` | Parse a base-10 unsigned integer and expose it as `unsigned long`. |
194+
| `ulong_long` | Parse a base-10 unsigned integer and expose it as `unsigned long long`. |
195+
| `uint8` | Parse a base-10 unsigned integer and expose it as `std::uint8_t`. |
196+
| `uint16` | Parse a base-10 unsigned integer and expose it as `std::uint16_t`. |
197+
| `uint32` | Parse a base-10 unsigned integer and expose it as `std::uint32_t`. |
198+
| `uint64` | Parse a base-10 unsigned integer and expose it as `std::uint64_t`. |
199+
| `bin` | Parse a base-2 unsigned integer and expose it as `unsigned int`. |
200+
| `oct` | Parse a base-8 unsigned integer and expose it as `unsigned int`. |
201+
| `hex` | Parse a base-16 unsigned integer and expose it as `unsigned int`. |
202+
203+
#### Real Number Parsers
204+
205+
| Syntax | Meaning |
206+
| ------------- | ---------------------------------------------------------- |
207+
| `float_` | Parse a signed real number and expose it as `float`. |
208+
| `double_` | Parse a signed real number and expose it as `double`. |
209+
| `long_double` | Parse a signed real number and expose it as `long double`. |
210+
211+
### Context Fetchers
212+
213+
The following function objects retrieve commonly used values from the parsing context (usually via a semantic action). Each fetcher returns the context entry itself, normally by reference, and is available only when the corresponding entry exists in the current context.
214+
215+
| Syntax | Meaning |
216+
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
217+
| `_attr(ctx)` | Return the attribute associated with the current semantic action. This is the attribute instance produced by the parser `p` on the expression `p.on_match(f)`. It is available only when that parser exposes a non-`unused_type` attribute. Equivalent to `x4::get<x4::contexts::attr>(ctx)`. |
218+
| `_rule_var(ctx)` | Return the attribute variable of the innermost active `x4::rule` invocation. In a recursive rule, this always refers to the current recursive invocation rather than an outer invocation. It does not refer to an attribute variable introduced by `as<T>(p)`. Equivalent to `x4::get<x4::contexts::rule_var>(ctx)`. |
219+
| `_local_var(ctx)` | Return the innermost local variable created by `with_local<T>[p]` using the default `x4::contexts::local_var` context id. When `with_local<T, ID>[p]` uses a custom key, retrieve the value with `x4::get<ID>(ctx)` instead. Equivalent to `x4::get<x4::contexts::local_var>(ctx)`. |
220+
| `_as_var(ctx)` | Return the attribute variable managed by the innermost active `as<T>(p)` facility. Semantic actions inside `p` can use this fetcher to access the value being constructed for the enclosing `as<T>` parser. Equivalent to `x4::get<x4::contexts::as_var>(ctx)`. |

0 commit comments

Comments
 (0)