patch test bug incorrectly oriented square brackets

This commit is contained in:
Sorrel Bri 2020-05-21 19:36:43 -07:00
parent dfae87e408
commit bb69a9ffa4
5 changed files with 861 additions and 792 deletions

View file

@ -73,12 +73,6 @@ var grammar = {
: t), : t),
) )
}, },
{"name": "setAlias", "symbols": [(lexer.has("comma") ? {type: "comma"} : comma), "_", (lexer.has("setIdentifier") ? {type: "setIdentifier"} : setIdentifier)], "postprocess": pipe(
d => d && d.length ? d.filter(t => !!t) : d,
d => d.map(t => t.type === 'setIdentifier' ? t.toString() : null),
d => d.filter(t => !!t),
d => ({type: 'alias', alias: d }),
) },
{"name": "setExpression", "symbols": [(lexer.has("openSquareBracket") ? {type: "openSquareBracket"} : openSquareBracket), "_", "phoneList", "_", (lexer.has("closeSquareBracket") ? {type: "closeSquareBracket"} : closeSquareBracket)]}, {"name": "setExpression", "symbols": [(lexer.has("openSquareBracket") ? {type: "openSquareBracket"} : openSquareBracket), "_", "phoneList", "_", (lexer.has("closeSquareBracket") ? {type: "closeSquareBracket"} : closeSquareBracket)]},
{"name": "setExpression$ebnf$1$subexpression$1", "symbols": ["setOperation"]}, {"name": "setExpression$ebnf$1$subexpression$1", "symbols": ["setOperation"]},
{"name": "setExpression$ebnf$1", "symbols": ["setExpression$ebnf$1$subexpression$1"], "postprocess": id}, {"name": "setExpression$ebnf$1", "symbols": ["setExpression$ebnf$1$subexpression$1"], "postprocess": id},
@ -90,6 +84,12 @@ var grammar = {
d => d.map(t => t.map(u => u[0])), d => d.map(t => t.map(u => u[0])),
flag('setExpression') flag('setExpression')
) }, ) },
{"name": "setAlias", "symbols": [(lexer.has("comma") ? {type: "comma"} : comma), "_", (lexer.has("setIdentifier") ? {type: "setIdentifier"} : setIdentifier)], "postprocess": pipe(
d => d && d.length ? d.filter(t => !!t) : d,
d => d.map(t => t.type === 'setIdentifier' ? t.toString() : null),
d => d.filter(t => !!t),
d => ({type: 'alias', alias: d }),
) },
{"name": "phoneList$ebnf$1", "symbols": []}, {"name": "phoneList$ebnf$1", "symbols": []},
{"name": "phoneList$ebnf$1$subexpression$1$ebnf$1", "symbols": []}, {"name": "phoneList$ebnf$1$subexpression$1$ebnf$1", "symbols": []},
{"name": "phoneList$ebnf$1$subexpression$1$ebnf$1$subexpression$1", "symbols": [(lexer.has("comma") ? {type: "comma"} : comma), "_"]}, {"name": "phoneList$ebnf$1$subexpression$1$ebnf$1$subexpression$1", "symbols": [(lexer.has("comma") ? {type: "comma"} : comma), "_"]},

View file

@ -72,13 +72,6 @@ setDefinition -> %setIdentifier (setAlias):? __ equal __ setExpression
: t), : t),
) )
%} %}
setAlias -> %comma _ %setIdentifier
{% pipe(
d => d && d.length ? d.filter(t => !!t) : d,
d => d.map(t => t.type === 'setIdentifier' ? t.toString() : null),
d => d.filter(t => !!t),
d => ({type: 'alias', alias: d }),
) %}
setExpression -> %openSquareBracket _ phoneList _ %closeSquareBracket setExpression -> %openSquareBracket _ phoneList _ %closeSquareBracket
| %openCurlyBracket _ (setOperation):? _ %closeCurlyBracket | %openCurlyBracket _ (setOperation):? _ %closeCurlyBracket
{% {%
@ -88,6 +81,15 @@ setExpression -> %openSquareBracket _ phoneList _ %closeSquareBracket
d => d.map(t => t.map(u => u[0])), d => d.map(t => t.map(u => u[0])),
flag('setExpression') flag('setExpression')
) %} ) %}
setAlias -> %comma _ %setIdentifier
{% pipe(
d => d && d.length ? d.filter(t => !!t) : d,
d => d.map(t => t.type === 'setIdentifier' ? t.toString() : null),
d => d.filter(t => !!t),
d => ({type: 'alias', alias: d }),
) %}
phoneList -> (%phone (%comma _):* ):* phoneList -> (%phone (%comma _):* ):*
{% {%
pipe( pipe(

View file

@ -1,21 +1,28 @@
const moo = require('moo'); const moo = require("moo");
const lexer = moo.states({ const lexer = moo.states({
main: { main: {
comment: /;.*$/, comment: /;.*$/,
star: { match: /\*/, push: 'epoch' }, star: { match: /\*/, push: "epoch" },
slash: { match: /\//, push: 'lexicon' }, slash: { match: /\//, push: "lexicon" },
// change so that identifiers are always upper, keywords are always lower, phones are always lower // change so that identifiers are always upper, keywords are always lower, phones are always lower
'kwSet': { match: 'set', type: moo.keywords({ 'kwSet': 'set '}), push: 'setDefinition'}, kwSet: {
identifier: { match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/, }, match: "set",
openBracket: { match: /\[/, push: 'feature' }, type: moo.keywords({ kwSet: "set " }),
push: "setDefinition",
},
identifier: { match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/ },
openBracket: { match: /\[/, push: "feature" },
whiteSpace: { match: /\s+/, lineBreaks: true }, whiteSpace: { match: /\s+/, lineBreaks: true },
newLine: { match: /\n+/, lineBreaks: true } newLine: { match: /\n+/, lineBreaks: true },
}, },
epoch: { epoch: {
identifier: { match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/, push: 'rule' }, identifier: {
openParen: { match: /\(/, push: 'ruleDefinition' }, match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/,
push: "rule",
},
openParen: { match: /\(/, push: "ruleDefinition" },
pipe: { match: /\|/, pop: true }, pipe: { match: /\|/, pop: true },
greaterThan: /\>/, greaterThan: /\>/,
arrow: /\-\>/, arrow: /\-\>/,
@ -23,60 +30,60 @@ const lexer = moo.states({
slash: /\//, slash: /\//,
dot: /\./, dot: /\./,
underscore: /\_/, underscore: /\_/,
newLine: { match: /\n/, lineBreaks: true } newLine: { match: /\n/, lineBreaks: true },
}, },
ruleDefinition: { ruleDefinition: {
doubleTick: { match: /``/, push: 'ruleName' }, doubleTick: { match: /``/, push: "ruleName" },
singleTick: { match: /`/, push: 'ruleDescription' }, singleTick: { match: /`/, push: "ruleDescription" },
// push rule // push rule
closeParen: { match: /\)/, pop: true }, closeParen: { match: /\)/, pop: true },
newLine: { match: /\n/, lineBreaks: true } newLine: { match: /\n/, lineBreaks: true },
}, },
ruleName: { ruleName: {
ruleName: { match: /.+(?=``)/ }, ruleName: { match: /.+(?=``)/ },
doubleTick: { match: /``/, pop: true } doubleTick: { match: /``/, pop: true },
}, },
ruleDescription: { ruleDescription: {
ruleDescription: { match: /.+(?=`)/ }, ruleDescription: { match: /.+(?=`)/ },
singleTick: { match: /`/, pop: true } singleTick: { match: /`/, pop: true },
}, },
rule: { rule: {
openSquareBracket: { match: /\[/, push: 'ruleFeature' }, openSquareBracket: { match: /\[/, push: "ruleFeature" },
// whiteSpace: { match: /\s/ }, // whiteSpace: { match: /\s/ },
newLine: { match: /\n/, pop: true, lineBreaks: true } newLine: { match: /\n/, pop: true, lineBreaks: true },
}, },
ruleFeature: { ruleFeature: {
ruleFeature: { match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/ }, ruleFeature: { match: /[A-Za-z]+[\u00c0-\u03FFA-Za-z0-9\\-\\_]*/ },
closeBracket: { match: /\]/, pop: true }, closeBracket: { match: /\]/, pop: true },
newLine: { match: /\n/, lineBreaks: true } newLine: { match: /\n/, lineBreaks: true },
}, },
lexicon: { lexicon: {
slash: { match: /\//, pop: true }, slash: { match: /\//, pop: true },
newLine: { match: /\n/, lineBreaks: true } newLine: { match: /\n/, lineBreaks: true },
}, },
feature: { feature: {
closeBracket: { match: /\]/, pop: true }, closeBracket: { match: /\]/, pop: true },
positiveAssignment: /\+=/, positiveAssignment: /\+=/,
negativeAssignment: /\-=/, negativeAssignment: /\-=/,
newLine: { match: /\n/, lineBreaks: true } newLine: { match: /\n/, lineBreaks: true },
}, },
setDefinition: { setDefinition: {
comment: /;.*$/, comment: /;.*$/,
setIdentifier: { match: /[A-Z]+[A-Z_]*/ }, setIdentifier: { match: /[A-Z]+[A-Z_]*/ },
openCurlyBracket: { match: /\{/, push: 'setOperation' }, openCurlyBracket: { match: /\{/, push: "setOperation" },
equal: /=/, equal: /=/,
openSquareBracket: /\[/, openSquareBracket: /\[/,
phone: /[\u00c0-\u03FFa-z]+/, phone: /[\u00c0-\u03FFa-z]+/,
closeSquareBracket: { match: /\]/ }, closeSquareBracket: { match: /\]/ },
comma: { match: /,/, push: 'commaOperation' }, comma: { match: /,/, push: "commaOperation" },
whiteSpace: { match: /[\t ]+/ }, whiteSpace: { match: /[\t ]+/ },
newLine: { match: /\n/, pop: true, lineBreaks: true }, newLine: { match: /\n/, pop: true, lineBreaks: true },
}, },
@ -84,21 +91,23 @@ const lexer = moo.states({
setOperation: { setOperation: {
closeCurlyBracket: { match: /\}/, pop: true }, closeCurlyBracket: { match: /\}/, pop: true },
// ! restrict identifiers // ! restrict identifiers
keyword: { match: ['not', 'and', 'or', 'nor', 'in', 'yield', 'concat', 'dissoc'], type: moo.keywords({ keyword: {
'kwSetNot': 'not' , match: ["not", "and", "or", "nor", "in", "yield", "concat", "dissoc"],
'kwSetAnd': 'and' , type: moo.keywords({
'kwSetOr': 'or' , kwSetNot: "not",
'kwSetNor': 'nor' , kwSetAnd: "and",
'kwSetIn': 'in' , kwSetOr: "or",
'kwSetYield': 'yield' , kwSetNor: "nor",
'kwSetConcat': 'concat', kwSetIn: "in",
'kwSetDissoc': 'dissoc' kwSetYield: "yield",
}) kwSetConcat: "concat",
kwSetDissoc: "dissoc",
}),
}, },
identifier: /[A-Z]+[A-Z_]+/, identifier: /[A-Z]+[A-Z_]+/,
whiteSpace: { match: /\s+/, lineBreaks: true }, whiteSpace: { match: /\s+/, lineBreaks: true },
openSquareBracket: /\]/, openSquareBracket: /\[/,
closeSquareBracket: /\[/, closeSquareBracket: /\]/,
identifier: /[A-Z]+[A-Z_]*/, identifier: /[A-Z]+[A-Z_]*/,
phone: /[\u00c0-\u03FFa-z]+/, phone: /[\u00c0-\u03FFa-z]+/,
}, },
@ -108,9 +117,8 @@ const lexer = moo.states({
// this prevents popping back to main // this prevents popping back to main
comment: /\s*;.*$/, comment: /\s*;.*$/,
whiteSpace: { match: /\s+/, lineBreaks: true, pop: true }, whiteSpace: { match: /\s+/, lineBreaks: true, pop: true },
newLine: { match: /\n/, lineBreaks: true, pop: true } newLine: { match: /\n/, lineBreaks: true, pop: true },
} },
}); });
module.exports = {lexer}; module.exports = { lexer };

File diff suppressed because it is too large Load diff

View file

@ -1,44 +1,43 @@
import { lexer } from '../lexer'; import { lexer } from "../lexer";
import { parser } from '../parser'; import { parser } from "../parser";
import { assertionData } from './assertionData'; import { assertionData } from "./assertionData";
describe('parser', () => { describe("parser", () => {
it('parses simple comment', () => { it("parses simple comment", () => {
const { latl, AST } = assertionData.simpleComment; const { latl, AST } = assertionData.simpleComment;
const feedResults = parser().feed(latl).results; const feedResults = parser().feed(latl).results;
expect(feedResults.length).toBe(1); expect(feedResults.length).toBe(1);
expect(feedResults[0]).toStrictEqual(AST) expect(feedResults[0]).toStrictEqual(AST);
}) });
it('parses simple set definition', () => { it("parses simple set definition", () => {
const { latl, AST } = assertionData.simpleSetDefinition; const { latl, AST } = assertionData.simpleSetDefinition;
const feedResults = parser().feed(latl).results; const feedResults = parser().feed(latl).results;
expect(feedResults.length).toBe(1); expect(feedResults.length).toBe(1);
expect(feedResults[0]).toStrictEqual(AST); expect(feedResults[0]).toStrictEqual(AST);
}) });
it('parses multiple set definitions with comma operator', () => { it("parses multiple set definitions with comma operator", () => {
const { latl, AST } = assertionData.commaSetDefinition; const { latl, AST } = assertionData.commaSetDefinition;
const feedResults = parser().feed(latl).results; const feedResults = parser().feed(latl).results;
expect(feedResults.length).toBe(1); expect(feedResults.length).toBe(1);
expect(feedResults[0]).toStrictEqual(AST); expect(feedResults[0]).toStrictEqual(AST);
}); });
it('lexes set definition with alias' it("lexes set definition with alias", () => {
, () => {
const { latl, AST } = assertionData.setAliasDefinition; const { latl, AST } = assertionData.setAliasDefinition;
const feedResults = parser().feed(latl).results; const feedResults = parser().feed(latl).results;
expect(feedResults[0]).toStrictEqual(AST); expect(feedResults[0]).toStrictEqual(AST);
} });
);
it('lexes set definition with set join', () => { it.skip("lexes set definition with set join", () => {
const { latl, AST } = assertionData.setDefinitionJoin; const { latl, AST } = assertionData.setDefinitionJoin;
const feedResults = parser().feed(latl).results; const feedResults = parser().feed(latl).results;
expect(feedResults[0]).toStrictEqual(AST); expect(feedResults[0]).toStrictEqual(AST);
}); });
it.todo('lexes set definition with yield operation' it.todo(
"lexes set definition with yield operation"
// , () => { // , () => {
// const { latl, tokens } = assertionData.setDefinitionYield; // const { latl, tokens } = assertionData.setDefinitionYield;
// const stream = getStream(latl); // const stream = getStream(latl);
@ -46,7 +45,8 @@ describe('parser', () => {
// } // }
); );
it.todo('lexes all set join operations' it.todo(
"lexes all set join operations"
// , () => { // , () => {
// const { latl, tokens } = assertionData.setOperationsJoin; // const { latl, tokens } = assertionData.setOperationsJoin;
// const stream = getStream(latl); // const stream = getStream(latl);
@ -54,14 +54,15 @@ describe('parser', () => {
// } // }
); );
it.todo('lexes set filter, concat, and dissoc operations' it.todo(
"lexes set filter, concat, and dissoc operations"
// , () => { // , () => {
// const { latl, tokens } = assertionData.setOperations; // const { latl, tokens } = assertionData.setOperations;
// const stream = getStream(latl); // const stream = getStream(latl);
// expect(stream).toStrictEqual(tokens); // expect(stream).toStrictEqual(tokens);
// } // }
) );
}) });
// { // {
// "set": // "set":