@@ -11,15 +11,16 @@ export enum Component {
1111 Group ,
1212}
1313
14+ // Higher number is higher precedence
1415export enum Combinator {
1516 /** Components are mandatory and should appear in that order */
16- Juxtaposition ,
17+ Juxtaposition = 0 ,
1718 /** Components are mandatory but may appear in any order */
18- DoubleAmpersand ,
19+ DoubleAmpersand = 1 ,
1920 /** At least one of the components must be present, and they may appear in any order */
20- DoubleBar ,
21+ DoubleBar = 2 ,
2122 /** Exactly one of the components must be present */
22- SingleBar ,
23+ SingleBar = 3 ,
2324}
2425
2526export enum Multiplier {
@@ -94,7 +95,6 @@ const REGEX_KEYWORD = /^([\w-]+)/g;
9495
9596export default function parse ( syntax : string ) : EntityType [ ] {
9697 const levels : EntityType [ ] [ ] = [ [ ] ] ;
97- const deepestLevel = ( ) => levels [ levels . length - 1 ] ;
9898 let previousMatchWasComponent = false ;
9999 let entityMatch : RegExpExecArray | null ;
100100 while ( ( entityMatch = REGEX_ENTITY . exec ( syntax ) ) ) {
@@ -118,12 +118,12 @@ export default function parse(syntax: string): EntityType[] {
118118 } else if ( value . indexOf ( ']' ) === 0 ) {
119119 const definitions = levels . pop ( ) ;
120120 if ( definitions ) {
121- deepestLevel ( ) . push ( componentGroupData ( definitions , multiplierData ( rawMultiplier ) ) ) ;
121+ deepestLevel ( ) . push ( componentGroupData ( groupByPrecedence ( definitions ) , multiplierData ( rawMultiplier ) ) ) ;
122122 }
123123 previousMatchWasComponent = true ;
124124 continue ;
125125 } else {
126- if ( previousMatchWasComponent === true ) {
126+ if ( previousMatchWasComponent ) {
127127 deepestLevel ( ) . push ( combinatorData ( Combinator . Juxtaposition ) ) ;
128128 }
129129
@@ -149,7 +149,27 @@ export default function parse(syntax: string): EntityType[] {
149149 deepestLevel ( ) . push ( { entity : Entity . Unknown , multiplier : multiplierData ( rawMultiplier ) } ) ;
150150 }
151151
152- return levels [ 0 ] ;
152+ function deepestLevel ( ) {
153+ return levels [ levels . length - 1 ] ;
154+ }
155+
156+ return groupByPrecedence ( levels [ 0 ] ) ;
157+ }
158+
159+ export function isFunction ( entity : EntityType ) : entity is IFunction {
160+ return entity . entity === Entity . Function ;
161+ }
162+
163+ export function isComponent ( entity : EntityType ) : entity is ComponentType {
164+ return entity . entity === Entity . Component ;
165+ }
166+
167+ export function isCombinator ( entity : EntityType ) : entity is ICombinator {
168+ return entity . entity === Entity . Combinator ;
169+ }
170+
171+ export function isQurlyBracetMultiplier ( multiplier : MultiplierType ) : multiplier is IMultiplierQurlyBracet {
172+ return multiplier . sign === Multiplier . QurlyBracet ;
153173}
154174
155175function combinatorData ( combinator : Combinator , multiplier : MultiplierType | null = null ) : ICombinator {
@@ -173,7 +193,7 @@ function componentData(
173193 } ;
174194}
175195
176- function componentGroupData ( entities : EntityType [ ] , multiplier : MultiplierType | null ) : ComponentType {
196+ function componentGroupData ( entities : EntityType [ ] , multiplier : MultiplierType | null = null ) : ComponentType {
177197 return {
178198 entity : Entity . Component ,
179199 component : Component . Group ,
@@ -203,3 +223,24 @@ function multiplierData(raw: string[]): MultiplierType | null {
203223 return null ;
204224 }
205225}
226+
227+ function groupByPrecedence ( entities : EntityType [ ] ) : EntityType [ ] {
228+ for ( let i = 0 ; i < entities . length ; i ++ ) {
229+ const entity = entities [ i ] ;
230+ if ( isCombinator ( entity ) ) {
231+ for ( let a = i ; a >= 0 ; a -- ) {
232+ const adjacentEntity = entities [ a ] ;
233+ if ( isCombinator ( adjacentEntity ) && adjacentEntity . combinator < entity . combinator ) {
234+ return groupByPrecedence ( [ componentGroupData ( entities . slice ( 0 , i ) ) , ...entities . slice ( i ) ] ) ;
235+ }
236+ }
237+ for ( let a = i ; a < entities . length ; a ++ ) {
238+ const subsequentEntity = entities [ a ] ;
239+ if ( isCombinator ( subsequentEntity ) && subsequentEntity . combinator < entity . combinator ) {
240+ return [ ...entities . slice ( 0 , i + 1 ) , componentGroupData ( groupByPrecedence ( entities . slice ( i + 1 ) ) ) ] ;
241+ }
242+ }
243+ }
244+ }
245+ return entities ;
246+ }
0 commit comments