UNPKG

@taml/parser

Version:

Parser for TAML (Terminal ANSI Markup Language) that generates AST nodes

292 lines 22.5 kB
/** * 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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