Skip to content

Commit

Permalink
add max depth to recursion
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanzhouyc authored and paulr34 committed Nov 22, 2024
1 parent 1da11bf commit c92cdc6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 30 deletions.
52 changes: 28 additions & 24 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -20136,7 +20136,7 @@ This module provides the APIs for dotdot Loading
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
* [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
* [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
Expand Down Expand Up @@ -21532,7 +21532,7 @@ Output conformance string:

<a name="module_Loader API_ Loader APIs..parseConformanceRecursively"></a>

### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒
### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
helper function to parse conformance or an operand in conformance recursively

The baseLevelTerms variable include terms that can not have nested terms.
Expand All @@ -21541,10 +21541,11 @@ When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [<code>Loader API: Loader APIs</code>](#module_Loader API_ Loader APIs)
**Returns**: The conformance string.

| Param | Type |
| --- | --- |
| operand | <code>\*</code> |
| parentJoinChar | <code>\*</code> |
| Param | Type | Default |
| --- | --- | --- |
| operand | <code>\*</code> | |
| depth | <code>\*</code> | <code>0</code> |
| parentJoinChar | <code>\*</code> | |

<a name="module_Loader API_ Loader APIs..parseUiOptions"></a>

Expand Down Expand Up @@ -21969,7 +21970,7 @@ This module provides the APIs for new data model loading
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
* [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
* [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
Expand Down Expand Up @@ -23365,7 +23366,7 @@ Output conformance string:

<a name="module_Loader API_ Loader APIs..parseConformanceRecursively"></a>

### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒
### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
helper function to parse conformance or an operand in conformance recursively

The baseLevelTerms variable include terms that can not have nested terms.
Expand All @@ -23374,10 +23375,11 @@ When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [<code>Loader API: Loader APIs</code>](#module_Loader API_ Loader APIs)
**Returns**: The conformance string.

| Param | Type |
| --- | --- |
| operand | <code>\*</code> |
| parentJoinChar | <code>\*</code> |
| Param | Type | Default |
| --- | --- | --- |
| operand | <code>\*</code> | |
| depth | <code>\*</code> | <code>0</code> |
| parentJoinChar | <code>\*</code> | |

<a name="module_Loader API_ Loader APIs..parseUiOptions"></a>

Expand Down Expand Up @@ -23802,7 +23804,7 @@ This module provides the APIs for ZCL/Data-Model loading.
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
* [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
* [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
Expand Down Expand Up @@ -25198,7 +25200,7 @@ Output conformance string:

<a name="module_Loader API_ Loader APIs..parseConformanceRecursively"></a>

### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒
### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
helper function to parse conformance or an operand in conformance recursively

The baseLevelTerms variable include terms that can not have nested terms.
Expand All @@ -25207,10 +25209,11 @@ When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [<code>Loader API: Loader APIs</code>](#module_Loader API_ Loader APIs)
**Returns**: The conformance string.

| Param | Type |
| --- | --- |
| operand | <code>\*</code> |
| parentJoinChar | <code>\*</code> |
| Param | Type | Default |
| --- | --- | --- |
| operand | <code>\*</code> | |
| depth | <code>\*</code> | <code>0</code> |
| parentJoinChar | <code>\*</code> | |

<a name="module_Loader API_ Loader APIs..parseUiOptions"></a>

Expand Down Expand Up @@ -25635,7 +25638,7 @@ This module provides the APIs for for common functionality related to loading.
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
* [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
* [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
Expand Down Expand Up @@ -27031,7 +27034,7 @@ Output conformance string:

<a name="module_Loader API_ Loader APIs..parseConformanceRecursively"></a>

### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒
### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
helper function to parse conformance or an operand in conformance recursively

The baseLevelTerms variable include terms that can not have nested terms.
Expand All @@ -27040,10 +27043,11 @@ When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [<code>Loader API: Loader APIs</code>](#module_Loader API_ Loader APIs)
**Returns**: The conformance string.

| Param | Type |
| --- | --- |
| operand | <code>\*</code> |
| parentJoinChar | <code>\*</code> |
| Param | Type | Default |
| --- | --- | --- |
| operand | <code>\*</code> | |
| depth | <code>\*</code> | <code>0</code> |
| parentJoinChar | <code>\*</code> | |

<a name="module_Loader API_ Loader APIs..parseUiOptions"></a>

Expand Down
23 changes: 17 additions & 6 deletions src-electron/zcl/zcl-loader-silabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2304,16 +2304,21 @@ function parseConformanceFromXML(operand) {
* When they appear, stop recursing and return the name inside directly
*
* @param {*} operand
* @param {*} depth
* @param {*} parentJoinChar
* @returns The conformance string.
*/
function parseConformanceRecursively(operand, parentJoinChar = '') {
function parseConformanceRecursively(operand, depth = 0, parentJoinChar = '') {
if (depth > 200) {
throw new Error(`Maximum recursion depth exceeded
when parsing conformance: ${JSON.stringify(operand)}`)
}
const baseLevelTerms = ['feature', 'condition', 'attribute', 'command']
if (operand.mandatoryConform) {
let insideTerm = operand.mandatoryConform[0]
// Recurse further if insideTerm is not empty
if (insideTerm && Object.keys(insideTerm).toString() != '$') {
return parseConformanceRecursively(operand.mandatoryConform[0])
return parseConformanceRecursively(operand.mandatoryConform[0], depth + 1)
} else {
return 'M'
}
Expand All @@ -2322,21 +2327,23 @@ function parseConformanceRecursively(operand, parentJoinChar = '') {
// check '$' key is not the only key in the object to handle special cases
// e.g. '<optionalConform choice="a" more="true"/>'
if (insideTerm && Object.keys(insideTerm).toString() != '$') {
return `[${parseConformanceRecursively(operand.optionalConform[0])}]`
return `[${parseConformanceRecursively(operand.optionalConform[0], depth + 1)}]`
} else {
return 'O'
}
} else if (operand.otherwiseConform) {
return Object.entries(operand.otherwiseConform[0])
.map(([key, value]) => parseConformanceRecursively({ [key]: value }))
.map(([key, value]) =>
parseConformanceRecursively({ [key]: value }, depth + 1)
)
.join(', ')
} else if (operand.notTerm) {
// need to surround terms inside a notTerm with '()' if it contains multiple terms
// e.g. !(A | B) or !(A & B)
// able to process multiple parallel notTerms, e.g. !A & !B
return operand.notTerm
.map((term) => {
let nt = parseConformanceRecursively(term)
let nt = parseConformanceRecursively(term, depth + 1)
return nt.includes('&') || nt.includes('|') ? `!(${nt})` : `!${nt}`
})
.join(` ${parentJoinChar} `)
Expand All @@ -2353,7 +2360,11 @@ function parseConformanceRecursively(operand, parentJoinChar = '') {
if (baseLevelTerms.includes(key)) {
return value.map((operand) => operand.$.name).join(` ${joinChar} `)
} else {
let terms = parseConformanceRecursively({ [key]: value }, joinChar)
let terms = parseConformanceRecursively(
{ [key]: value },
depth + 1,
joinChar
)
return terms.includes(oppositeChar) ? `(${terms})` : terms
}
})
Expand Down

0 comments on commit c92cdc6

Please sign in to comment.