diff --git a/docs/.eleventyignore b/docs/.eleventyignore new file mode 100644 index 0000000..4be6680 --- /dev/null +++ b/docs/.eleventyignore @@ -0,0 +1 @@ +/**/*.inc.tce diff --git a/docs/src/_includes/nodes/Include.njk b/docs/src/_includes/nodes/Include.njk new file mode 100644 index 0000000..0a3a1bd --- /dev/null +++ b/docs/src/_includes/nodes/Include.njk @@ -0,0 +1,7 @@ +{% from "./Node.njk" import Node %} + +{% macro render(node, page) %} + {% for child in node.children %} + {{ Node(child.type, child, page) }} + {% endfor %} +{% endmacro %} diff --git a/docs/src/docs/c.tce b/docs/src/docs/c.tce deleted file mode 100644 index dc5b45d..0000000 --- a/docs/src/docs/c.tce +++ /dev/null @@ -1,435 +0,0 @@ -layout layout.njk -title C Documentation - Terrace -description - C language documentation for the Terrace programming language - -Section light - class flex flex-col md:flex-row gap-16 - - Block - class w-full lg:w-1/3 - TableOfContents - - Block - Heading 1 Terrace C Documentation - class -ml-2 - - Markdown - Documentation is available for the following languages: - - [C](/docs/c/) - 75% Complete - - [JavaScript](/docs/javascript/) - 75% Complete - - [Python](/docs/python/) - 0% Complete - - Heading 2 Getting Started - class mt-12 mb-6 - Markdown - The terrace parser is distributed as a set of C header files.
- To use it, download and include the following files in your project tree: - - [parser.h](https://git.thederf.com/thederf/Terrace/src/branch/main/packages/c/parser.h) - Core terrace parser - - [document.h](https://git.thederf.com/thederf/Terrace/src/branch/main/packages/c/document.h) - (optional) Convenience functions for parsing of documents - - A simple example program using to read each line from stdin and output parser information, looking for a "title" key: - CodeBlock c - // Provides getline() for reading from stdin - #include - // Provides free() for deallocating the lines from getline() - #include - // Provides document API for interacting with Terrace files - #include "document.h" - - // Custom userData struct. Stores information needed - // by read_line below. - typedef struct read_line_container_s { - size_t bufsize; - } read_line_container_t; - - // A user-supplied function to read lines from stdin (or whichever data source you choose) - int read_line_from_stdin(char** line, void* userData) { - read_line_container_t* lineContainer = (read_line_container_t*) userData; - // Uses getline from the C stdlib to read the next line from stdin. - int num_chars_read = getline(line, &lineContainer->bufsize, stdin); - // Change trailing newline to null char. Terrace doesn't use trailing newlines - if (num_chars_read > 0) (*line)[num_chars_read - 1] = '\0'; - // Return the number of charaters read to the document parser. - return num_chars_read; - } - - int main(int argc, char *argv[]) { - read_line_container_t read_line_information = { .bufsize = 64 }; - // Initialize the terrace document with the line reader function created above. - terrace_document_t doc = terrace_create_document(' ', &read_line_from_stdin, &read_line_information); - - // Loop over every line in the document. - while(terrace_next(&doc, -1)) { - // > Replace with your custom line handling code. - - // Print the line and level to demonstrate the terrace_level and terrace_line functions. - printf("| level %u | line %s |", terrace_level(&doc), terrace_line(&doc, -1)); - // If one of the lines starts with "title", output it. - if (terrace_match(&doc, "title")) { - printf("Title: %s |", terrace_tail(&doc)); - } - }; - - // Free allocated line memory - free(line); - - return 0; - } - - Markdown - - Heading 2 Core API - class mt-12 - Markdown - **Note:** The Core API is designed for maximum portability and is not intended to be directly consumed. - - For most projects you'll want to use the [Document API](#document-api) instead. - It provides an ergonomic wrapper around the Core API and lets you focus on parsing - your documents. - - Heading 3 terrace_linedata_t - class mb-4 mt-12 - Markdown - This struct holds information about each line as it is parsed. Mutated each time [terrace_parse_line()](#terrace-parse-line) is called. Not intended to be used directly. - Use the relevant `terrace_` functions from the [Document API](#document-api) instead. - CodeBlock c - // 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; - - Heading 3 terrace_create_linedata() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | indent | const char | The character used for indentation in the document. Only a single character is permitted. - | **@returns** | [terrace_linedata_t](#terrace-linedatat) | A terrace_linedata_t struct with the specified indent character and all other values initialized to 0. - - Initialize a [terrace_linedata](#terrace-linedatat) struct with default values to pass to [terrace_parse_line()](#terrace-parse-line). - CodeBlock c - // Call Signature - terrace_linedata_t terrace_create_linedata(const char indent) - Heading 3 terrace_parse_line() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | line | char* | A pointer to the line to parse as a C-style string. Shouldn't end with a newline. - | lineData | [terrace_linedata_t](#terrace-linedatat)* | A pointer to the terrace_linedata_t struct to store information about the current line in. - - Core Terrace parser function, sets `level`, `offsetHead`, and `offsetTail` in a [terrace_linedata](#terrace-linedatat) struct based on the current line. - CodeBlock c - // Call Signature - void terrace_parse_line(const char* line, terrace_linedata_t* lineData) - - Heading 2 Document API - class mt-12 - - Heading 3 terrace_document_t - class mb-4 mt-12 - Markdown - Tracks state of a document while being parsed. - Obtained from [terrace_create_document()](#terrace-create-document) below - CodeBlock c - // Type Definition - typedef struct terrace_document_s { - // == Internal State == // - unsigned int _repeatCurrentLine; - // Current line being read - char* _currentLine; - - // == External Information == // - // Embedded line data struct. Holds information about the current parsed line - terrace_linedata_t lineData; - // Custom data passed to the readline function - void* userData; - /** - * Line reader function, provided by the user - * Needed to get the next line inside of `terrace_next(doc)` - * @param {char**} line First argument is a pointer to `_currentLine`, above - * @param {void*} userData Second argument is `userData`, above - * @returns {int} The number of characters read, or -1 if no characters were read. - */ - int (*reader)(char** line, void* userData); - } terrace_document_t; - - Heading 3 terrace_create_document() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | indent | const char | The indent character to use. Generally a single space character. - | reader | int (\*reader)(char** line, void* userData) | A function pointer to a function that reads lines sequentially from a user-provided source. Receives a pointer to `lineData->_currLine`, and `userData`, supplied in the next argument. - | userData | void * | A user-supplied pointer to any state information needed by their reader function. Passed to `reader`each time it is called. - | **@returns** | [terrace_document_t](#terrace-documentt) | A state struct needed by the convenience functions below. - - Initializes the state needed for the convenience functions below. Takes a user-supplied `reader` function to read each line from a user-determined source. - CodeBlock c - // Call Signature - terrace_document_t terrace_create_document(const char indent, int (*reader)(char** line, void* userData), void* userData) - - Heading 3 terrace_next() - class mb-4 mt-12 - - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | levelScope | int | If set above -1, `next()` will return `0` when it encounters a line with a level at or below `levelScope` - | **@returns** | char | Returns `1` after parsing a line, or `0` if the document has ended or a line at or below `levelScope` has been encountered. - - Advances the current position in the terrace document and populates lineData - with the parsed information from that line. - - Returns `1` after parsing the next line, or `0` upon reaching the end of the document. - If the `levelScope` parameter is not -1, `terrace_next()` will also return `0` when it encounters a line - with a level at or below `levelScope`. This allows you to iterate through subsections of a document. - - If a lower-level line was encountered, the following call to `terrace_next()` will repeat this line again. - This allows a child loop to look forward, determine that the next line will be outside its purview, - and return control to the calling loop transparently without additional logic. - - Intended to be used inside a while loop to parse a section of a Terrace document. - - CodeBlock c - // Call Signature - char terrace_next(terrace_document_t* doc, int levelScope) - - // Usage - while(terrace_next(doc, -1)) { - // Do something with each line. - } - - Heading 3 terrace_level() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | **@returns** | unsigned int | The indent level of the current line - - Returns the number of indent characters of the current line. - - Given the following document, `terrace_level(doc)` would return 0, 1, 2, and 5 respectively for each line. - CodeBlock terrace - block - block - block - block - - CodeBlock c - // Call Signature - unsigned int terrace_level(terrace_document_t* doc) - - // Usage - while(terrace_next(doc, -1)) { - printf("Indent Level: %u", terrace_level(doc)); - } - - Heading 3 terrace_line() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | startOffset | int | How many indent characters to skip before outputting the line contents. If set to -1, uses the current indent level. - | **@returns** | char* | The line contents starting from `startOffset` - - Get a string with the current line contents. - If `startOffset` is -1, skips all indent characters by default. Otherwise only skips the amount specified. - - Given the following document - CodeBlock terrace - root - sub-line - Markdown - - Calling `terrace_line(doc, -1)` on the second line returns "sub-line", trimming off the leading indent characters. - - Calling `terrace_line(doc, 0)` however, returns "    sub-line", with all four leading spaces. - - `startOffset`s other than `-1` are primarily used for parsing blocks that have literal indented multi-line text - - CodeBlock c - // Call Signature - char* terrace_line(terrace_document_t* doc, int startOffset) - - // Usage - while(terrace_next(doc, -1)) { - printf("Line with indent characters: %s", terrace_line(doc, 0)); - printf("Line without indent characters: %s", terrace_line(doc, -1)); - } - - Heading 3 terrace_head_length() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | **@returns** | unsigned int | The length of the `head` portion (first word) of a line - - Get the *length* of the first "word" of a line, - starting from the first non-indent character to the first space or end of the line - Often used for deciding how to parse a block. - - Because C uses NULL-terminated strings, we cannot easily slice a string to return something out of the middle. - Instead, `terrace_head_length()` provides the length of the head portion. - In combination with `doc->lineData.offsetHead`, you can copy the head section into a new string, - or use any number of `strn*` C stdlib functions to work with the head section without copying it. - - Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser - - Given the following line, `terrace_head_length(doc)` returns `5` - CodeBlock terrace - title An Important Document - CodeBlock c - // Call Signature - unsigned int terrace_head_length(terrace_document_t* doc) - - // Usage - while(terrace_next(doc, -1)) { - printf("Head length: %u", terrace_head_length(doc)); - } - - Heading 3 terrace_tail() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | **@returns** | char* | The remainder of the line following the `head` portion, with no leading space. - - Get a char pointer to everything following the first "word" of a line, - starting from the first character after the space at the end of `head`. - - Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser - - Given the following line, `terrace_tail(doc)` returns "An Important Document" - CodeBlock terrace - title An Important Document - CodeBlock c - // Call Signature - char* terrace_tail(terrace_document_t* doc) - - // Usage - while(terrace_next(doc, -1)) { - printf("Line tail: %s", terrace_tail(doc)); - } - - Heading 3 terrace_match() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. - | matchValue | const char* | A string to check against the line `head` for equality. - | **@returns** | char | A byte set to `0` if the head does not match, or `1`if it does match. - - Quickly check if the current line head matches a specified value. Useful in many document-parsing situations. - - Given the following line: - CodeBlock terrace - title An Important Document - Markdown - - `terrace_match(doc, "title")` returns `1` - - `terrace_match(doc, "somethingElse")` returns `0` - CodeBlock c - // Call Signature - char terrace_match(terrace_document_t* doc, const char* matchHead) - - // Usage - while(terrace_next(doc, -1)) { - printf("Does the line start with 'title': %d", terrace_match(doc, "title")); - } - - Heading 2 Recipes - class mt-12 - - Heading 3 Parse a single line - Markdown - Parses a single line into `line_data`, the prints the information from `line_data`. - CodeBlock c - #include "parser.h" - - int main(int argc, char *argv[]) { - char* line = "example line"; - // Create the line_data struct - terrace_linedata_t line_data; - // Set the indent character to a space - line_data.indent = ' '; - // Populates line_data level, offsetHead, and offsetTail from line - terrace_parse_line(line, &line_data); - - printf( - "level %u | indent %c | offsetHead %u | offsetTail %u\n", - line_data.level, - line_data.indent, - line_data.offsetHead, - line_data.offsetTail - ); - - return 0; - } - - Heading 3 Parse all lines from stdin - Markdown - Reads lines from stdin one-by-one and prints each line's `line_data`. - CodeBlock c - #include "parser.h" - // Depends on several cstdlib functions - #include - #include - #include - #include - - int main(int argc, char *argv[]) { - // Pointer to start of line - char *line = NULL; - // Initial size of the buffer to read into - // getline() will resize as needed - size_t bufsize = 128; - // How many characters have been read - ssize_t chars_read = 0; - - // Create the line_data struct - terrace_linedata_t line_data; - // Set the indent character to a space - line_data.indent = ' '; - - while (chars_read = getline(&line, &bufsize, stdin)) { - // If chars_read is -1, we've reached end of file. - if (chars_read == -1) break; - // getline returns lines with a trailing newline - // terrace_parse_line expects no trailing newline - // strip it off using strtok() - // (An odd solution, probably leaks memory) - char *terrace_line = strtok(line, "\n"); - terrace_parse_line(terrace_line, &line_data); - - printf( - "level %u | indent %c | offsetHead %u | offsetTail %u\n", - line_data.level, - line_data.indent, - line_data.offsetHead, - line_data.offsetTail - ); - }; - - // Free the buffer allocated by getline(). - free(line); - } - - Heading 2 Contributing - class mt-12 - -Section dark - Footer - class w-full diff --git a/docs/src/docs/c/core-api.inc.tce b/docs/src/docs/c/core-api.inc.tce new file mode 100644 index 0000000..a232415 --- /dev/null +++ b/docs/src/docs/c/core-api.inc.tce @@ -0,0 +1,52 @@ +Heading 2 Core API + class mt-12 +Markdown + **Note:** The Core API is designed for maximum portability and is not intended to be directly consumed. + + For most projects you'll want to use the [Document API](#document-api) instead. + It provides an ergonomic wrapper around the Core API and lets you focus on parsing + your documents. + +Heading 3 terrace_linedata_t + class mb-4 mt-12 +Markdown + This struct holds information about each line as it is parsed. Mutated each time [terrace_parse_line()](#terrace-parse-line) is called. Not intended to be used directly. + Use the relevant `terrace_` functions from the [Document API](#document-api) instead. +CodeBlock c + // 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; + +Heading 3 terrace_create_linedata() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | indent | const char | The character used for indentation in the document. Only a single character is permitted. + | **@returns** | [terrace_linedata_t](#terrace-linedatat) | A terrace_linedata_t struct with the specified indent character and all other values initialized to 0. + + Initialize a [terrace_linedata](#terrace-linedatat) struct with default values to pass to [terrace_parse_line()](#terrace-parse-line). +CodeBlock c + // Call Signature + terrace_linedata_t terrace_create_linedata(const char indent) +Heading 3 terrace_parse_line() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | line | char* | A pointer to the line to parse as a C-style string. Shouldn't end with a newline. + | lineData | [terrace_linedata_t](#terrace-linedatat)* | A pointer to the terrace_linedata_t struct to store information about the current line in. + + Core Terrace parser function, sets `level`, `offsetHead`, and `offsetTail` in a [terrace_linedata](#terrace-linedatat) struct based on the current line. +CodeBlock c + // Call Signature + void terrace_parse_line(const char* line, terrace_linedata_t* lineData) diff --git a/docs/src/docs/c/document-api.inc.tce b/docs/src/docs/c/document-api.inc.tce new file mode 100644 index 0000000..b363170 --- /dev/null +++ b/docs/src/docs/c/document-api.inc.tce @@ -0,0 +1,294 @@ +Heading 2 Document API + class mt-12 + +Heading 3 terrace_document_t + class mb-4 mt-12 +Markdown + Tracks state of a document while being parsed. + Obtained from [terrace_create_document()](#terrace-create-document) below +CodeBlock c + // Type Definition + typedef struct terrace_document_s { + // == Internal State == // + unsigned int _repeatCurrentLine; + // Current line being read + char* _currentLine; + + // == External Information == // + // Embedded line data struct. Holds information about the current parsed line + terrace_linedata_t lineData; + // Custom data passed to the readline function + void* userData; + /** + * Line reader function, provided by the user + * Needed to get the next line inside of `terrace_next(doc)` + * @param {char**} line First argument is a pointer to `_currentLine`, above + * @param {void*} userData Second argument is `userData`, above + * @returns {int} The number of characters read, or -1 if no characters were read. + */ + int (*reader)(char** line, void* userData); + } terrace_document_t; + +Heading 3 terrace_create_document() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | indent | const char | The indent character to use. Generally a single space character. + | reader | int (\*reader)(char** line, void* userData) | A function pointer to a function that reads lines sequentially from a user-provided source. Receives a pointer to `lineData->_currLine`, and `userData`, supplied in the next argument. + | userData | void * | A user-supplied pointer to any state information needed by their reader function. Passed to `reader`each time it is called. + | **@returns** | [terrace_document_t](#terrace-documentt) | A state struct needed by the convenience functions below. + + Initializes the state needed for the convenience functions below. Takes a user-supplied `reader` function to read each line from a user-determined source. +CodeBlock c + // Call Signature + terrace_document_t terrace_create_document(const char indent, int (*reader)(char** line, void* userData), void* userData) + +Heading 3 terrace_next() + class mb-4 mt-12 + +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | levelScope | int | If set above -1, `next()` will return `0` when it encounters a line with a level at or below `levelScope` + | **@returns** | char | Returns `1` after parsing a line, or `0` if the document has ended or a line at or below `levelScope` has been encountered. + + Advances the current position in the terrace document and populates lineData + with the parsed information from that line. + + Returns `1` after parsing the next line, or `0` upon reaching the end of the document. + If the `levelScope` parameter is not -1, `terrace_next()` will also return `0` when it encounters a line + with a level at or below `levelScope`. This allows you to iterate through subsections of a document. + + If a lower-level line was encountered, the following call to `terrace_next()` will repeat this line again. + This allows a child loop to look forward, determine that the next line will be outside its purview, + and return control to the calling loop transparently without additional logic. + + Intended to be used inside a while loop to parse a section of a Terrace document. + +CodeBlock c + // Call Signature + char terrace_next(terrace_document_t* doc, int levelScope) + + // Usage + while(terrace_next(doc, -1)) { + // Do something with each line. + } + +Heading 3 terrace_level() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | **@returns** | unsigned int | The indent level of the current line + + Returns the number of indent characters of the current line. + + Given the following document, `terrace_level(doc)` would return 0, 1, 2, and 5 respectively for each line. +CodeBlock terrace + block + block + block + block + +CodeBlock c + // Call Signature + unsigned int terrace_level(terrace_document_t* doc) + + // Usage + while(terrace_next(doc, -1)) { + printf("Indent Level: %u", terrace_level(doc)); + } + +Heading 3 terrace_line() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | startOffset | int | How many indent characters to skip before outputting the line contents. If set to -1, uses the current indent level. + | **@returns** | char* | The line contents starting from `startOffset` + + Get a string with the current line contents. + If `startOffset` is -1, skips all indent characters by default. Otherwise only skips the amount specified. + + Given the following document +CodeBlock terrace + root + sub-line +Markdown + - Calling `terrace_line(doc, -1)` on the second line returns "sub-line", trimming off the leading indent characters. + - Calling `terrace_line(doc, 0)` however, returns "    sub-line", with all four leading spaces. + + `startOffset`s other than `-1` are primarily used for parsing blocks that have literal indented multi-line text + +CodeBlock c + // Call Signature + char* terrace_line(terrace_document_t* doc, int startOffset) + + // Usage + while(terrace_next(doc, -1)) { + printf("Line with indent characters: %s", terrace_line(doc, 0)); + printf("Line without indent characters: %s", terrace_line(doc, -1)); + } + +Heading 3 terrace_head_length() + class mb-4 mt-12 +Markdown +| Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | **@returns** | unsigned int | The length of the `head` portion (first word) of a line + + Get the *length* of the first "word" of a line, + starting from the first non-indent character to the first space or end of the line + Often used for deciding how to parse a block. + + Because C uses NULL-terminated strings, we cannot easily slice a string to return something out of the middle. + Instead, `terrace_head_length()` provides the length of the head portion. + In combination with `doc->lineData.offsetHead`, you can copy the head section into a new string, + or use any number of `strn*` C stdlib functions to work with the head section without copying it. + + Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser + + Given the following line, `terrace_head_length(doc)` returns `5` +CodeBlock terrace + title An Important Document +CodeBlock c + // Call Signature + unsigned int terrace_head_length(terrace_document_t* doc) + + // Usage + while(terrace_next(doc, -1)) { + printf("Head length: %u", terrace_head_length(doc)); + } + +Heading 3 terrace_tail() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | **@returns** | char* | The remainder of the line following the `head` portion, with no leading space. + + Get a char pointer to everything following the first "word" of a line, + starting from the first character after the space at the end of `head`. + + Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser + + Given the following line, `terrace_tail(doc)` returns "An Important Document" +CodeBlock terrace + title An Important Document +CodeBlock c + // Call Signature + char* terrace_tail(terrace_document_t* doc) + + // Usage + while(terrace_next(doc, -1)) { + printf("Line tail: %s", terrace_tail(doc)); + } + +Heading 3 terrace_match() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | doc | [terrace_document_t*](#terrace-documentt) | A pointer to the current document state struct. + | matchValue | const char* | A string to check against the line `head` for equality. + | **@returns** | char | A byte set to `0` if the head does not match, or `1`if it does match. + + Quickly check if the current line head matches a specified value. Useful in many document-parsing situations. + + Given the following line: +CodeBlock terrace + title An Important Document +Markdown + - `terrace_match(doc, "title")` returns `1` + - `terrace_match(doc, "somethingElse")` returns `0` +CodeBlock c + // Call Signature + char terrace_match(terrace_document_t* doc, const char* matchHead) + + // Usage + while(terrace_next(doc, -1)) { + printf("Does the line start with 'title': %d", terrace_match(doc, "title")); + } + +Heading 2 Recipes + class mt-12 + +Heading 3 Parse a single line +Markdown + Parses a single line into `line_data`, the prints the information from `line_data`. +CodeBlock c + #include "parser.h" + + int main(int argc, char *argv[]) { + char* line = "example line"; + // Create the line_data struct + terrace_linedata_t line_data; + // Set the indent character to a space + line_data.indent = ' '; + // Populates line_data level, offsetHead, and offsetTail from line + terrace_parse_line(line, &line_data); + + printf( + "level %u | indent %c | offsetHead %u | offsetTail %u\n", + line_data.level, + line_data.indent, + line_data.offsetHead, + line_data.offsetTail + ); + + return 0; + } + +Heading 3 Parse all lines from stdin +Markdown + Reads lines from stdin one-by-one and prints each line's `line_data`. +CodeBlock c + #include "parser.h" + // Depends on several cstdlib functions + #include + #include + #include + #include + + int main(int argc, char *argv[]) { + // Pointer to start of line + char *line = NULL; + // Initial size of the buffer to read into + // getline() will resize as needed + size_t bufsize = 128; + // How many characters have been read + ssize_t chars_read = 0; + + // Create the line_data struct + terrace_linedata_t line_data; + // Set the indent character to a space + line_data.indent = ' '; + + while (chars_read = getline(&line, &bufsize, stdin)) { + // If chars_read is -1, we've reached end of file. + if (chars_read == -1) break; + // getline returns lines with a trailing newline + // terrace_parse_line expects no trailing newline + // strip it off using strtok() + // (An odd solution, probably leaks memory) + char *terrace_line = strtok(line, "\n"); + terrace_parse_line(terrace_line, &line_data); + + printf( + "level %u | indent %c | offsetHead %u | offsetTail %u\n", + line_data.level, + line_data.indent, + line_data.offsetHead, + line_data.offsetTail + ); + }; + + // Free the buffer allocated by getline(). + free(line); + } diff --git a/docs/src/docs/c/index.tce b/docs/src/docs/c/index.tce new file mode 100644 index 0000000..1ae1968 --- /dev/null +++ b/docs/src/docs/c/index.tce @@ -0,0 +1,88 @@ +layout layout.njk +title C Documentation - Terrace +description + C language documentation for the Terrace programming language + +Section light + class flex flex-col md:flex-row gap-16 + + Block + class w-full lg:w-1/3 + TableOfContents + + Block + Heading 1 Terrace C Documentation + class -ml-2 + + Markdown + Documentation is available for the following languages: + - [C](/docs/c/) - 75% Complete + - [JavaScript](/docs/javascript/) - 75% Complete + - [Python](/docs/python/) - 0% Complete + + Heading 2 Getting Started + class mt-12 mb-6 + Markdown + The terrace parser is distributed as a set of C header files.
+ To use it, download and include the following files in your project tree: + - [parser.h](https://git.thederf.com/thederf/Terrace/src/branch/main/packages/c/parser.h) - Core terrace parser + - [document.h](https://git.thederf.com/thederf/Terrace/src/branch/main/packages/c/document.h) - (optional) Convenience functions for parsing of documents + + A simple example program using to read each line from stdin and output parser information, looking for a "title" key: + CodeBlock c + // Provides getline() for reading from stdin + #include + // Provides free() for deallocating the lines from getline() + #include + // Provides document API for interacting with Terrace files + #include "document.h" + + // Custom userData struct. Stores information needed + // by read_line below. + typedef struct read_line_container_s { + size_t bufsize; + } read_line_container_t; + + // A user-supplied function to read lines from stdin (or whichever data source you choose) + int read_line_from_stdin(char** line, void* userData) { + read_line_container_t* lineContainer = (read_line_container_t*) userData; + // Uses getline from the C stdlib to read the next line from stdin. + int num_chars_read = getline(line, &lineContainer->bufsize, stdin); + // Change trailing newline to null char. Terrace doesn't use trailing newlines + if (num_chars_read > 0) (*line)[num_chars_read - 1] = '\0'; + // Return the number of charaters read to the document parser. + return num_chars_read; + } + + int main(int argc, char *argv[]) { + read_line_container_t read_line_information = { .bufsize = 64 }; + // Initialize the terrace document with the line reader function created above. + terrace_document_t doc = terrace_create_document(' ', &read_line_from_stdin, &read_line_information); + + // Loop over every line in the document. + while(terrace_next(&doc, -1)) { + // > Replace with your custom line handling code. + + // Print the line and level to demonstrate the terrace_level and terrace_line functions. + printf("| level %u | line %s |", terrace_level(&doc), terrace_line(&doc, -1)); + // If one of the lines starts with "title", output it. + if (terrace_match(&doc, "title")) { + printf("Title: %s |", terrace_tail(&doc)); + } + }; + + // Free allocated line memory + free(line); + + return 0; + } + + Include ./src/docs/c/core-api.inc.tce + Include ./src/docs/c/document-api.inc.tce + + Heading 2 Contributing + class mt-12 + +Section dark + Footer + class w-full diff --git a/docs/src/docs/javascript.tce b/docs/src/docs/javascript.tce deleted file mode 100644 index a80ca21..0000000 --- a/docs/src/docs/javascript.tce +++ /dev/null @@ -1,579 +0,0 @@ -layout layout.njk -title JavaScript Documentation - Terrace -description - JavaScript language documentation for the Terrace programming language - -Section light - class flex flex-col md:flex-row gap-16 - - Block - class w-full lg:w-1/3 - TableOfContents - - Block - Heading 1 Terrace JavaScript Documentation - class -ml-2 - - Markdown - Documentation is available for the following languages: - - [C](/docs/c/) - 75% Complete - - [JavaScript](/docs/javascript/) - 75% Complete - - [Python](/docs/python/) - 0% Complete - - Heading 2 Getting Started - class mt-12 mb-6 - Markdown - Install Terrace using [NPM](https://www.npmjs.com/): - - CodeBlock bash - # NPM (https://npmjs.com) - $ npm install @terrace-lang/js - - # PNPM (https://pnpm.io/) - $ pnpm install @terrace-lang/js - - # Yarn (https://yarnpkg.com/) - $ yarn add @terrace-lang/js - - Heading 2 Core API - class mt-12 - Markdown - **Note:** The Core API uses C-style conventions to optimize memory management - and improve portability to other environments and languages. - It is unwieldy and does not follow JavaScript best practices. - - For most projects you'll want to use the [Document API](#document-api) instead. - It provides an ergonomic wrapper around the Core API and lets you focus on parsing - your documents. - - Heading 3 LineData - class mb-4 mt-12 - CodeBlock typescript - // Type Definition - // Holds the parsed information from each line. - type LineData = { - // Which character is being used for indentation. Avoids having to specify it on each parseLine call. - indent: string; - // How many indent characters are present in the current line before the first non-indent character. - level: number; - // The number of characters before the start of the line's "head" section. - // (Normally the same as `level`) - offsetHead: number; - // The number of characters before the start of the line's "tail" section. - offsetTail: number; - } - - Heading 3 createLineData() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | indent | string | The character used for indentation in the document. Only a single character is permitted. - | **@returns** | [LineData](#line-data) | A LineData instance with the specified indent character and all other values initialized to 0. - - Initialize a LineData instance with default values to pass to [parseLine()](#parse-line). - - CodeBlock typescript - // Type Definition - function createLineData(indent: string = ' '): LineData - - // Import Path - import { createLineData } from '@terrace-lang/js/parser' - - // Usage - const lineData = createLineData(' ') - console.dir(lineData) - // { indent: ' ', level: 0, offsetHead: 0, offsetTail: 0 } - // Use the same lineData object for all calls to parseLine in the same document. - - Heading 3 parseLine() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | line | string | A string containing a line to parse. Shouldn't end with a newline. - | lineData | [LineData](#line-data) | A LineData object to store information about the current line, from [createLineData()](#create-line-data).
**Mutated in-place!** - - Core Terrace parser function, sets `level`, `offsetHead`, and `offsetTail` in a [LineData](#line-data) object based on the passed line. - Note that this is a C-style function, `lineData` is treated as a reference and mutated in-place. - - CodeBlock typescript - // Type Definition - function parseLine(lineData: LineData): LineData - - // Import Path - import { createLineData, parseLine } from '@terrace-lang/js/parser' - - // Usage - const lineData = createLineData(' ') - parseLine('title Example Title', lineData) - console.dir(lineData) - // { indent: ' ', level: 0, offsetHead: 0, offsetTail: 5 } - - Heading 2 Document API - class mt-12 - - Heading 3 useDocument() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | reader | [Reader](#reader) | When called, resolves to a string containing the next line in the document. - | indent | string | The character used for indentation in the document. Only a single character is permitted. - | **@returns** | [Document](#document) | A set of convenience functions for iterating through and parsing a document line by line. - - Provides a simple set of convenience functions around parseLine for more ergonomic parsing of Terrace documents. - CodeBlock typescript - // Type Definition - function useDocument (reader: Reader, indent: string = ' '): Document - - // Import Path - import { useDocument } from '@terrace-lang/js/document' - - Heading 3 Document - class mb-4 mt-12 - Markdown - Container for a handful of convenience functions for parsing documents. - Obtained from [useDocument()](#usedocument) above - CodeBlock typescript - // Type Definition - type Document = { - next: (levelScope?: number) => Promise - level: () => number, - line: (startOffset?: number) => string, - head: () => string, - tail: () => string, - match: (matchHead: string) => boolean - } - - Heading 3 Document.next() - class mb-4 mt-12 - - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | levelScope | number = -1 | If specified, `next()` will return `false` when it encounters a line with a level at or below `levelScope` - | **@returns** | Promise | Returns `true` after parsing a line, or `false` if the document has ended or a line at or below `levelScope` has been encountered. - - Advances the current position in the terrace document and populates lineData - with the parsed information from that line. - - Returns `true` after parsing the next line, or `false` upon reaching the end of the document. - If the `levelScope` parameter is provided, `next()` will return `false` when it encounters a line - with a level at or below `levelScope`. This allows you to iterate through subsections of a document. - - If a lower-level line was encountered, the following call to `next()` will repeat this line again. - This allows a child loop to look forward, determine that the next line will be outside its purview, - and return control to the calling loop transparently without additional logic. - - Intended to be used inside a while loop to parse a section of a Terrace document. - - CodeBlock typescript - // Type Definition - next: (levelScope?: number) => Promise - - // Import Path - import { useDocument } from '@terrace-lang/js/document' - - // Usage - const { next } = useDocument(...) - while (await next()) { - // Do something with each line. - } - - Heading 3 Document.level() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | **@returns** | number | The indent level of the current line - - Returns the number of indent characters of the current line. - - Given the following document, `level()` would return 0, 1, 2, and 5 respectively for each line. - CodeBlock terrace - block - block - block - block - - CodeBlock typescript - // Type Definition - level: () => number - - // Usage - import { useDocument } from '@terrace-lang/js/document' - const { level } = useDocument(...) - - Heading 3 Document.line() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | levelScope | startOffset = [level()](#document-level) | How many indent characters to skip before outputting the line contents. Defaults to the current indent level - | **@returns** | string | The line contents starting from `startOffset` - - Get a string with the current line contents. Skips all indent characters by default, but this can be configured with `startOffset` - - Given the following document - CodeBlock terrace - root - sub-line - Markdown - - Calling `line()` on the second line returns "sub-line", trimming off the leading indent characters. - - Calling `line(0)` however, returns "    sub-line", with all four leading spaces. - - `startOffset` is primarily used for parsing blocks that have literal indented multi-line text, such as markdown. - - CodeBlock typescript - // Type Definition - line: (startOffset?: number) => string - - // Usage - import { useDocument } from '@terrace-lang/js/document' - const { line } = useDocument(...) - - Heading 3 Document.head() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | **@returns** | string | The `head` portion (first word) of a line - - Get the first "word" of a line, starting from the first non-indent character to the first space or end of the line. - Often used for deciding how to parse a block. - - Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser - - Given the following line, [head()](#document-head) returns "title" - CodeBlock terrace - title An Important Document - CodeBlock typescript - // Type Definition - head: () => string - - // Usage - import { useDocument } from '@terrace-lang/js/document' - const { head } = useDocument(...) - - Heading 3 Document.tail() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | **@returns** | string | The remainder of the line following the [head()](#document-head) portion, with no leading space - - Get all text following the first "word" of a line, starting from the first character after the space at the end of [head()](#document-head) - - Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser - - Given the following line, [tail()](#document-tail) returns "An Important Document" - CodeBlock terrace - title An Important Document - CodeBlock typescript - // Type Definition - tail: () => string - - // Usage - import { useDocument } from '@terrace-lang/js/document' - const { tail } = useDocument(...) - - Heading 3 Document.match() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | matchValue | string | A string to check against [head()](#document-head) for equality - | **@returns** | boolean | Whether the current [head()](#document-head) matches the passed value - - Quickly check if the current line head matches a specified value - - Shorthand for `matchValue === head()` - - Given the following line - CodeBlock terrace - title An Important Document - Markdown - - `match('title')` returns `true` - - `match('somethingElse`) returns `false` - CodeBlock typescript - // Type Definition - match: (matchValue: string) => boolean - - // Usage - import { useDocument } from '@terrace-lang/js/document' - const { match } = useDocument(...) - - Heading 2 Reader API - class mt-12 - Markdown - The [Document API](#document-api) requires `Reader` functions to iterate through lines - in a document. A reader function simply returns a string (or a promise resolving to a string). - Each time it is called, it returns the next line from whichever source it is pulling them. - - Terrace provides a few built-in readers, but you are welcome to build your own instead. - - Heading 3 Reader - class mb-4 mt-12 - Markdown - Any function (async included) that returns the next line in a document when called and null when the end of the document has been reached. - - CodeBlock typescript - // Type Definition - type Reader = () => string|null|Promise - - Heading 3 createStringReader() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | source | string\|string[] | The lines to iterate over, as a multiline string or an array of line strings. - | index | number | Optional - which line to start from. - | **@returns** | [Reader](#reader) | A reader function that returns each line from the source document when called sequentially. - - Get a simple [Reader](#reader) function that always returns the next line from a mutliline string or an array of line strings. - CodeBlock typescript - // Type Definition - function createStringReader(source: string|string[], index: number = 0): Reader - - // Import Path - import { createStringReader } from '@terrace-lang/js/readers/js-string' - - Markdown - **Usage** - CodeBlock typescript - import { createStringReader, useDocument } from '@terrace-lang/js' - - // Create a string reader with two lines - const reader = createStringReader('title Example Title\n line2') - // Also permitted: - // const reader = createStringReader(['title Example Title', ' line 2']) - - const { next, level, line } = useDocument(reader) - await next() - console.log(level(), line()) - // 0 title Example Title - await next() - console.log(level(), line()) - // 1 line 2 - - - Heading 3 createFileReader() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | path | string | A path to the file to read. - | **@returns** | [Reader](#reader) | A reader function that returns each line from the file when called sequentially - - **Note:** Only available in Node.js environments.
- Get a [Reader](#reader) function that returns the next line from the specified file when called sequentially. - - - CodeBlock typescript - // Type Definition - function createFileReader(path: string): Reader - - // Import Path - import { createFileReader } from '@terrace-lang/js/readers/node-readline' - - Markdown - **Usage** - CodeExample - summary-class mb-[300px] - pre-class max-h-[300px] - javascript main.js - import { createFileReader, useDocument } from '@terrace-lang/js' - - // Read the file ./example.tce - const { next, level, line } = useDocument(createFileReader('./example.tce')) - await next() - console.log(level(), line()) - // 0 title Example Title - await next() - console.log(level(), line()) - // 1 line 2 - - terrace example.tce - title Example Title - line 2 - - Heading 3 createStdinReader() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | **@returns** | [Reader](#reader) | A reader function that returns each line from `stdin` when called sequentially - - **Note:** Only available in Node.js environments.
- Get a [Reader](#reader) function that returns the next line from standard input when called sequentially. Does not block stdin to wait for input. If no input is present it returns null immediately. - CodeBlock typescript - // Type Definition - function createStdinReader(): Reader - - // Import Path - import { createStdinReader } from '@terrace-lang/js/readers/node-readline' - Markdown - **Usage** - CodeExample - summary-class mb-[250px] - pre-class max-h-[250px] - javascript main.js - import { createStdinReader, useDocument } from '@terrace-lang/js' - - // Read the contents of standard input - const { next, level, line } = useDocument(createStdinReader()) - - while(await next()) { - console.log(level(), line()) - // See `shell` panel above for output - } - - terrace example.tce - title Example Title - line 2 - - sh - # Run main.js with the contents of example.tce piped to stdin - $ cat example.tce > node ./main.js - 0 title Example Title - 1 line 2 - - Heading 3 createStreamReader() - class mb-4 mt-12 - Markdown - | Parameter | Type | Description - | -------------- | --------------------- | ----------------------------------------------------------------------- - | stream | NodeJS.ReadStream|fs.ReadStream | A ReadStream compatible with Node.js `readline` APIs - | **@returns** | [Reader](#reader) | A reader function that returns each line from `stdin` when called sequentially - - **Note:** Only available in Node.js environments.
- Get a [Reader](#reader) function that always returns the next line from a passed read stream when called sequentially. - CodeBlock typescript - // Type Definition - function createStreamReader(): Reader - - // Import Path - import { createStreamReader } from '@terrace-lang/js/readers/node-readline' - Markdown - **Usage** - CodeExample - summary-class mb-[320px] - pre-class max-h-[320px] - javascript main.js - import fs from 'node:fs' - import { createStreamReader, useDocument } from '@terrace-lang/js' - - // Read the file ./example.tce - equivalent to the `createFileReader` example above. - const reader = createStreamReader(fs.createReadStream('./example.tce')) - const { next, level, line } = useDocument(reader) - await next() - console.log(level(), line()) - // 0 title Example Title - await next() - console.log(level(), line()) - // 1 line 2 - - terrace example.tce - title Example Title - line 2 - - Heading 2 Recipes - class mt-12 - - Heading 3 Read object properties - class mb-2 - Markdown - Read known properties from a Terrace block and write them to an object. - CodeBlock javascript - // Provides simple convenience functions over the core parser - // CommonJS: const { useDocument } = require('@terrace-lang/js/document') - import { useDocument } from '@terrace-lang/js/document' - // A helper for iterating over a string line-by-line - // CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string') - import { createStringReader } from '@terrace-lang/js/readers/js-string' - - const input = ` - object - string_property An example string - numeric_property 4 - ` - - const output = { - string_property: null, - numeric_property: null - } - - // useDocument returns convenience functions - const { next, level, head, tail, match } = useDocument(createStringReader(input)) - - // next() parses the next line in the document - while (await next()) { - // match('object') is equivalent to head() === 'object' - // Essentially: "If the current line starts with 'object'" - if (match('object')) { - const objectLevel = level() - // When we call next with a parent level it, - // only iterates over lines inside the parent block - while (await next(objectLevel)) { - // tail() returns the part of the current line after the first space - if (match('string_property')) output.string_property = tail() - // parseFloat() here the string tail() to a numeric float value - if (match('numeric_property')) output.numeric_property = parseFloat(tail()) - } - } - } - - console.dir(output) - // { string_property: 'An example string', numeric_property: 4 } - - Markdown - Read *all* properties as strings from a Terrace block and write them to an object. - CodeBlock javascript - // Provides simple convenience functions over the core parser - // CommonJS: const { useDocument } = require('@terrace-lang/js/document') - import { useDocument } from '@terrace-lang/js/document' - // A helper for iterating over a string line-by-line - // CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string') - import { createStringReader } from '@terrace-lang/js/readers/js-string' - - const input = ` - object - property1 Value 1 - property2 Value 2 - random_property igazi3ii4quaC5OdoB5quohnah1beeNg - ` - - const output = {} - - // useDocument returns convenience functions - const { next, level, head, tail, match } = useDocument(createStringReader(input)) - - // next() parses the next line in the document - while (await next()) { - // match('object') is equivalent to head() === 'object' - // Essentially: "If the current line starts with 'object'" - if (match('object')) { - const objectLevel = level() - // When we call next with a parent level, - // it only iterates over lines inside the parent block - while (await next(objectLevel)) { - // Skip empty lines - if (!line()) continue - // Add any properties to the object as strings using the - // line head() as the key and tail() as the value - output[head()] = tail() - } - } - } - - console.dir(output) - // { property1: 'Value 1', property2: 'Value 2', random_property: 'igazi3ii4quaC5OdoB5quohnah1beeNg' } - - - Heading 2 Contributing - class mt-12 - -Section dark - Footer - class w-full diff --git a/docs/src/docs/javascript/core-api.inc.tce b/docs/src/docs/javascript/core-api.inc.tce new file mode 100644 index 0000000..89dc805 --- /dev/null +++ b/docs/src/docs/javascript/core-api.inc.tce @@ -0,0 +1,74 @@ +Heading 2 Core API + class mt-12 +Markdown + **Note:** The Core API uses C-style conventions to optimize memory management + and improve portability to other environments and languages. + It is unwieldy and does not follow JavaScript best practices. + + For most projects you'll want to use the [Document API](#document-api) instead. + It provides an ergonomic wrapper around the Core API and lets you focus on parsing + your documents. + +Heading 3 LineData + class mb-4 mt-12 +CodeBlock typescript + // Type Definition + // Holds the parsed information from each line. + type LineData = { + // Which character is being used for indentation. Avoids having to specify it on each parseLine call. + indent: string; + // How many indent characters are present in the current line before the first non-indent character. + level: number; + // The number of characters before the start of the line's "head" section. + // (Normally the same as `level`) + offsetHead: number; + // The number of characters before the start of the line's "tail" section. + offsetTail: number; + } + +Heading 3 createLineData() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | indent | string | The character used for indentation in the document. Only a single character is permitted. + | **@returns** | [LineData](#line-data) | A LineData instance with the specified indent character and all other values initialized to 0. + + Initialize a LineData instance with default values to pass to [parseLine()](#parse-line). + +CodeBlock typescript + // Type Definition + function createLineData(indent: string = ' '): LineData + + // Import Path + import { createLineData } from '@terrace-lang/js/parser' + + // Usage + const lineData = createLineData(' ') + console.dir(lineData) + // { indent: ' ', level: 0, offsetHead: 0, offsetTail: 0 } + // Use the same lineData object for all calls to parseLine in the same document. + +Heading 3 parseLine() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | line | string | A string containing a line to parse. Shouldn't end with a newline. + | lineData | [LineData](#line-data) | A LineData object to store information about the current line, from [createLineData()](#create-line-data).
**Mutated in-place!** + + Core Terrace parser function, sets `level`, `offsetHead`, and `offsetTail` in a [LineData](#line-data) object based on the passed line. + Note that this is a C-style function, `lineData` is treated as a reference and mutated in-place. + +CodeBlock typescript + // Type Definition + function parseLine(lineData: LineData): LineData + + // Import Path + import { createLineData, parseLine } from '@terrace-lang/js/parser' + + // Usage + const lineData = createLineData(' ') + parseLine('title Example Title', lineData) + console.dir(lineData) + // { indent: ' ', level: 0, offsetHead: 0, offsetTail: 5 } diff --git a/docs/src/docs/javascript/document-api.inc.tce b/docs/src/docs/javascript/document-api.inc.tce new file mode 100644 index 0000000..8aa78af --- /dev/null +++ b/docs/src/docs/javascript/document-api.inc.tce @@ -0,0 +1,193 @@ +Heading 2 Document API + class mt-12 + +Heading 3 useDocument() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | reader | [Reader](#reader) | When called, resolves to a string containing the next line in the document. + | indent | string | The character used for indentation in the document. Only a single character is permitted. + | **@returns** | [Document](#document) | A set of convenience functions for iterating through and parsing a document line by line. + + Provides a simple set of convenience functions around parseLine for more ergonomic parsing of Terrace documents. +CodeBlock typescript + // Type Definition + function useDocument (reader: Reader, indent: string = ' '): Document + + // Import Path + import { useDocument } from '@terrace-lang/js/document' + +Heading 3 Document + class mb-4 mt-12 +Markdown + Container for a handful of convenience functions for parsing documents. + Obtained from [useDocument()](#usedocument) above +CodeBlock typescript + // Type Definition + type Document = { + next: (levelScope?: number) => Promise + level: () => number, + line: (startOffset?: number) => string, + head: () => string, + tail: () => string, + match: (matchHead: string) => boolean + } + +Heading 3 Document.next() + class mb-4 mt-12 + +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | levelScope | number = -1 | If specified, `next()` will return `false` when it encounters a line with a level at or below `levelScope` + | **@returns** | Promise | Returns `true` after parsing a line, or `false` if the document has ended or a line at or below `levelScope` has been encountered. + + Advances the current position in the terrace document and populates lineData + with the parsed information from that line. + + Returns `true` after parsing the next line, or `false` upon reaching the end of the document. + If the `levelScope` parameter is provided, `next()` will return `false` when it encounters a line + with a level at or below `levelScope`. This allows you to iterate through subsections of a document. + + If a lower-level line was encountered, the following call to `next()` will repeat this line again. + This allows a child loop to look forward, determine that the next line will be outside its purview, + and return control to the calling loop transparently without additional logic. + + Intended to be used inside a while loop to parse a section of a Terrace document. + +CodeBlock typescript + // Type Definition + next: (levelScope?: number) => Promise + + // Import Path + import { useDocument } from '@terrace-lang/js/document' + + // Usage + const { next } = useDocument(...) + while (await next()) { + // Do something with each line. + } + +Heading 3 Document.level() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | **@returns** | number | The indent level of the current line + + Returns the number of indent characters of the current line. + + Given the following document, `level()` would return 0, 1, 2, and 5 respectively for each line. +CodeBlock terrace + block + block + block + block + +CodeBlock typescript + // Type Definition + level: () => number + + // Usage + import { useDocument } from '@terrace-lang/js/document' + const { level } = useDocument(...) + +Heading 3 Document.line() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | levelScope | startOffset = [level()](#document-level) | How many indent characters to skip before outputting the line contents. Defaults to the current indent level + | **@returns** | string | The line contents starting from `startOffset` + + Get a string with the current line contents. Skips all indent characters by default, but this can be configured with `startOffset` + + Given the following document +CodeBlock terrace + root + sub-line +Markdown + - Calling `line()` on the second line returns "sub-line", trimming off the leading indent characters. + - Calling `line(0)` however, returns "    sub-line", with all four leading spaces. + + `startOffset` is primarily used for parsing blocks that have literal indented multi-line text, such as markdown. + +CodeBlock typescript + // Type Definition + line: (startOffset?: number) => string + + // Usage + import { useDocument } from '@terrace-lang/js/document' + const { line } = useDocument(...) + +Heading 3 Document.head() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | **@returns** | string | The `head` portion (first word) of a line + + Get the first "word" of a line, starting from the first non-indent character to the first space or end of the line. + Often used for deciding how to parse a block. + + Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser + + Given the following line, [head()](#document-head) returns "title" +CodeBlock terrace + title An Important Document +CodeBlock typescript + // Type Definition + head: () => string + + // Usage + import { useDocument } from '@terrace-lang/js/document' + const { head } = useDocument(...) + +Heading 3 Document.tail() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | **@returns** | string | The remainder of the line following the [head()](#document-head) portion, with no leading space + + Get all text following the first "word" of a line, starting from the first character after the space at the end of [head()](#document-head) + + Terrace DSLs do not *need* to use head-tail line structure, but support for them is built into the parser + + Given the following line, [tail()](#document-tail) returns "An Important Document" +CodeBlock terrace + title An Important Document +CodeBlock typescript + // Type Definition + tail: () => string + + // Usage + import { useDocument } from '@terrace-lang/js/document' + const { tail } = useDocument(...) + +Heading 3 Document.match() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | matchValue | string | A string to check against [head()](#document-head) for equality + | **@returns** | boolean | Whether the current [head()](#document-head) matches the passed value + + Quickly check if the current line head matches a specified value + + Shorthand for `matchValue === head()` + + Given the following line +CodeBlock terrace + title An Important Document +Markdown + - `match('title')` returns `true` + - `match('somethingElse`) returns `false` +CodeBlock typescript + // Type Definition + match: (matchValue: string) => boolean + + // Usage + import { useDocument } from '@terrace-lang/js/document' + const { match } = useDocument(...) diff --git a/docs/src/docs/javascript/index.tce b/docs/src/docs/javascript/index.tce new file mode 100644 index 0000000..86a920f --- /dev/null +++ b/docs/src/docs/javascript/index.tce @@ -0,0 +1,48 @@ +layout layout.njk +title JavaScript Documentation - Terrace +description + JavaScript language documentation for the Terrace programming language + +Section light + class flex flex-col md:flex-row gap-16 + + Block + class w-full lg:w-1/3 + TableOfContents + + Block + Heading 1 Terrace JavaScript Documentation + class -ml-2 + + Markdown + Documentation is available for the following languages: + - [C](/docs/c/) - 75% Complete + - [JavaScript](/docs/javascript/) - 75% Complete + - [Python](/docs/python/) - 0% Complete + + Heading 2 Getting Started + class mt-12 mb-6 + Markdown + Install Terrace using [NPM](https://www.npmjs.com/): + + CodeBlock bash + # NPM (https://npmjs.com) + $ npm install @terrace-lang/js + + # PNPM (https://pnpm.io/) + $ pnpm install @terrace-lang/js + + # Yarn (https://yarnpkg.com/) + $ yarn add @terrace-lang/js + + Include ./src/docs/javascript/core-api.inc.tce + Include ./src/docs/javascript/document-api.inc.tce + Include ./src/docs/javascript/reader-api.inc.tce + Include ./src/docs/javascript/recipes.inc.tce + + Heading 2 Contributing + class mt-12 + +Section dark + Footer + class w-full diff --git a/docs/src/docs/javascript/reader-api.inc.tce b/docs/src/docs/javascript/reader-api.inc.tce new file mode 100644 index 0000000..0f544bc --- /dev/null +++ b/docs/src/docs/javascript/reader-api.inc.tce @@ -0,0 +1,173 @@ +Heading 2 Reader API + class mt-12 +Markdown + The [Document API](#document-api) requires `Reader` functions to iterate through lines + in a document. A reader function simply returns a string (or a promise resolving to a string). + Each time it is called, it returns the next line from whichever source it is pulling them. + + Terrace provides a few built-in readers, but you are welcome to build your own instead. + +Heading 3 Reader + class mb-4 mt-12 +Markdown + Any function (async included) that returns the next line in a document when called and null when the end of the document has been reached. + +CodeBlock typescript + // Type Definition + type Reader = () => string|null|Promise + +Heading 3 createStringReader() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | source | string\|string[] | The lines to iterate over, as a multiline string or an array of line strings. + | index | number | Optional - which line to start from. + | **@returns** | [Reader](#reader) | A reader function that returns each line from the source document when called sequentially. + + Get a simple [Reader](#reader) function that always returns the next line from a mutliline string or an array of line strings. +CodeBlock typescript + // Type Definition + function createStringReader(source: string|string[], index: number = 0): Reader + + // Import Path + import { createStringReader } from '@terrace-lang/js/readers/js-string' + +Markdown + **Usage** +CodeBlock typescript + import { createStringReader, useDocument } from '@terrace-lang/js' + + // Create a string reader with two lines + const reader = createStringReader('title Example Title\n line2') + // Also permitted: + // const reader = createStringReader(['title Example Title', ' line 2']) + + const { next, level, line } = useDocument(reader) + await next() + console.log(level(), line()) + // 0 title Example Title + await next() + console.log(level(), line()) + // 1 line 2 + + +Heading 3 createFileReader() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | path | string | A path to the file to read. + | **@returns** | [Reader](#reader) | A reader function that returns each line from the file when called sequentially + + **Note:** Only available in Node.js environments.
+ Get a [Reader](#reader) function that returns the next line from the specified file when called sequentially. + + +CodeBlock typescript + // Type Definition + function createFileReader(path: string): Reader + + // Import Path + import { createFileReader } from '@terrace-lang/js/readers/node-readline' + +Markdown + **Usage** +CodeExample + summary-class mb-[300px] + pre-class max-h-[300px] + javascript main.js + import { createFileReader, useDocument } from '@terrace-lang/js' + + // Read the file ./example.tce + const { next, level, line } = useDocument(createFileReader('./example.tce')) + await next() + console.log(level(), line()) + // 0 title Example Title + await next() + console.log(level(), line()) + // 1 line 2 + + terrace example.tce + title Example Title + line 2 + +Heading 3 createStdinReader() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | **@returns** | [Reader](#reader) | A reader function that returns each line from `stdin` when called sequentially + + **Note:** Only available in Node.js environments.
+ Get a [Reader](#reader) function that returns the next line from standard input when called sequentially. Does not block stdin to wait for input. If no input is present it returns null immediately. +CodeBlock typescript + // Type Definition + function createStdinReader(): Reader + + // Import Path + import { createStdinReader } from '@terrace-lang/js/readers/node-readline' +Markdown + **Usage** +CodeExample + summary-class mb-[250px] + pre-class max-h-[250px] + javascript main.js + import { createStdinReader, useDocument } from '@terrace-lang/js' + + // Read the contents of standard input + const { next, level, line } = useDocument(createStdinReader()) + + while(await next()) { + console.log(level(), line()) + // See `shell` panel above for output + } + + terrace example.tce + title Example Title + line 2 + + sh + # Run main.js with the contents of example.tce piped to stdin + $ cat example.tce > node ./main.js + 0 title Example Title + 1 line 2 + +Heading 3 createStreamReader() + class mb-4 mt-12 +Markdown + | Parameter | Type | Description + | -------------- | --------------------- | ----------------------------------------------------------------------- + | stream | NodeJS.ReadStream|fs.ReadStream | A ReadStream compatible with Node.js `readline` APIs + | **@returns** | [Reader](#reader) | A reader function that returns each line from `stdin` when called sequentially + + **Note:** Only available in Node.js environments.
+ Get a [Reader](#reader) function that always returns the next line from a passed read stream when called sequentially. +CodeBlock typescript + // Type Definition + function createStreamReader(): Reader + + // Import Path + import { createStreamReader } from '@terrace-lang/js/readers/node-readline' +Markdown + **Usage** +CodeExample + summary-class mb-[320px] + pre-class max-h-[320px] + javascript main.js + import fs from 'node:fs' + import { createStreamReader, useDocument } from '@terrace-lang/js' + + // Read the file ./example.tce - equivalent to the `createFileReader` example above. + const reader = createStreamReader(fs.createReadStream('./example.tce')) + const { next, level, line } = useDocument(reader) + await next() + console.log(level(), line()) + // 0 title Example Title + await next() + console.log(level(), line()) + // 1 line 2 + + terrace example.tce + title Example Title + line 2 diff --git a/docs/src/docs/javascript/recipes.inc.tce b/docs/src/docs/javascript/recipes.inc.tce new file mode 100644 index 0000000..4a51417 --- /dev/null +++ b/docs/src/docs/javascript/recipes.inc.tce @@ -0,0 +1,91 @@ +Heading 2 Recipes + class mt-12 + +Heading 3 Read object properties + class mb-2 +Markdown + Read known properties from a Terrace block and write them to an object. +CodeBlock javascript + // Provides simple convenience functions over the core parser + // CommonJS: const { useDocument } = require('@terrace-lang/js/document') + import { useDocument } from '@terrace-lang/js/document' + // A helper for iterating over a string line-by-line + // CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string') + import { createStringReader } from '@terrace-lang/js/readers/js-string' + + const input = ` + object + string_property An example string + numeric_property 4 + ` + + const output = { + string_property: null, + numeric_property: null + } + + // useDocument returns convenience functions + const { next, level, head, tail, match } = useDocument(createStringReader(input)) + + // next() parses the next line in the document + while (await next()) { + // match('object') is equivalent to head() === 'object' + // Essentially: "If the current line starts with 'object'" + if (match('object')) { + const objectLevel = level() + // When we call next with a parent level it, + // only iterates over lines inside the parent block + while (await next(objectLevel)) { + // tail() returns the part of the current line after the first space + if (match('string_property')) output.string_property = tail() + // parseFloat() here the string tail() to a numeric float value + if (match('numeric_property')) output.numeric_property = parseFloat(tail()) + } + } + } + + console.dir(output) + // { string_property: 'An example string', numeric_property: 4 } + +Markdown + Read *all* properties as strings from a Terrace block and write them to an object. +CodeBlock javascript + // Provides simple convenience functions over the core parser + // CommonJS: const { useDocument } = require('@terrace-lang/js/document') + import { useDocument } from '@terrace-lang/js/document' + // A helper for iterating over a string line-by-line + // CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string') + import { createStringReader } from '@terrace-lang/js/readers/js-string' + + const input = ` + object + property1 Value 1 + property2 Value 2 + random_property igazi3ii4quaC5OdoB5quohnah1beeNg + ` + + const output = {} + + // useDocument returns convenience functions + const { next, level, head, tail, match } = useDocument(createStringReader(input)) + + // next() parses the next line in the document + while (await next()) { + // match('object') is equivalent to head() === 'object' + // Essentially: "If the current line starts with 'object'" + if (match('object')) { + const objectLevel = level() + // When we call next with a parent level, + // it only iterates over lines inside the parent block + while (await next(objectLevel)) { + // Skip empty lines + if (!line()) continue + // Add any properties to the object as strings using the + // line head() as the key and tail() as the value + output[head()] = tail() + } + } + } + + console.dir(output) + // { property1: 'Value 1', property2: 'Value 2', random_property: 'igazi3ii4quaC5OdoB5quohnah1beeNg' } diff --git a/docs/src/parser/nodes/Include.js b/docs/src/parser/nodes/Include.js new file mode 100644 index 0000000..d9869bc --- /dev/null +++ b/docs/src/parser/nodes/Include.js @@ -0,0 +1,28 @@ +const { useDocument } = require('@terrace-lang/js/document') +const { createFileReader } = require('@terrace-lang/js/readers/node-readline') +const fs = require('fs/promises') +const path = require('path') +const knownNodes = require('./index.js') + +module.exports = async function (originalDoc, rootLevel, ...args) { + const includedDoc = useDocument(createFileReader(originalDoc.tail())) + const { next, head, tail, level } = includedDoc + + const node = { + type: originalDoc.head(), + class: '', + children: [] + } + + while (await next()) { + if (!head()) continue + const block = head() + + if (!knownNodes[block]) continue + node.children.push(await knownNodes[block](includedDoc, level(), ...args)) + } + + console.dir(node) + + return node +} diff --git a/docs/src/parser/nodes/index.js b/docs/src/parser/nodes/index.js index a3021bd..26a416b 100644 --- a/docs/src/parser/nodes/index.js +++ b/docs/src/parser/nodes/index.js @@ -1,5 +1,6 @@ const parseNode = require('./Node.js') +module.exports.Include = require('./Include.js') module.exports.Block = parseNode module.exports.Section = async (doc, rootLevel, ...args) => { const variant = doc.tail() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc62515..44e54ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,10 +61,13 @@ importers: '@terrace-lang/c': workspace:* '@terrace-lang/js': workspace:* '@terrace-lang/python': workspace:* + chai: ^4.3.7 dependencies: '@terrace-lang/c': link:../packages/c '@terrace-lang/js': link:../packages/js '@terrace-lang/python': link:../packages/python + devDependencies: + chai: 4.3.7 packages: @@ -1361,6 +1364,10 @@ packages: resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==} dev: true + /assertion-error/1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + /async-each-series/0.1.1: resolution: {integrity: sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==} engines: {node: '>=0.8.0'} @@ -1673,6 +1680,19 @@ packages: resolution: {integrity: sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==} dev: true + /chai/4.3.7: + resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 4.1.3 + get-func-name: 2.0.0 + loupe: 2.3.6 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + /chalk/1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} @@ -1712,6 +1732,10 @@ packages: is-regex: 1.1.4 dev: true + /check-error/1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + dev: true + /chokidar/3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -1931,6 +1955,13 @@ packages: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} dev: true + /deep-eql/4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + /deepmerge/4.3.0: resolution: {integrity: sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==} engines: {node: '>=0.10.0'} @@ -2705,6 +2736,10 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dev: true + /get-func-name/2.0.0: + resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + dev: true + /get-intrinsic/1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: @@ -3893,6 +3928,12 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true + /loupe/2.3.6: + resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + dependencies: + get-func-name: 2.0.0 + dev: true + /lru-cache/4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: @@ -4347,6 +4388,10 @@ packages: pify: 3.0.0 dev: true + /pathval/1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true diff --git a/test/package.json b/test/package.json index 2ca5c82..07fd3a9 100644 --- a/test/package.json +++ b/test/package.json @@ -5,8 +5,11 @@ "test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest" }, "dependencies": { - "@terrace-lang/js": "workspace:*", "@terrace-lang/c": "workspace:*", + "@terrace-lang/js": "workspace:*", "@terrace-lang/python": "workspace:*" + }, + "devDependencies": { + "chai": "^4.3.7" } }