UNPKG

clarity-pattern-parser

Version:

Parsing Library for Typescript and Javascript.

142 lines (112 loc) 5.23 kB
import { patterns } from "../grammar/patterns"; import { Context } from "./Context"; import { Literal } from "./Literal"; import { Reference } from "./Reference"; import { Sequence } from "./Sequence"; import { Regex } from "./Regex"; describe("Context", () => { test("Basic", () => { const john = new Literal("john", "John"); const space = new Literal("space", " "); const jane = new Literal("jane", "Jane"); const spaceReference = new Reference("space"); const names = new Sequence("names", [john, spaceReference, jane]); const context = new Context("context", names, [space, names]); const { ast } = context.exec("John Jane"); expect(ast?.toString()).toBe("John Jane"); }); test("With Grammar", ()=>{ const {names} = patterns` names = john + space + jane john = "John" jane = "Jane" space = " " `; const { ast } = names.exec("John Jane"); expect(ast?.toString()).toBe("John Jane"); }); test("test() returns boolean match through context", () => { const john = new Literal("john", "John"); const space = new Literal("space", " "); const jane = new Literal("jane", "Jane"); const spaceReference = new Reference("space"); const names = new Sequence("names", [john, spaceReference, jane]); const context = new Context("context", names, [space]); expect(context.test("John Jane")).toBe(true); expect(context.test("John Bob")).toBe(false); }); test("getPatternsWithinContext lists sibling patterns", () => { const john = new Literal("john", "John"); const space = new Literal("space", " "); const jane = new Literal("jane", "Jane"); const spaceReference = new Reference("space"); const names = new Sequence("names", [john, spaceReference, jane]); const context = new Context("context", names, [space, jane]); const available = context.getPatternsWithinContext(); expect(available["space"]).toBeDefined(); expect(available["space"].name).toBe("space"); expect(available["jane"]).toBeDefined(); expect(available["jane"].name).toBe("jane"); }); test("getPatternsWithinContext returns a copy (not internal state)", () => { const space = new Literal("space", " "); const inner = new Literal("x", "x"); const context = new Context("ctx", inner, [space]); const a = context.getPatternsWithinContext(); const b = context.getPatternsWithinContext(); expect(a).not.toBe(b); expect(a).toEqual(b); }); test("isEqual compares two contexts with same structure", () => { const inner = new Literal("x", "x"); const a = new Context("ctx", inner); const b = new Context("ctx", inner); expect(a.isEqual(b)).toBe(true); const c = new Context("ctx", new Literal("y", "y")); expect(a.isEqual(c)).toBe(false); }); test("find locates a pattern within the context's child", () => { const john = new Literal("john", "John"); const jane = new Literal("jane", "Jane"); const names = new Sequence("names", [john, jane]); const context = new Context("ctx", names); const found = context.find(p => p.name === "jane"); expect(found).not.toBeNull(); expect(found!.name).toBe("jane"); const notFound = context.find(p => p.name === "bob"); expect(notFound).toBeNull(); }); test("standalone introspection methods return empty (no parent)", () => { const inner = new Literal("x", "x"); const context = new Context("ctx", inner); expect(context.getTokensAfter(inner)).toEqual([]); expect(context.getNextTokens()).toEqual([]); expect(context.getPatternsAfter(inner)).toEqual([]); expect(context.getNextPatterns()).toEqual([]); }); test("introspection delegates to parent when embedded in sequence", () => { const inner = new Regex("word", "[a-z]+"); const context = new Context("ctx", inner); const semi = new Literal("semi", ";"); const seq = new Sequence("stmt", [context, semi]); const ctxInSeq = seq.children[0]; expect(ctxInSeq.getNextTokens()).toEqual([";"]); expect(ctxInSeq.getNextPatterns().length).toBe(1); // getTokensAfter/getPatternsAfter delegate with child reference const child = ctxInSeq.children[0]; expect(ctxInSeq.getTokensAfter(child)).toEqual([";"]); expect(ctxInSeq.getPatternsAfter(child).length).toBe(1); }); test("getTokens delegates to inner pattern", () => { const inner = new Literal("hello", "hello"); const context = new Context("ctx", inner); expect(context.getTokens()).toEqual(["hello"]); }); test("getPatterns delegates to inner pattern", () => { const inner = new Literal("x", "x"); const context = new Context("ctx", inner); const patterns = context.getPatterns(); expect(patterns).toHaveLength(1); expect(patterns[0].name).toBe("x"); }); });