Terrace/packages/c/parser.h

56 lines
2.6 KiB
C

#ifndef TERRACE_PARSER_H
#define TERRACE_PARSER_H
// Holds the parsed information from each line.
typedef struct terrace_linedata_s {
// Which character is being used for indentation. Avoids having to specify it on each terrace_parse_line call.
char indent;
// How many indent characters are present in the current line before the first non-indent character.
unsigned int level;
// The number of characters before the start of the line's "head" section.
// (Normally the same as `level`)
unsigned int offsetHead;
// The number of characters before the start of the line's "tail" section.
unsigned int offsetTail;
} terrace_linedata_t;
/**
* Initialize a terrace_linedata struct with default values to pass to terrace_parse_line()
* @param {const char} indent The character to use for indenting lines. ONLY ONE CHARACTER IS CURRENTLY PERMITTED.
* @returns {terrace_linedata_t} A linedata struct with the specified indent character and all other values initialized to 0.
*/
terrace_linedata_t terrace_create_linedata(const char indent) {
terrace_linedata_t line_data = { .indent = indent, .level = 0, .offsetHead = 0, .offsetTail = 0 };
return line_data;
}
/**
* Core Terrace parser function, sets level, offsetHead, and offsetTail in a terrace_linedata struct based on the current line.
* @param char* line A pointer to the line to parse as a C-style string. Shouldn't end with a newline.
* @param terrace_linedata_t* lineData A pointer to the terrace_linedata_t struct to store information about the current line in.
*/
void terrace_parse_line(const char* line, terrace_linedata_t* lineData) {
// Empty lines are nullptr/0 as they have no characters. (The newline character should be stripped off.)
// Special case handling for these allows them to be parsed extra quickly.
if (!line) {
// Empty lines are treated as having the same level as the previous line, so lineData->line is not updated.
lineData->offsetHead = 0;
lineData->offsetTail = 0;
} else {
// Count the number of indent characters in the current line.
unsigned int level = 0;
while (line[level] == lineData->indent) ++level;
lineData->level = level;
// Set offsetHead and offsetTail to level to start with.
// offsetHead should always be equal to level, and offsetTail will always be equal to or greater than level.
lineData->offsetHead = level;
lineData->offsetTail = level;
// Increment offsetTail until we encounter a space character (start of tail) or reach EOL (no tail present).
while (line[lineData->offsetTail] && line[lineData->offsetTail] != ' ') ++lineData->offsetTail;
}
}
#endif