Make more progress on package configuration, fill out C docs.

This commit is contained in:
Joshua Bemenderfer
2023-02-21 22:35:53 -05:00
parent fb90f825ed
commit 3b7077e761
19 changed files with 872 additions and 275 deletions

View File

@@ -3,6 +3,7 @@
#include "parser.h"
// Tracks state of a given while being parsed.
typedef struct terrace_document_s {
// == Internal State == //
unsigned int _repeatCurrentLine;
@@ -37,7 +38,7 @@ terrace_document_t terrace_create_document(const char indent, int (*reader)(char
terrace_document_t document = {
._repeatCurrentLine = 0,
._currentLine = 0,
.lineData = terrace_create_line_data(indent),
.lineData = terrace_create_linedata(indent),
.reader = reader,
.userData = userData
};
@@ -56,6 +57,7 @@ terrace_document_t terrace_create_document(const char indent, int (*reader)(char
* block
* block
* ```
* @param {terrace_document_t*} doc A pointer to the Terrace document being parsed
* @returns {unsigned int} The indent level of the current line
*/
unsigned int terrace_level(terrace_document_t* doc) {
@@ -64,7 +66,7 @@ unsigned int terrace_level(terrace_document_t* doc) {
/**
* Get a string with the current line contents
* If `startOffset` is -1, skips all indent characters by default. Otherwise only skips the amount specified
* If `startOffset` is -1, skips all indent characters by default. Otherwise only skips the amount specified.
*
* Given the following document
*
@@ -78,7 +80,7 @@ unsigned int terrace_level(terrace_document_t* doc) {
* `startOffset`s other than `-1` are primarily used for parsing blocks that have literal indented multi-line text
*
* @param {terrace_document_t*} doc A pointer to the Terrace document being parsed
* @param {int} startOffset How many indent characters to skip before outputting the line contents. Defaults to the current indent level
* @param {int} startOffset 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`
*/
char* terrace_line(terrace_document_t* doc, int startOffset) {
@@ -92,7 +94,7 @@ char* terrace_line(terrace_document_t* doc, int startOffset) {
* 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.
* 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.
*
@@ -103,16 +105,16 @@ char* terrace_line(terrace_document_t* doc, int startOffset) {
* ```terrace
* title An Important Document
* ```
* @param {terrace_document_t*} doc A pointer to the Terrace document being parsed
* @param {terrace_document_t*} doc A pointer to the current document state struct.
* @returns {int} The length of the `head` portion (first word) of a line
*/
int terrace_head_length(terrace_document_t* doc) {
unsigned int terrace_head_length(terrace_document_t* doc) {
return doc->lineData.offsetTail - doc->lineData.offsetHead;
}
/**
* 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`
* 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
*
@@ -121,8 +123,8 @@ int terrace_head_length(terrace_document_t* doc) {
* ```terrace
* title An Important Document
* ```
* @param {terrace_document_t*} doc A pointer to the Terrace document being parsed
* @returns {char*} The remainder of the line following the `head` portion, with no leading space
* @param {terrace_document_t*} doc A pointer to the current document state struct.
* @returns {char*} The remainder of the line following the `head` portion, with no leading space.
*/
char* terrace_tail(terrace_document_t* doc) {
return doc->_currentLine + doc->lineData.offsetTail + 1;
@@ -131,7 +133,7 @@ char* terrace_tail(terrace_document_t* doc) {
/**
* Quickly check if the current line head matches a specified value. Useful in many document-parsing situations.
*
* Given the following line
* Given the following line:
*
* ```terrace
* title An Important Document
@@ -140,8 +142,9 @@ char* terrace_tail(terrace_document_t* doc) {
* `terrace_match(doc, "title")` returns `1`
* `terrace_match(doc, "somethingElse") returns `0`
*
* @param {const char*} matchValue 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
* @param {terrace_document_t*} doc A pointer to the current document state struct.
* @param {const char*} matchValue 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.
*/
char terrace_match(terrace_document_t* doc, const char* matchHead) {
// Get a pointer to the start of the head portion of the string.
@@ -168,7 +171,7 @@ char terrace_match(terrace_document_t* doc, const char* matchHead) {
* 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 `next()` will repeat this line again.
* 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.
*
@@ -179,7 +182,7 @@ char terrace_match(terrace_document_t* doc, const char* matchHead) {
* // Do something with each line.
* }
* ```
*
* @param {terrace_document_t*} doc A pointer to the current document state struct.
* @param {number} levelScope 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.
*/
@@ -209,4 +212,4 @@ char terrace_next(terrace_document_t* doc, int levelScope) {
return 1;
}
#endif
#endif

View File

@@ -14,17 +14,22 @@ typedef struct terrace_linedata_s {
unsigned int offsetTail;
} terrace_linedata_t;
terrace_linedata_t terrace_create_line_data(const char indent) {
/**
* Initialize a terrace_linedata struct with default values to pass to terrace_parse_line()
* @param {const char} indent The character to use for indenting lines. ONLY ONE CHARACTER IS CURRENTLY PERMITTED.
* @returns {terrace_linedata_t} A linedata struct with the specified indent character and all other values initialized to 0.
*/
terrace_linedata_t terrace_create_linedata(const char indent) {
terrace_linedata_t line_data = { .indent = indent, .level = 0, .offsetHead = 0, .offsetTail = 0 };
return line_data;
}
/**
* Core Terrace parser function, sets level, offsetHead, and offsetTail in a lineData struct based on the current line.
* Core Terrace parser function, sets level, offsetHead, and offsetTail in a terrace_linedata struct based on the current line.
* @param char* line A pointer to the line to parse as a C-style string. Shouldn't end with a newline.
* @param terrace_linedata_t* lineData A pointer to the terrace_linedata_t struct to store information about the current line in.
*/
void terrace_parse_line(const char *line, terrace_linedata_t *lineData) {
void terrace_parse_line(const char* line, terrace_linedata_t* lineData) {
// Empty lines are nullptr/0 as they have no characters. (The newline character should be stripped off.)
// Special case handling for these allows them to be parsed extra quickly.
if (!line) {

View File

@@ -9,7 +9,7 @@ void linedata_basic (char indent) {
size_t bufsize = 32;
ssize_t c_read = 0;
terrace_linedata_t line_data = terrace_create_line_data(indent);
terrace_linedata_t line_data = terrace_create_linedata(indent);
while(c_read = getline(&line, &bufsize, stdin)) {
if (c_read == -1) break;
@@ -28,7 +28,7 @@ void linedata_head_tail (char indent) {
size_t bufsize = 32;
ssize_t c_read = 0;
terrace_linedata_t line_data = terrace_create_line_data(indent);
terrace_linedata_t line_data = terrace_create_linedata(indent);
char *head;
char *tail;

View File

@@ -1,6 +1,4 @@
MIT License
Copyright (c) 2022 Joshua Michael Bemenderfer
Copyright (c) 2022-present Joshua Michael Bemenderfer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -1,37 +1,41 @@
{
"name": "@terrace-lang/js",
"version": "0.0.1",
"description": "Terrace is a simple structured data syntax for configuration, content authoring, and DSLs.",
"version": "0.1.0",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "https://github.com/terrace-lang/terrace.git",
"directory": "packages/js"
},
"bugs": "https://github.com/terrace-lang/terrace/issues",
"homepage": "https://terrace-lang.org",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./parser": {
"import": "./dist/parser.js",
"require": "./dist/parser.cjs"
},
"./document": {
"import": "./dist/document.js",
"require": "./dist/document.cjs"
},
"./readers/node-readline": {
"import": "./dist/readers/node-readline.js",
"require": "./dist/readers/node-readline.cjs"
},
"./readers/js-string": {
"import": "./dist/readers/js-string.js",
"require": "./dist/readers/js-string.cjs"
"./*": {
"types": "./dist/types/*.d.ts",
"import": "./dist/esm/*.js",
"require": "./dist/cjs/*.js"
}
},
"scripts": {
"test": "node ./test/index.js",
"dev": "vite build --watch",
"build": "vite build"
"dev": "run-p dev:*",
"dev:esm": "tsc --watch --project ./tsconfig.esm.json",
"dev:cjs": "tsc --watch --project ./tsconfig.cjs.json",
"dev:types": "tsc --watch --project ./tsconfig.types.json",
"build": "run-p build:*",
"build:esm": "tsc --project ./tsconfig.esm.json",
"build:cjs": "tsc --project ./tsconfig.cjs.json",
"build:types": "tsc --project ./tsconfig.types.json"
},
"devDependencies": {
"vite": "^3.2.3",
"vitest": "^0.24.5"
"@types/node": "^18.14.0",
"npm-run-all": "^4.1.5",
"typescript": "^4.9.5"
},
"engines": {
"node": ">=17.0.0",
"npm": ">=7.0.0"
}
}

View File

@@ -1,5 +1,5 @@
import type { Reader } from './readers/reader'
import { createLineData, parseLine } from './parser'
import type { Reader } from './readers/reader.js'
import { createLineData, parseLine } from './parser.js'
// Container for a handful of convenience functions for parsing documents
// Obtained from useDocument() below

View File

@@ -1,2 +1,2 @@
export * from './parser'
export * from './document'
export * from './parser.js'
export * from './document.js'

View File

@@ -1,4 +1,4 @@
import type { Reader } from './reader'
import type { Reader } from './reader.js'
/**
* Get a simple `Reader` function that always returns the next line

View File

@@ -1,6 +1,6 @@
import fs from 'node:fs'
import readline from 'node:readline/promises'
import type { Reader } from './reader'
import fs from 'fs'
import readline from 'readline/promises'
import type { Reader } from './reader.js'
/**

View File

@@ -1,18 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node 18",
"include": ["index.d.ts", "src/**/*"],
"compilerOptions": {
"lib": ["ES2022"],
"module": "ES2022",
"target": "ES2022",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "CommonJS",
"target": "ES2020",
"outDir": "./dist/cjs/",
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ES2020",
"target": "ES2020",
"outDir": "./dist/esm/",
}
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"declarationMap": true,
"declarationDir": "./dist/types",
}
}

View File

@@ -1,23 +0,0 @@
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: {
'index': 'src/index.ts',
'document': 'src/document.ts',
'parser': 'src/parser.ts',
'readers/js-string': 'src/readers/js-string.ts',
'readers/node-readline': 'src/readers/node-readline.ts',
}
},
rollupOptions: {
external: [
`node:fs`,
`node:readline/promises`
]
}
}
})