Skip to content

Releases: dindondanapp/tabulascript

v0.1.0 — initial public release

08 Jun 15:59

Choose a tag to compare

Initial public release. MIT licensed.

npm add @dindondanapp/tabulascript

Reference TypeScript implementation of TabulaScript — the DSL DinDonDan uses to describe church mass timetables. Pure, isomorphic, zero runtime dependencies, ESM-only, Node ≥ 20.

Added

  • parse(source, env) — line-oriented lexer + recursive-descent parser + Pratt date-expression parser, producing a typed TabulaAST. Line-accurate TabulaError diagnostics throughout.
  • evaluate(ast, env, range) — pure, isomorphic day-iteration evaluator producing a DayMap keyed by "YYYY-MM-DD". Last-matching-case-wins per block (the seam applyOverrides rides).
  • applyOverrides(ast, overrides) + buildOverride(...) + condition helpers (dateRangeCondition, weekdayCondition, holidayCondition, eveCondition, etc.). Host-injected case shape stays stable across AST evolutions.
  • defaultKeywords — multilingual alias tables covering all 10 supported DinDonDan locales (it, en, es, fr, de, pt, pl, ar, zh, ja). The !-suffix maps to the weekday only (dom! → Sunday weekday, not the holiday wildcard).
  • CivilDate primitive — TZ-free {y, m, d} + addDays / compare / weekday / daysInMonth etc. Built on Howard Hinnant's epoch-day algorithm.
  • defaultHolidayCalendar / defaultEveCalendar — Italian civic defaults. Override per-country via Env.holidays / Env.eves.
  • Language-neutral specification — spec/grammar.ebnf, spec/semantics.md, and spec/ast-schema.json (generated from src/types.ts).
  • Conformance test harness at test/conformance/corpus.test.ts, run against a synthetic golden corpus.

Notable semantics

These behaviours are deliberate and locked by tests:

  • > / < require a weekday on the LHS; a non-weekday LHS is a parse-time error.
  • Date arithmetic (+ / -) is pure civil-day arithmetic — no timezone or DST effects.
  • A variable name colliding with a keyword alias is rejected at parse time rather than shadowing the keyword. Inherited object property names (constructor, __proto__, …) are never treated as variables.
  • Time strings are normalised to zero-padded HH:MM.
  • All four binary operators (>, <, +, -) share one precedence level and are left-associative.
  • Any out-of-range day is clamped to the last day of its month (so 30/2 and 31/2 both resolve to Feb 28/29, 31/4 to Apr 30); it never spills into the next month. The d == 31 "last day of the month" idiom is the common case of this rule.
  • Single-operand conditions are point intervals; // is a comment only at line start; - is both the range separator and the subtract-days operator, disambiguated by lookahead (a - before a bare integer subtracts; any other - separates a range); hours accept ≤ 24 and minutes ≤ 60.
  • Within a block, the last matching case wins (the seam applyOverrides relies on).
  • Parenthesis nesting in date expressions is capped (MAX_EXPR_DEPTH), so malformed deeply-nested input raises TabulaError rather than overflowing the call stack.