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"
}
}