@taml/parser
Version:
Parser for TAML (Terminal ANSI Markup Language) that generates AST nodes
292 lines • 22.5 kB
JavaScript
/**
* Main TAML parser that converts tokens to AST
*/
import { createDocument, createElement, createText, isDocumentNode, isElementNode, isTextNode, } from "@taml/ast";
import { isCloseTagToken, isEofToken, isOpenTagToken, isTextToken, tokenize, } from "./tokenizer.js";
import { MismatchedTagError, UnclosedTagError } from "./errors.js";
/**
* TAML Parser class
*/
export class TamlParser {
source;
constructor(source) {
this.source = source;
}
/**
* Parse the TAML source into an AST
*/
parse() {
const tokens = tokenize(this.source);
const context = {
tokens,
position: 0,
source: this.source,
tagStack: [],
};
const children = this.parseNodes(context);
// Check for unclosed tags
if (context.tagStack.length > 0) {
const unclosedTag = context.tagStack[context.tagStack.length - 1];
if (unclosedTag) {
throw new UnclosedTagError(unclosedTag.tagName, unclosedTag.token.start, unclosedTag.token.line, unclosedTag.token.column, this.source);
}
}
return createDocument(children, 0, this.source.length);
}
/**
* Parse with options including depth checking
*/
parseWithOptions(options) {
const tokens = tokenize(this.source);
const context = {
tokens,
position: 0,
source: this.source,
tagStack: [],
};
const children = this.parseNodesWithDepth(context, 0, options.maxDepth);
// Check for unclosed tags
if (context.tagStack.length > 0) {
const unclosedTag = context.tagStack[context.tagStack.length - 1];
if (unclosedTag) {
throw new UnclosedTagError(unclosedTag.tagName, unclosedTag.token.start, unclosedTag.token.line, unclosedTag.token.column, this.source);
}
}
return createDocument(children, 0, this.source.length);
}
/**
* Parse nodes with depth checking
*/
parseNodesWithDepth(context, currentDepth, maxDepth) {
if (currentDepth > maxDepth) {
throw new Error(`Maximum nesting depth of ${maxDepth} exceeded`);
}
const nodes = [];
while (context.position < context.tokens.length) {
const token = context.tokens[context.position];
if (!token) {
break;
}
if (isEofToken(token)) {
break;
}
if (isCloseTagToken(token)) {
// This will be handled by the calling context
break;
}
if (isOpenTagToken(token)) {
const element = this.parseElementWithDepth(context, currentDepth, maxDepth);
nodes.push(element);
}
else if (isTextToken(token)) {
const text = this.parseText(context);
nodes.push(text);
}
else {
// Skip unexpected tokens
context.position++;
}
}
return nodes;
}
/**
* Parse an element with depth checking
*/
parseElementWithDepth(context, currentDepth, maxDepth) {
const openToken = context.tokens[context.position];
if (!openToken || !isOpenTagToken(openToken)) {
throw new Error("Expected open tag token");
}
context.position++; // Move past opening tag
// Push tag onto stack for tracking
context.tagStack.push({
tagName: openToken.tagName,
token: openToken,
});
// Parse children with incremented depth
const children = this.parseNodesWithDepth(context, currentDepth + 1, maxDepth);
// Check for closing tag
if (context.position >= context.tokens.length) {
throw new UnclosedTagError(openToken.tagName, openToken.start, openToken.line, openToken.column, this.source);
}
const closeToken = context.tokens[context.position];
if (!closeToken || !isCloseTagToken(closeToken)) {
throw new UnclosedTagError(openToken.tagName, openToken.start, openToken.line, openToken.column, this.source);
}
// Verify tag names match
if (closeToken.tagName !== openToken.tagName) {
throw new MismatchedTagError(openToken.tagName, closeToken.tagName, closeToken.start, closeToken.line, closeToken.column, this.source);
}
context.position++; // Move past closing tag
context.tagStack.pop(); // Remove from tag stack
return createElement(openToken.tagName, children, openToken.start, closeToken.end);
}
/**
* Parse a sequence of nodes until we hit EOF or a closing tag
*/
parseNodes(context) {
const nodes = [];
while (context.position < context.tokens.length) {
const token = context.tokens[context.position];
if (!token) {
break;
}
if (isEofToken(token)) {
break;
}
if (isCloseTagToken(token)) {
// This will be handled by the calling context
break;
}
if (isOpenTagToken(token)) {
const element = this.parseElement(context);
nodes.push(element);
}
else if (isTextToken(token)) {
const text = this.parseText(context);
nodes.push(text);
}
else {
// Skip unexpected tokens
context.position++;
}
}
return nodes;
}
/**
* Parse an element (opening tag + children + closing tag)
*/
parseElement(context) {
const openToken = context.tokens[context.position];
if (!openToken || !isOpenTagToken(openToken)) {
throw new Error("Expected open tag token");
}
context.position++; // Move past opening tag
// Push tag onto stack for tracking
context.tagStack.push({
tagName: openToken.tagName,
token: openToken,
});
// Parse children
const children = this.parseNodes(context);
// Check for closing tag
if (context.position >= context.tokens.length) {
throw new UnclosedTagError(openToken.tagName, openToken.start, openToken.line, openToken.column, this.source);
}
const closeToken = context.tokens[context.position];
if (!closeToken || !isCloseTagToken(closeToken)) {
throw new UnclosedTagError(openToken.tagName, openToken.start, openToken.line, openToken.column, this.source);
}
// Verify tag names match
if (closeToken.tagName !== openToken.tagName) {
throw new MismatchedTagError(openToken.tagName, closeToken.tagName, closeToken.start, closeToken.line, closeToken.column, this.source);
}
context.position++; // Move past closing tag
context.tagStack.pop(); // Remove from tag stack
return createElement(openToken.tagName, children, openToken.start, closeToken.end);
}
/**
* Parse a text node
*/
parseText(context) {
const token = context.tokens[context.position];
if (!token || !isTextToken(token)) {
throw new Error("Expected text token");
}
context.position++;
return createText(token.content, token.start, token.end);
}
/**
* Get current token without advancing
*/
peek(context) {
return context.position < context.tokens.length
? (context.tokens[context.position] ?? null)
: null;
}
/**
* Get current parser state for debugging
*/
getDebugInfo(context) {
return {
position: context.position,
currentToken: this.peek(context),
tagStack: context.tagStack.map((entry) => entry.tagName),
};
}
}
/**
* Convenience function to parse TAML source text
*/
export function parseTaml(source, options) {
const parser = new TamlParser(source);
// Apply default options
const opts = {
includePositions: true,
maxDepth: 100,
...options,
};
// Parse with depth checking and position options
const ast = parser.parseWithOptions(opts);
// If position information should be excluded, strip it
if (!opts.includePositions) {
return stripPositions(ast);
}
return ast;
}
/**
* Parse TAML and return the AST with error context
*/
export function parseTamlSafe(source, options) {
try {
const ast = parseTaml(source, options);
return { success: true, ast };
}
catch (error) {
return {
success: false,
error: error instanceof Error ? error : new Error(String(error)),
};
}
}
/**
* Validate TAML syntax without building full AST
*/
export function validateTaml(source) {
const errors = [];
try {
parseTaml(source);
return { valid: true, errors: [] };
}
catch (error) {
if (error instanceof Error) {
errors.push(error);
}
return { valid: false, errors };
}
}
/**
* Strip position information from AST nodes (for includePositions: false option)
*/
function stripPositions(node) {
const strippedChildren = node.children.map((child) => stripPositionsFromNode(child));
return createDocument(strippedChildren, 0, 0);
}
/**
* Recursively strip position information from any AST node
*/
function stripPositionsFromNode(node) {
if (isDocumentNode(node)) {
const strippedChildren = node.children.map((child) => stripPositionsFromNode(child));
return createDocument(strippedChildren, 0, 0);
}
if (isElementNode(node)) {
const strippedChildren = node.children.map((child) => stripPositionsFromNode(child));
return createElement(node.tagName, strippedChildren, 0, 0);
}
if (isTextNode(node)) {
return createText(node.content, 0, 0);
}
return node;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvcGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxFQUdMLGNBQWMsRUFDZCxhQUFhLEVBQ2IsVUFBVSxFQUNWLGNBQWMsRUFDZCxhQUFhLEVBQ2IsVUFBVSxHQUNYLE1BQU0sV0FBVyxDQUFDO0FBSW5CLE9BQU8sRUFFTCxlQUFlLEVBQ2YsVUFBVSxFQUNWLGNBQWMsRUFDZCxXQUFXLEVBQ1gsUUFBUSxHQUNULE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBWW5FOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDUTtJQUE3QixZQUE2QixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUFHLENBQUM7SUFFL0M7O09BRUc7SUFDSCxLQUFLO1FBQ0gsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyQyxNQUFNLE9BQU8sR0FBaUI7WUFDNUIsTUFBTTtZQUNOLFFBQVEsRUFBRSxDQUFDO1lBQ1gsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFFBQVEsRUFBRSxFQUFFO1NBQ2IsQ0FBQztRQUVGLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFMUMsMEJBQTBCO1FBQzFCLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDaEMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNsRSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksZ0JBQWdCLENBQ3hCLFdBQVcsQ0FBQyxPQUFP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