|
CX Framework
Cross-platform C utility framework
|
Modules | |
| Literals and Characters | |
| Extraction | |
| Typed Values | |
Data Structures | |
| struct | strscan |
Macros | |
| #define | strscInit(sc, s, ...) _strscInit(sc, s, opt_flags(__VA_ARGS__)) |
Typedefs | |
| typedef struct strscan | strscan |
Enumerations | |
| enum | STRSC_FLAGS { STRSC_CaseInsensitive = 0x01 } |
| Flags controlling how a scanner matches. More... | |
Functions | |
| bool | strscFinish (strscan *sc) |
| bool | strscDone (strscan *sc) |
| int32 | strscMark (strscan *sc) |
| void | strscRewind (strscan *sc, int32 mark) |
| bool | strscSeek (strscan *sc, int32 pos) |
| void | strscFail (strscan *sc) |
A cursor that walks a string left to right, matching and extracting pieces as it goes. This is the low-level half of cx's parsing support: use it for grammars that a pattern cannot express, and use pattern matching for everything else.
A scanner carries an ok flag that starts true and turns false the first time something does not match. Once it is false every later call does nothing and returns false immediately. That means a grammar can be written as a straight run of calls with a single check at the end, instead of an if around every step:
strscMark() records the current position and strscRewind() returns to it. Rewinding also clears the error flag, so it is how alternatives are tried:
The scanner borrows the string rather than holding a reference to it, so the string must stay alive for as long as the scanner is in use. Extracted pieces are ordinary strings that the caller owns and must destroy.
| #define strscInit | ( | sc, | |
| s, | |||
| ... | |||
| ) | _strscInit(sc, s, opt_flags(__VA_ARGS__)) |
void strscInit(strscan *sc, strref s, [flags])
Starts a scan at the beginning of a string.
The string is borrowed, so it must outlive the scanner.
| sc | Scanner to initialize |
| s | String to scan (NULL scans an empty string) |
| ... | (flags) Optional: STRSC_FLAGS |
Example:
String scanner state
Read pos, errpos, ok and s freely; change the position with strscSeek() or strscRewind() rather than by assignment.
| enum STRSC_FLAGS |
|
inline |
Tests whether the cursor has reached the end of the string.
| sc | Scanner to test |
| void strscFail | ( | strscan * | sc | ) |
Marks the scan as failed at the current position.
For a check the scanner itself cannot make - a day number that parsed fine but is out of range, say. Does nothing if the scan has already failed.
| sc | Scanner to fail |
| bool strscFinish | ( | strscan * | sc | ) |
Ends a scan and reports whether everything matched.
Does not check that the whole string was consumed - call strscDone() before this if the grammar requires that.
The scanner lets go of the string here, so nothing may be matched or extracted afterward; ok and errpos are still set, which is what an error report needs.
| sc | Scanner to finish |
|
inline |
int32 strscMark(strscan *sc)
Records the current position so strscRewind() can come back to it. Currently is the same as reading pos, but this may change so do not depend on it.
| sc | Scanner to inspect |
| void strscRewind | ( | strscan * | sc, |
| int32 | mark | ||
| ) |
Returns to a recorded position and clears the error flag.
This is how alternatives are tried: mark, attempt one form, and rewind to attempt another. Clearing the error is the point - a failed attempt that has been rewound never happened.
| sc | Scanner to reposition |
| mark | Position from strscMark() |
| bool strscSeek | ( | strscan * | sc, |
| int32 | pos | ||
| ) |
Moves the cursor to an absolute offset.
Unlike strscRewind(), this does not clear the error flag, and it fails if the offset is outside the string.
| sc | Scanner to reposition |
| pos | Byte offset to move to |