ima-parse
Version:
Easy Simple Parser, that only requires a Grammar JSON to output an AST.
160 lines (158 loc) • 7.59 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Parser_1 = require("../Parser");
const testHelpers_1 = require("./testHelpers");
describe("Parser", () => {
let grammar;
let parser;
beforeEach(() => {
grammar = {
TopLevel: { name: "TopLevel", definition: [] },
global: { type: "rules", optional: true, key: "content", rules: [] }
};
parser = new Parser_1.Parser(grammar);
});
it("should flag any input as invalid when there are no rules on the top level", () => {
// Arrange
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [] });
// Act
parser.parseText(`import * from "path"`);
// Assert
expect(parser.getTopLevelParser().parsedParts.length).toStrictEqual(0);
expect(parser.brokenContent).toEqual([
{
content: "import",
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 1, ln: 1 }, end: { col: 7, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
},
{
content: "*",
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 8, ln: 1 }, end: { col: 9, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
},
{
content: "from",
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 10, ln: 1 }, end: { col: 14, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
},
{
content: '"',
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 15, ln: 1 }, end: { col: 16, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
},
{
content: "path",
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 16, ln: 1 }, end: { col: 20, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
},
{
content: '"',
parseTrail: [{ part: 0, rule: "TopLevel" }],
position: { start: { col: 20, ln: 1 }, end: { col: 21, ln: 1 } },
reason: { parsedPart: { part: 0, rule: "TopLevel" }, type: "unexpected_phrase" }
}
]);
});
it("should flag an unknown character as broken content", () => {
// Make sure the rule exists on top level
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [testHelpers_1.importRule] });
// Act
parser.parseText(`import €* from "path"`);
// Assert
expect(parser.getTopLevelParser().parsedParts.length).toStrictEqual(1);
expect(parser.brokenContent).toEqual([
{ reason: { type: "unknown_character" }, content: "€", position: { start: { col: 8, ln: 1 }, end: { col: 9, ln: 1 } } }
]);
});
it("should flag an unfinished rule as such, but continue parsing the new rule", () => {
// Make sure the rule exists on top level
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [testHelpers_1.importRule] });
// Act
parser.parseText(`import * from import * from "path"`);
// Assert
expect(parser.getTopLevelParser().parsedParts.length).toStrictEqual(2);
expect(parser.brokenContent).toEqual([
{
reason: { type: "unfinished_rule", parsedPart: { rule: "Import", part: 2 } },
content: "import",
position: { start: { col: 15, ln: 1 }, end: { col: 21, ln: 1 } },
parseTrail: [
{ part: 2, rule: "Import" },
{ part: 0, rule: "TopLevel" }
]
}
]);
});
it("should parse a single rule completely", () => {
// Make sure the rule exists on top level
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [testHelpers_1.importRule] });
// Act
parser.parseText(`import * from "path"`);
// Assert
expect(parser.brokenContent.length).toStrictEqual(0);
expect(parser.getTopLevelParser().parsedParts.length).toStrictEqual(1);
});
it("should be able to handle newlines", () => {
// Make sure the rule exists on top level
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [testHelpers_1.asteriskRule] });
// Act
parser.parseText(`*
*
*`);
// Assert
expect(parser.brokenContent.length).toStrictEqual(0);
const parts = parser.getTopLevelParser().parsedParts;
expect(parts.length).toStrictEqual(3);
expect(parts[0].childParser.getPosition()).toEqual({ start: { ln: 1, col: 1 }, end: { ln: 1, col: 2 } });
expect(parts[1].childParser.getPosition()).toEqual({ start: { ln: 2, col: 9 }, end: { ln: 2, col: 10 } });
expect(parts[2].childParser.getPosition()).toEqual({ start: { ln: 4, col: 9 }, end: { ln: 4, col: 10 } });
});
it("should be able to handle texts that don't include their end phrase", () => {
// Make sure the rule exists on top level
grammar.TopLevel.definition.push({ type: "rules", optional: true, key: "content", rules: [testHelpers_1.asteriskRule, testHelpers_1.anyTextRule] });
// Act
parser.parseText(`
*any*
**hi*
`);
// Assert
expect(parser.brokenContent.length).toStrictEqual(0);
const parts = parser.getTopLevelParser().parsedParts;
expect(parts.length).toStrictEqual(7);
const parsedParts = parts.flatMap(p => p.childParser.parsedParts);
expect(parsedParts).toEqual([
{ index: 0, type: "simple", value: ["*"], startPos: { col: 9, ln: 2 }, endPos: { col: 10, ln: 2 }, isFinished: true },
{
index: 0,
type: "simple",
value: ["any"],
startPos: { col: 10, ln: 2 },
endPos: { col: 13, ln: 2 },
ignoredPhrase: true,
overrideSamePart: true,
textMode: false,
isFinished: true
},
{ index: 0, type: "simple", value: ["*"], startPos: { col: 14, ln: 2 }, endPos: { col: 15, ln: 2 }, isFinished: true },
{ index: 0, type: "simple", value: ["*"], startPos: { col: 9, ln: 3 }, endPos: { col: 10, ln: 3 }, isFinished: true },
{ index: 0, type: "simple", value: ["*"], startPos: { col: 10, ln: 3 }, endPos: { col: 11, ln: 3 }, isFinished: true },
{
index: 0,
type: "simple",
value: ["hi"],
startPos: { col: 11, ln: 3 },
endPos: { col: 13, ln: 3 },
ignoredPhrase: true,
isFinished: true,
overrideSamePart: true,
textMode: false
},
{ index: 0, type: "simple", value: ["*"], startPos: { col: 14, ln: 3 }, endPos: { col: 15, ln: 3 }, isFinished: true }
]);
});
});