Skip to content

Commit

Permalink
Group syntax entities by combinator precedence
Browse files Browse the repository at this point in the history
  • Loading branch information
frenic committed Apr 5, 2018
1 parent 80512fe commit db9f7a8
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 27 deletions.
59 changes: 50 additions & 9 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ export enum Component {
Group,
}

// Higher number is higher precedence
export enum Combinator {
/** Components are mandatory and should appear in that order */
Juxtaposition,
Juxtaposition = 0,
/** Components are mandatory but may appear in any order */
DoubleAmpersand,
DoubleAmpersand = 1,
/** At least one of the components must be present, and they may appear in any order */
DoubleBar,
DoubleBar = 2,
/** Exactly one of the components must be present */
SingleBar,
SingleBar = 3,
}

export enum Multiplier {
Expand Down Expand Up @@ -94,7 +95,6 @@ const REGEX_KEYWORD = /^([\w-]+)/g;

export default function parse(syntax: string): EntityType[] {
const levels: EntityType[][] = [[]];
const deepestLevel = () => levels[levels.length - 1];
let previousMatchWasComponent = false;
let entityMatch: RegExpExecArray | null;
while ((entityMatch = REGEX_ENTITY.exec(syntax))) {
Expand All @@ -118,12 +118,12 @@ export default function parse(syntax: string): EntityType[] {
} else if (value.indexOf(']') === 0) {
const definitions = levels.pop();
if (definitions) {
deepestLevel().push(componentGroupData(definitions, multiplierData(rawMultiplier)));
deepestLevel().push(componentGroupData(groupByPrecedence(definitions), multiplierData(rawMultiplier)));
}
previousMatchWasComponent = true;
continue;
} else {
if (previousMatchWasComponent === true) {
if (previousMatchWasComponent) {
deepestLevel().push(combinatorData(Combinator.Juxtaposition));
}

Expand All @@ -149,7 +149,27 @@ export default function parse(syntax: string): EntityType[] {
deepestLevel().push({ entity: Entity.Unknown, multiplier: multiplierData(rawMultiplier) });
}

return levels[0];
function deepestLevel() {
return levels[levels.length - 1];
}

return groupByPrecedence(levels[0]);
}

export function isFunction(entity: EntityType): entity is IFunction {
return entity.entity === Entity.Function;
}

export function isComponent(entity: EntityType): entity is ComponentType {
return entity.entity === Entity.Component;
}

export function isCombinator(entity: EntityType): entity is ICombinator {
return entity.entity === Entity.Combinator;
}

export function isQurlyBracetMultiplier(multiplier: MultiplierType): multiplier is IMultiplierQurlyBracet {
return multiplier.sign === Multiplier.QurlyBracet;
}

function combinatorData(combinator: Combinator, multiplier: MultiplierType | null = null): ICombinator {
Expand All @@ -173,7 +193,7 @@ function componentData(
};
}

function componentGroupData(entities: EntityType[], multiplier: MultiplierType | null): ComponentType {
function componentGroupData(entities: EntityType[], multiplier: MultiplierType | null = null): ComponentType {
return {
entity: Entity.Component,
component: Component.Group,
Expand Down Expand Up @@ -203,3 +223,24 @@ function multiplierData(raw: string[]): MultiplierType | null {
return null;
}
}

function groupByPrecedence(entities: EntityType[]): EntityType[] {
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
if (isCombinator(entity)) {
for (let a = i; a >= 0; a--) {
const adjacentEntity = entities[a];
if (isCombinator(adjacentEntity) && adjacentEntity.combinator < entity.combinator) {
return groupByPrecedence([componentGroupData(entities.slice(0, i)), ...entities.slice(i)]);
}
}
for (let a = i; a < entities.length; a++) {
const subsequentEntity = entities[a];
if (isCombinator(subsequentEntity) && subsequentEntity.combinator < entity.combinator) {
return [...entities.slice(0, i + 1), componentGroupData(groupByPrecedence(entities.slice(i + 1)))];
}
}
}
}
return entities;
}
22 changes: 4 additions & 18 deletions src/typer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import parse, {
Entity,
EntityType,
ICombinator,
IFunction,
IMultiplierQurlyBracet,
isCombinator,
isComponent,
isFunction,
isQurlyBracetMultiplier,
Multiplier,
MultiplierType,
} from './parser';
Expand Down Expand Up @@ -265,22 +267,6 @@ export default function typing(entities: EntityType[]): TypeType[] {
return types;
}

function isFunction(entity: EntityType): entity is IFunction {
return entity.entity === Entity.Function;
}

function isComponent(entity: EntityType): entity is ComponentType {
return entity.entity === Entity.Component;
}

function isCombinator(entity: EntityType): entity is ICombinator {
return entity.entity === Entity.Combinator;
}

function isQurlyBracetMultiplier(multiplier: MultiplierType): multiplier is IMultiplierQurlyBracet {
return multiplier.sign === Multiplier.QurlyBracet;
}

function isMultiplied(multiplier: MultiplierType) {
return (
(isQurlyBracetMultiplier(multiplier) && (multiplier.min > 1 || multiplier.max === 1)) ||
Expand Down

0 comments on commit db9f7a8

Please sign in to comment.