/** * Expr-lang token types and AST definitions */ export enum TokenKind { Identifier = 'Identifier', Number = 'Number', String = 'String', Operator = 'Operator', Bracket = 'Bracket', EOF = 'EOF', } export interface Token { kind: TokenKind; value: string; start: number; end: number; line: number; column: number; } export interface ParseError { message: string; startLine: number; startColumn: number; endLine: number; endColumn: number; } export const EOF_TOKEN: Token = { kind: TokenKind.EOF, value: '', start: 0, end: 0, line: 0, column: 0, }; // Operator precedence (higher = binds tighter) export const OPERATOR_PRECEDENCE: Record = { '??': 1, '||': 2, or: 2, '&&': 3, and: 3, '==': 4, '!=': 4, '<': 5, '>': 5, '<=': 5, '>=': 5, in: 5, matches: 5, contains: 5, startsWith: 5, endsWith: 5, '+': 6, '-': 6, '*': 7, '/': 7, '%': 7, '^': 8, '**': 8, }; // Unary operators export const UNARY_OPERATORS = new Set(['!', 'not', '-']); // Right-associative operators export const RIGHT_ASSOCIATIVE = new Set(['**', '^']); // Comparison operators (for chained comparisons) export const COMPARISON_OPERATORS = new Set(['<', '>', '<=', '>=', '==', '!=']); // Keywords export const KEYWORDS = new Set(['let', 'true', 'false', 'nil', 'in', 'not', 'and', 'or', 'if', 'else']);