@techspokes/typescript-wsdl-client 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -1
- package/dist/app/generateApp.d.ts.map +1 -1
- package/dist/app/generateApp.js +8 -6
- package/dist/cli.js +49 -5
- package/dist/client/checkedDirectRuntime.d.ts +59 -0
- package/dist/client/checkedDirectRuntime.d.ts.map +1 -0
- package/dist/client/checkedDirectRuntime.js +23 -0
- package/dist/client/directClientRuntime.d.ts +49 -0
- package/dist/client/directClientRuntime.d.ts.map +1 -0
- package/dist/client/directClientRuntime.js +112 -0
- package/dist/client/directClientVersion.d.ts +4 -0
- package/dist/client/directClientVersion.d.ts.map +1 -0
- package/dist/client/directClientVersion.js +3 -0
- package/dist/client/generateDirectClient.d.ts +14 -0
- package/dist/client/generateDirectClient.d.ts.map +1 -0
- package/dist/client/generateDirectClient.js +136 -0
- package/dist/compiler/buildCanonicalGraph.d.ts +7 -0
- package/dist/compiler/buildCanonicalGraph.d.ts.map +1 -0
- package/dist/compiler/buildCanonicalGraph.js +381 -0
- package/dist/compiler/canonicalGraph.d.ts +198 -0
- package/dist/compiler/canonicalGraph.d.ts.map +1 -0
- package/dist/compiler/canonicalGraph.js +37 -0
- package/dist/compiler/catalogErrors.d.ts +18 -0
- package/dist/compiler/catalogErrors.d.ts.map +1 -0
- package/dist/compiler/catalogErrors.js +86 -0
- package/dist/compiler/catalogProvenance.d.ts +15 -0
- package/dist/compiler/catalogProvenance.d.ts.map +1 -0
- package/dist/compiler/catalogProvenance.js +229 -0
- package/dist/compiler/checkedAssessment.d.ts +91 -0
- package/dist/compiler/checkedAssessment.d.ts.map +1 -0
- package/dist/compiler/checkedAssessment.js +300 -0
- package/dist/compiler/checkedSourcePreparation.d.ts +35 -0
- package/dist/compiler/checkedSourcePreparation.d.ts.map +1 -0
- package/dist/compiler/checkedSourcePreparation.js +131 -0
- package/dist/compiler/complexTypeContent.d.ts +59 -0
- package/dist/compiler/complexTypeContent.d.ts.map +1 -0
- package/dist/compiler/complexTypeContent.js +558 -0
- package/dist/compiler/composeCanonicalGraph.d.ts +69 -0
- package/dist/compiler/composeCanonicalGraph.d.ts.map +1 -0
- package/dist/compiler/composeCanonicalGraph.js +252 -0
- package/dist/compiler/dataOwnership.d.ts +22 -0
- package/dist/compiler/dataOwnership.d.ts.map +1 -0
- package/dist/compiler/dataOwnership.js +157 -0
- package/dist/compiler/datatypeValues.d.ts +47 -0
- package/dist/compiler/datatypeValues.d.ts.map +1 -0
- package/dist/compiler/datatypeValues.js +275 -0
- package/dist/compiler/directCodec.d.ts +59 -0
- package/dist/compiler/directCodec.d.ts.map +1 -0
- package/dist/compiler/directCodec.js +192 -0
- package/dist/compiler/directExecutionPolicy.d.ts +10 -0
- package/dist/compiler/directExecutionPolicy.d.ts.map +1 -0
- package/dist/compiler/directExecutionPolicy.js +17 -0
- package/dist/compiler/directOperation.d.ts +72 -0
- package/dist/compiler/directOperation.d.ts.map +1 -0
- package/dist/compiler/directOperation.js +282 -0
- package/dist/compiler/directSoap.d.ts +42 -0
- package/dist/compiler/directSoap.d.ts.map +1 -0
- package/dist/compiler/directSoap.js +298 -0
- package/dist/compiler/directSoapSource.d.ts +15 -0
- package/dist/compiler/directSoapSource.d.ts.map +1 -0
- package/dist/compiler/directSoapSource.js +86 -0
- package/dist/compiler/directSourceCapsule.d.ts +97 -0
- package/dist/compiler/directSourceCapsule.d.ts.map +1 -0
- package/dist/compiler/directSourceCapsule.js +305 -0
- package/dist/compiler/directStructure.d.ts +51 -0
- package/dist/compiler/directStructure.d.ts.map +1 -0
- package/dist/compiler/directStructure.js +252 -0
- package/dist/compiler/directStructurePlan.d.ts +16 -0
- package/dist/compiler/directStructurePlan.d.ts.map +1 -0
- package/dist/compiler/directStructurePlan.js +58 -0
- package/dist/compiler/directValues.d.ts +69 -0
- package/dist/compiler/directValues.d.ts.map +1 -0
- package/dist/compiler/directValues.js +282 -0
- package/dist/compiler/finiteRe01Verification.d.ts +140 -0
- package/dist/compiler/finiteRe01Verification.d.ts.map +1 -0
- package/dist/compiler/finiteRe01Verification.js +830 -0
- package/dist/compiler/graphTraversal.d.ts +11 -0
- package/dist/compiler/graphTraversal.d.ts.map +1 -0
- package/dist/compiler/graphTraversal.js +37 -0
- package/dist/compiler/hypotheticalScopedIdentity.d.ts +23 -0
- package/dist/compiler/hypotheticalScopedIdentity.d.ts.map +1 -0
- package/dist/compiler/hypotheticalScopedIdentity.js +81 -0
- package/dist/compiler/occurrenceAnalysis.d.ts +65 -0
- package/dist/compiler/occurrenceAnalysis.d.ts.map +1 -0
- package/dist/compiler/occurrenceAnalysis.js +300 -0
- package/dist/compiler/originalSourceMembership.d.ts +6 -0
- package/dist/compiler/originalSourceMembership.d.ts.map +1 -0
- package/dist/compiler/originalSourceMembership.js +31 -0
- package/dist/compiler/particleAttribution.d.ts +17 -0
- package/dist/compiler/particleAttribution.d.ts.map +1 -0
- package/dist/compiler/particleAttribution.js +474 -0
- package/dist/compiler/particleDeclarationConsistency.d.ts +24 -0
- package/dist/compiler/particleDeclarationConsistency.d.ts.map +1 -0
- package/dist/compiler/particleDeclarationConsistency.js +197 -0
- package/dist/compiler/particleExtension.d.ts +22 -0
- package/dist/compiler/particleExtension.d.ts.map +1 -0
- package/dist/compiler/particleExtension.js +119 -0
- package/dist/compiler/particleLocalAssessment.d.ts +20 -0
- package/dist/compiler/particleLocalAssessment.d.ts.map +1 -0
- package/dist/compiler/particleLocalAssessment.js +92 -0
- package/dist/compiler/particleRestriction.d.ts +24 -0
- package/dist/compiler/particleRestriction.d.ts.map +1 -0
- package/dist/compiler/particleRestriction.js +489 -0
- package/dist/compiler/particleSemanticView.d.ts +50 -0
- package/dist/compiler/particleSemanticView.d.ts.map +1 -0
- package/dist/compiler/particleSemanticView.js +297 -0
- package/dist/compiler/particleWildcardRelation.d.ts +88 -0
- package/dist/compiler/particleWildcardRelation.d.ts.map +1 -0
- package/dist/compiler/particleWildcardRelation.js +143 -0
- package/dist/compiler/re01CandidateCorrespondence.d.ts +64 -0
- package/dist/compiler/re01CandidateCorrespondence.d.ts.map +1 -0
- package/dist/compiler/re01CandidateCorrespondence.js +572 -0
- package/dist/compiler/re01TypeProperties.d.ts +71 -0
- package/dist/compiler/re01TypeProperties.d.ts.map +1 -0
- package/dist/compiler/re01TypeProperties.js +120 -0
- package/dist/compiler/re01TypePropertyValidation.d.ts +23 -0
- package/dist/compiler/re01TypePropertyValidation.d.ts.map +1 -0
- package/dist/compiler/re01TypePropertyValidation.js +161 -0
- package/dist/compiler/resolveCanonicalGraph.d.ts +38 -0
- package/dist/compiler/resolveCanonicalGraph.d.ts.map +1 -0
- package/dist/compiler/resolveCanonicalGraph.js +170 -0
- package/dist/compiler/scalarSchemaAssessment.d.ts +425 -0
- package/dist/compiler/scalarSchemaAssessment.d.ts.map +1 -0
- package/dist/compiler/scalarSchemaAssessment.js +5198 -0
- package/dist/compiler/schemaAttributeGroupProperties.d.ts +17 -0
- package/dist/compiler/schemaAttributeGroupProperties.d.ts.map +1 -0
- package/dist/compiler/schemaAttributeGroupProperties.js +53 -0
- package/dist/compiler/schemaAttributeProperties.d.ts +10 -0
- package/dist/compiler/schemaAttributeProperties.d.ts.map +1 -0
- package/dist/compiler/schemaAttributeProperties.js +11 -0
- package/dist/compiler/schemaAttributeUses.d.ts +90 -0
- package/dist/compiler/schemaAttributeUses.d.ts.map +1 -0
- package/dist/compiler/schemaAttributeUses.js +725 -0
- package/dist/compiler/schemaBinaryWordReconstruction.d.ts +10 -0
- package/dist/compiler/schemaBinaryWordReconstruction.d.ts.map +1 -0
- package/dist/compiler/schemaBinaryWordReconstruction.js +33 -0
- package/dist/compiler/schemaBuiltinFacets.d.ts +14 -0
- package/dist/compiler/schemaBuiltinFacets.d.ts.map +1 -0
- package/dist/compiler/schemaBuiltinFacets.js +51 -0
- package/dist/compiler/schemaCalendarImages.d.ts +8 -0
- package/dist/compiler/schemaCalendarImages.d.ts.map +1 -0
- package/dist/compiler/schemaCalendarImages.js +204 -0
- package/dist/compiler/schemaCalendarLanguage.d.ts +11 -0
- package/dist/compiler/schemaCalendarLanguage.d.ts.map +1 -0
- package/dist/compiler/schemaCalendarLanguage.js +227 -0
- package/dist/compiler/schemaComponentEquality.d.ts +28 -0
- package/dist/compiler/schemaComponentEquality.d.ts.map +1 -0
- package/dist/compiler/schemaComponentEquality.js +446 -0
- package/dist/compiler/schemaConstructionAssessment.d.ts +46 -0
- package/dist/compiler/schemaConstructionAssessment.d.ts.map +1 -0
- package/dist/compiler/schemaConstructionAssessment.js +663 -0
- package/dist/compiler/schemaDatatypeValues.d.ts +4 -0
- package/dist/compiler/schemaDatatypeValues.d.ts.map +1 -0
- package/dist/compiler/schemaDatatypeValues.js +2 -0
- package/dist/compiler/schemaDecimalLanguage.d.ts +7 -0
- package/dist/compiler/schemaDecimalLanguage.d.ts.map +1 -0
- package/dist/compiler/schemaDecimalLanguage.js +102 -0
- package/dist/compiler/schemaDeclarationPrimitives.d.ts +34 -0
- package/dist/compiler/schemaDeclarationPrimitives.d.ts.map +1 -0
- package/dist/compiler/schemaDeclarationPrimitives.js +194 -0
- package/dist/compiler/schemaDocumentSyntax.d.ts +55 -0
- package/dist/compiler/schemaDocumentSyntax.d.ts.map +1 -0
- package/dist/compiler/schemaDocumentSyntax.js +294 -0
- package/dist/compiler/schemaDurationLanguage.d.ts +11 -0
- package/dist/compiler/schemaDurationLanguage.d.ts.map +1 -0
- package/dist/compiler/schemaDurationLanguage.js +170 -0
- package/dist/compiler/schemaElementProperties.d.ts +16 -0
- package/dist/compiler/schemaElementProperties.d.ts.map +1 -0
- package/dist/compiler/schemaElementProperties.js +23 -0
- package/dist/compiler/schemaEndpointWordCapacity.d.ts +36 -0
- package/dist/compiler/schemaEndpointWordCapacity.d.ts.map +1 -0
- package/dist/compiler/schemaEndpointWordCapacity.js +39 -0
- package/dist/compiler/schemaExactCalendar.d.ts +73 -0
- package/dist/compiler/schemaExactCalendar.d.ts.map +1 -0
- package/dist/compiler/schemaExactCalendar.js +264 -0
- package/dist/compiler/schemaFacetAnnotation.d.ts +32 -0
- package/dist/compiler/schemaFacetAnnotation.d.ts.map +1 -0
- package/dist/compiler/schemaFacetAnnotation.js +199 -0
- package/dist/compiler/schemaGeneratedScalarShape.d.ts +35 -0
- package/dist/compiler/schemaGeneratedScalarShape.d.ts.map +1 -0
- package/dist/compiler/schemaGeneratedScalarShape.js +176 -0
- package/dist/compiler/schemaIdentityConstraints.d.ts +73 -0
- package/dist/compiler/schemaIdentityConstraints.d.ts.map +1 -0
- package/dist/compiler/schemaIdentityConstraints.js +362 -0
- package/dist/compiler/schemaIeeeLanguage.d.ts +43 -0
- package/dist/compiler/schemaIeeeLanguage.d.ts.map +1 -0
- package/dist/compiler/schemaIeeeLanguage.js +759 -0
- package/dist/compiler/schemaIntegerImages.d.ts +11 -0
- package/dist/compiler/schemaIntegerImages.d.ts.map +1 -0
- package/dist/compiler/schemaIntegerImages.js +113 -0
- package/dist/compiler/schemaLexicalPredicates.d.ts +29 -0
- package/dist/compiler/schemaLexicalPredicates.d.ts.map +1 -0
- package/dist/compiler/schemaLexicalPredicates.js +63 -0
- package/dist/compiler/schemaNotationProperties.d.ts +32 -0
- package/dist/compiler/schemaNotationProperties.d.ts.map +1 -0
- package/dist/compiler/schemaNotationProperties.js +84 -0
- package/dist/compiler/schemaNumericImageConditions.d.ts +24 -0
- package/dist/compiler/schemaNumericImageConditions.d.ts.map +1 -0
- package/dist/compiler/schemaNumericImageConditions.js +66 -0
- package/dist/compiler/schemaParticleWildcardProperties.d.ts +20 -0
- package/dist/compiler/schemaParticleWildcardProperties.d.ts.map +1 -0
- package/dist/compiler/schemaParticleWildcardProperties.js +43 -0
- package/dist/compiler/schemaPattern.d.ts +1062 -0
- package/dist/compiler/schemaPattern.d.ts.map +1 -0
- package/dist/compiler/schemaPattern.js +581 -0
- package/dist/compiler/schemaRegularLanguage.d.ts +67 -0
- package/dist/compiler/schemaRegularLanguage.d.ts.map +1 -0
- package/dist/compiler/schemaRegularLanguage.js +1166 -0
- package/dist/compiler/schemaScalarContext.d.ts +81 -0
- package/dist/compiler/schemaScalarContext.d.ts.map +1 -0
- package/dist/compiler/schemaScalarContext.js +78 -0
- package/dist/compiler/schemaScalarKernel.d.ts +182 -0
- package/dist/compiler/schemaScalarKernel.d.ts.map +1 -0
- package/dist/compiler/schemaScalarKernel.js +391 -0
- package/dist/compiler/schemaScalarWitnesses.d.ts +6 -0
- package/dist/compiler/schemaScalarWitnesses.d.ts.map +1 -0
- package/dist/compiler/schemaScalarWitnesses.js +118 -0
- package/dist/compiler/schemaSimpleTypeProperties.d.ts +95 -0
- package/dist/compiler/schemaSimpleTypeProperties.d.ts.map +1 -0
- package/dist/compiler/schemaSimpleTypeProperties.js +103 -0
- package/dist/compiler/schemaSourceGrammar.d.ts +27 -0
- package/dist/compiler/schemaSourceGrammar.d.ts.map +1 -0
- package/dist/compiler/schemaSourceGrammar.js +290 -0
- package/dist/compiler/schemaSourceLexical.d.ts +4 -0
- package/dist/compiler/schemaSourceLexical.d.ts.map +1 -0
- package/dist/compiler/schemaSourceLexical.js +12 -0
- package/dist/compiler/schemaSourceValues.d.ts +51 -0
- package/dist/compiler/schemaSourceValues.d.ts.map +1 -0
- package/dist/compiler/schemaSourceValues.js +225 -0
- package/dist/compiler/schemaSourceWildcards.d.ts +28 -0
- package/dist/compiler/schemaSourceWildcards.d.ts.map +1 -0
- package/dist/compiler/schemaSourceWildcards.js +247 -0
- package/dist/compiler/schemaSymbolicSequences.d.ts +16 -0
- package/dist/compiler/schemaSymbolicSequences.d.ts.map +1 -0
- package/dist/compiler/schemaSymbolicSequences.js +99 -0
- package/dist/compiler/schemaSymbolicValueSets.d.ts +32 -0
- package/dist/compiler/schemaSymbolicValueSets.d.ts.map +1 -0
- package/dist/compiler/schemaSymbolicValueSets.js +149 -0
- package/dist/compiler/schemaSyntaxAssessment.d.ts +25 -0
- package/dist/compiler/schemaSyntaxAssessment.d.ts.map +1 -0
- package/dist/compiler/schemaSyntaxAssessment.js +361 -0
- package/dist/compiler/schemaTemporalAliases.d.ts +6 -0
- package/dist/compiler/schemaTemporalAliases.d.ts.map +1 -0
- package/dist/compiler/schemaTemporalAliases.js +195 -0
- package/dist/compiler/schemaTokenImages.d.ts +9 -0
- package/dist/compiler/schemaTokenImages.d.ts.map +1 -0
- package/dist/compiler/schemaTokenImages.js +142 -0
- package/dist/compiler/schemaTypeIdentity.d.ts +39 -0
- package/dist/compiler/schemaTypeIdentity.d.ts.map +1 -0
- package/dist/compiler/schemaTypeIdentity.js +78 -0
- package/dist/compiler/schemaTypeRelations.d.ts +38 -0
- package/dist/compiler/schemaTypeRelations.d.ts.map +1 -0
- package/dist/compiler/schemaTypeRelations.js +576 -0
- package/dist/compiler/schemaUri.d.ts +13 -0
- package/dist/compiler/schemaUri.d.ts.map +1 -0
- package/dist/compiler/schemaUri.js +103 -0
- package/dist/compiler/schemaValueContext.d.ts +26 -0
- package/dist/compiler/schemaValueContext.d.ts.map +1 -0
- package/dist/compiler/schemaValueContext.js +1 -0
- package/dist/compiler/schemaValueImages.d.ts +10 -0
- package/dist/compiler/schemaValueImages.d.ts.map +1 -0
- package/dist/compiler/schemaValueImages.js +142 -0
- package/dist/compiler/schemaValueSequences.d.ts +15 -0
- package/dist/compiler/schemaValueSequences.d.ts.map +1 -0
- package/dist/compiler/schemaValueSequences.js +19 -0
- package/dist/compiler/semanticBudget.d.ts +50 -0
- package/dist/compiler/semanticBudget.d.ts.map +1 -0
- package/dist/compiler/semanticBudget.js +178 -0
- package/dist/compiler/semanticCatalog.d.ts +122 -0
- package/dist/compiler/semanticCatalog.d.ts.map +1 -0
- package/dist/compiler/semanticCatalog.js +160 -0
- package/dist/compiler/semanticContext.d.ts +172 -0
- package/dist/compiler/semanticContext.d.ts.map +1 -0
- package/dist/compiler/semanticContext.js +1168 -0
- package/dist/compiler/semanticTypeDependencies.d.ts +8 -0
- package/dist/compiler/semanticTypeDependencies.d.ts.map +1 -0
- package/dist/compiler/semanticTypeDependencies.js +64 -0
- package/dist/compiler/semanticTypeReference.d.ts +24 -0
- package/dist/compiler/semanticTypeReference.d.ts.map +1 -0
- package/dist/compiler/semanticTypeReference.js +36 -0
- package/dist/compiler/shapeResolver.d.ts +1 -0
- package/dist/compiler/shapeResolver.d.ts.map +1 -1
- package/dist/compiler/shapeResolver.js +7 -9
- package/dist/compiler/sourceSchemaBinding.d.ts +26 -0
- package/dist/compiler/sourceSchemaBinding.d.ts.map +1 -0
- package/dist/compiler/sourceSchemaBinding.js +39 -0
- package/dist/compiler/structuralCompanions.d.ts +16 -0
- package/dist/compiler/structuralCompanions.d.ts.map +1 -0
- package/dist/compiler/structuralCompanions.js +232 -0
- package/dist/compiler/validateSemanticGraph.d.ts +5 -0
- package/dist/compiler/validateSemanticGraph.d.ts.map +1 -0
- package/dist/compiler/validateSemanticGraph.js +376 -0
- package/dist/compiler/wildcardAlgebra.d.ts +26 -0
- package/dist/compiler/wildcardAlgebra.d.ts.map +1 -0
- package/dist/compiler/wildcardAlgebra.js +155 -0
- package/dist/gateway/generateGateway.d.ts.map +1 -1
- package/dist/gateway/generateGateway.js +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/loader/orderedSyntax.d.ts +77 -0
- package/dist/loader/orderedSyntax.d.ts.map +1 -0
- package/dist/loader/orderedSyntax.js +202 -0
- package/dist/loader/resolutionDepth.d.ts +7 -0
- package/dist/loader/resolutionDepth.d.ts.map +1 -0
- package/dist/loader/resolutionDepth.js +65 -0
- package/dist/loader/schemaInput.d.ts +53 -0
- package/dist/loader/schemaInput.d.ts.map +1 -0
- package/dist/loader/schemaInput.js +212 -0
- package/dist/loader/schemaResources.d.ts +59 -0
- package/dist/loader/schemaResources.d.ts.map +1 -0
- package/dist/loader/schemaResources.js +292 -0
- package/dist/openapi/generateOpenAPI.d.ts.map +1 -1
- package/dist/openapi/generateOpenAPI.js +2 -2
- package/dist/test/generateTests.d.ts.map +1 -1
- package/dist/test/generateTests.js +2 -2
- package/dist/util/xmlWhitespace.d.ts +3 -0
- package/dist/util/xmlWhitespace.d.ts.map +1 -0
- package/dist/util/xmlWhitespace.js +4 -0
- package/docs/README.md +14 -1
- package/docs/architecture.md +9 -0
- package/docs/cli-reference.md +21 -1
- package/docs/content-model-analysis.md +92 -0
- package/docs/content-model-baseline.md +121 -0
- package/docs/content-model-catalog.md +116 -0
- package/docs/content-model-companions.md +90 -0
- package/docs/content-model-composition.md +103 -0
- package/docs/content-model-decisions.md +79 -0
- package/docs/content-model-gateway-feasibility.md +169 -0
- package/docs/content-model-graph.md +121 -0
- package/docs/content-model-loading.md +163 -0
- package/docs/content-model-matching.md +85 -0
- package/docs/content-model-readiness.md +144 -0
- package/docs/content-model-resolution.md +81 -0
- package/docs/content-model-s02-handoff.md +98 -0
- package/docs/content-model-s06-au-01.md +425 -0
- package/docs/content-model-s06-dt-01.md +386 -0
- package/docs/content-model-s06-pw-01.md +350 -0
- package/docs/content-model-s06-re-01-resolver-implementation.md +869 -0
- package/docs/content-model-s06-re-01-resolver.md +513 -0
- package/docs/content-model-s06-re-01-scalar-witnesses.md +1423 -0
- package/docs/content-model-s06-re-01-support-reconstruction.md +6337 -0
- package/docs/content-model-s06-re-01.md +7477 -0
- package/docs/content-model-s06-research-handoff.md +909 -0
- package/docs/content-model-shipped-fix.md +83 -0
- package/docs/content-model-soap-feasibility.md +165 -0
- package/docs/decisions/002-streamable-responses.md +2 -0
- package/docs/decisions/003-content-model-contracts.md +280 -0
- package/docs/direct-values.md +311 -0
- package/docs/reference-validation.md +243 -0
- package/docs/releases/v1.1.5.md +38 -0
- package/docs/roadmap/README.md +2 -2
- package/docs/supported-patterns.md +13 -5
- package/package.json +26 -13
- package/src/generation/preambles/direct-client/typescript.preamble +3 -0
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
const XML = [[9, 10], [13, 13], [32, 0xd7ff], [0xe000, 0xfffd], [0x10000, 0x10ffff]];
|
|
2
|
+
export function schemaRegularLanguages(c) {
|
|
3
|
+
const records = new WeakMap();
|
|
4
|
+
const materialized = new WeakMap();
|
|
5
|
+
const deterministic = new WeakMap();
|
|
6
|
+
const witnesses = new WeakMap();
|
|
7
|
+
const classes = new Map();
|
|
8
|
+
const formulaLanguages = new WeakMap(), formulaIds = new WeakMap();
|
|
9
|
+
const booleanLanguages = new Map(), complements = new WeakMap();
|
|
10
|
+
let nextFormulaId = 0;
|
|
11
|
+
const issue = (formula, owner) => {
|
|
12
|
+
c.step(owner);
|
|
13
|
+
const known = formulaLanguages.get(formula);
|
|
14
|
+
if (known)
|
|
15
|
+
return known;
|
|
16
|
+
c.step(owner, 3);
|
|
17
|
+
const language = Object.freeze({ kind: 'private-regular-language' });
|
|
18
|
+
c.step(owner, 3);
|
|
19
|
+
records.set(language, formula);
|
|
20
|
+
formulaLanguages.set(formula, language);
|
|
21
|
+
formulaIds.set(formula, nextFormulaId++);
|
|
22
|
+
return language;
|
|
23
|
+
};
|
|
24
|
+
const read = (language) => {
|
|
25
|
+
const formula = records.get(language);
|
|
26
|
+
if (!formula)
|
|
27
|
+
throw new TypeError('Regular language must be issued by this request factory');
|
|
28
|
+
return formula;
|
|
29
|
+
};
|
|
30
|
+
const normalize = (ranges, owner) => {
|
|
31
|
+
c.step(owner, ranges.length * ranges.length + ranges.length * 4 + 1);
|
|
32
|
+
const sorted = [...ranges].sort((a, b) => a[0] - b[0]), result = [];
|
|
33
|
+
for (const [lo, hi] of sorted) {
|
|
34
|
+
c.step(owner, 3);
|
|
35
|
+
const previous = result.at(-1);
|
|
36
|
+
if (previous && lo <= previous[1] + 1)
|
|
37
|
+
previous[1] = Math.max(previous[1], hi);
|
|
38
|
+
else {
|
|
39
|
+
c.step(owner, 3);
|
|
40
|
+
result.push([lo, hi]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
const complement = (ranges, owner) => {
|
|
46
|
+
const sorted = normalize(ranges, owner), result = [];
|
|
47
|
+
for (const [lo, hi] of XML) {
|
|
48
|
+
let cursor = lo;
|
|
49
|
+
for (const [a, b] of sorted) {
|
|
50
|
+
c.step(owner, 3);
|
|
51
|
+
if (b < cursor || a > hi)
|
|
52
|
+
continue;
|
|
53
|
+
if (a > cursor) {
|
|
54
|
+
c.step(owner, 3);
|
|
55
|
+
result.push([cursor, Math.min(a - 1, hi)]);
|
|
56
|
+
}
|
|
57
|
+
cursor = Math.max(cursor, b + 1);
|
|
58
|
+
}
|
|
59
|
+
if (cursor <= hi) {
|
|
60
|
+
c.step(owner, 3);
|
|
61
|
+
result.push([cursor, hi]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
const characterRanges = (expression, owner) => {
|
|
67
|
+
c.text(expression, owner);
|
|
68
|
+
const cached = classes.get(expression);
|
|
69
|
+
if (cached)
|
|
70
|
+
return cached;
|
|
71
|
+
// Literal/range classes avoid a Unicode sweep. Property escapes use the
|
|
72
|
+
// same host Unicode authority as the admitted single-character assessor.
|
|
73
|
+
let source = expression, removeColon = false;
|
|
74
|
+
if (source.startsWith('(?!:)')) {
|
|
75
|
+
source = source.slice('(?!:)'.length);
|
|
76
|
+
removeColon = true;
|
|
77
|
+
}
|
|
78
|
+
let offset = 0;
|
|
79
|
+
const point = () => {
|
|
80
|
+
c.step(owner, 3);
|
|
81
|
+
if (source[offset] !== '\\') {
|
|
82
|
+
const value = source.codePointAt(offset);
|
|
83
|
+
offset += value > 0xffff ? 2 : 1;
|
|
84
|
+
return { ranges: [[value, value]], singleton: value };
|
|
85
|
+
}
|
|
86
|
+
offset++;
|
|
87
|
+
const escape = source[offset++];
|
|
88
|
+
if (escape === 'u') {
|
|
89
|
+
let raw;
|
|
90
|
+
if (source[offset] === '{') {
|
|
91
|
+
const start = ++offset;
|
|
92
|
+
while (source[offset] !== '}') {
|
|
93
|
+
c.step(owner);
|
|
94
|
+
offset++;
|
|
95
|
+
}
|
|
96
|
+
c.step(owner, offset - start + 1);
|
|
97
|
+
raw = source.slice(start, offset++);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
c.step(owner, 4);
|
|
101
|
+
raw = source.slice(offset, offset + 4);
|
|
102
|
+
offset += 4;
|
|
103
|
+
}
|
|
104
|
+
c.text(raw, owner);
|
|
105
|
+
const value = Number.parseInt(raw, 16);
|
|
106
|
+
return { ranges: [[value, value]], singleton: value };
|
|
107
|
+
}
|
|
108
|
+
if (escape === 'p' || escape === 'P') {
|
|
109
|
+
const start = offset - 2;
|
|
110
|
+
offset++;
|
|
111
|
+
while (source[offset] !== '}') {
|
|
112
|
+
c.step(owner);
|
|
113
|
+
offset++;
|
|
114
|
+
}
|
|
115
|
+
offset++;
|
|
116
|
+
const key = source.slice(start, offset), known = classes.get(key);
|
|
117
|
+
if (known)
|
|
118
|
+
return { ranges: known };
|
|
119
|
+
c.step(owner, key.length + 4);
|
|
120
|
+
const regex = new RegExp(`^(?:${key})$`, 'u'), ranges = [];
|
|
121
|
+
for (const [lo, hi] of XML) {
|
|
122
|
+
let begin;
|
|
123
|
+
for (let cp = lo; cp <= hi; cp++) {
|
|
124
|
+
c.step(owner, 3);
|
|
125
|
+
const matches = regex.test(String.fromCodePoint(cp));
|
|
126
|
+
if (matches && begin === undefined)
|
|
127
|
+
begin = cp;
|
|
128
|
+
if (!matches && begin !== undefined) {
|
|
129
|
+
c.step(owner, 3);
|
|
130
|
+
ranges.push([begin, cp - 1]);
|
|
131
|
+
begin = undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (begin !== undefined) {
|
|
135
|
+
c.step(owner, 3);
|
|
136
|
+
ranges.push([begin, hi]);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
c.step(owner, 2);
|
|
140
|
+
classes.set(key, ranges);
|
|
141
|
+
return { ranges };
|
|
142
|
+
}
|
|
143
|
+
const value = escape === 'n' ? 10 : escape === 'r' ? 13 : escape === 't' ? 9 : escape.codePointAt(0);
|
|
144
|
+
return { ranges: [[value, value]], singleton: value };
|
|
145
|
+
};
|
|
146
|
+
const ranges = [];
|
|
147
|
+
let negative = false;
|
|
148
|
+
if (source[0] === '[') {
|
|
149
|
+
offset++;
|
|
150
|
+
if (source[offset] === '^') {
|
|
151
|
+
negative = true;
|
|
152
|
+
offset++;
|
|
153
|
+
}
|
|
154
|
+
while (offset < source.length - 1) {
|
|
155
|
+
const first = point();
|
|
156
|
+
if (source[offset] === '-' && offset + 1 < source.length - 1) {
|
|
157
|
+
offset++;
|
|
158
|
+
const last = point();
|
|
159
|
+
if (first.singleton === undefined || last.singleton === undefined)
|
|
160
|
+
throw new TypeError('Invalid private character range');
|
|
161
|
+
c.step(owner, 3);
|
|
162
|
+
ranges.push([first.singleton, last.singleton]);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
c.step(owner, first.ranges.length);
|
|
166
|
+
ranges.push(...first.ranges);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const first = point();
|
|
172
|
+
c.step(owner, first.ranges.length);
|
|
173
|
+
ranges.push(...first.ranges);
|
|
174
|
+
}
|
|
175
|
+
let result = negative ? complement(ranges, owner) : normalize(ranges, owner);
|
|
176
|
+
if (removeColon)
|
|
177
|
+
result = complement([...complement(result, owner), [58, 58]], owner);
|
|
178
|
+
c.step(owner, 2);
|
|
179
|
+
classes.set(expression, result);
|
|
180
|
+
return result;
|
|
181
|
+
};
|
|
182
|
+
const fromPattern = (atoms, root, owner) => {
|
|
183
|
+
c.step(owner, 4);
|
|
184
|
+
const edges = [];
|
|
185
|
+
const state = () => { c.step(owner, 2); edges.push([]); return edges.length - 1; };
|
|
186
|
+
const link = (from, to, ranges) => { c.step(owner, 4); edges[from].push({ to, ranges }); };
|
|
187
|
+
const start = state(), end = state();
|
|
188
|
+
c.step(owner, 4);
|
|
189
|
+
const pending = [{ node: root, start, end }];
|
|
190
|
+
while (pending.length) {
|
|
191
|
+
c.step(owner);
|
|
192
|
+
const task = pending.pop(), atom = atoms[task.node];
|
|
193
|
+
if (atom.kind === 'character')
|
|
194
|
+
link(task.start, task.end, characterRanges(atom.expression, owner));
|
|
195
|
+
else if (atom.kind === 'choice') {
|
|
196
|
+
for (const node of atom.children) {
|
|
197
|
+
c.step(owner, 4);
|
|
198
|
+
pending.push({ ...task, node });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else if (atom.kind === 'sequence') {
|
|
202
|
+
let previous = task.start;
|
|
203
|
+
if (!atom.children.length)
|
|
204
|
+
link(previous, task.end);
|
|
205
|
+
for (let i = 0; i < atom.children.length; i++) {
|
|
206
|
+
const next = i === atom.children.length - 1 ? task.end : state();
|
|
207
|
+
c.step(owner, 4);
|
|
208
|
+
pending.push({ node: atom.children[i], start: previous, end: next });
|
|
209
|
+
previous = next;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
c.text(atom.min, owner);
|
|
214
|
+
c.text(atom.max, owner);
|
|
215
|
+
c.step(owner, atom.min.length ** 2 + atom.max.length ** 2 + 2);
|
|
216
|
+
const minimum = BigInt(atom.min), maximum = atom.max === 'unbounded' ? minimum : BigInt(atom.max);
|
|
217
|
+
// A materialized Thompson construction needs these copies. Charging
|
|
218
|
+
// first also prevents unsafe Number conversion or native allocations.
|
|
219
|
+
c.step(owner, Number(maximum > BigInt(Math.floor(Number.MAX_SAFE_INTEGER / 16))
|
|
220
|
+
? BigInt(Number.MAX_SAFE_INTEGER) : maximum * 16n));
|
|
221
|
+
let previous = task.start;
|
|
222
|
+
for (let count = 0n; count < maximum; count++) {
|
|
223
|
+
c.step(owner, atom.max.length + 2);
|
|
224
|
+
if (count >= minimum)
|
|
225
|
+
link(previous, task.end);
|
|
226
|
+
const next = state();
|
|
227
|
+
c.step(owner, 4);
|
|
228
|
+
pending.push({ node: atom.child, start: previous, end: next });
|
|
229
|
+
previous = next;
|
|
230
|
+
}
|
|
231
|
+
link(previous, task.end);
|
|
232
|
+
if (atom.max === 'unbounded') {
|
|
233
|
+
const loop = state();
|
|
234
|
+
link(previous, loop);
|
|
235
|
+
c.step(owner, 4);
|
|
236
|
+
pending.push({ node: atom.child, start: loop, end: previous });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return issue({ kind: 'leaf', machine: { edges, start, end } }, owner);
|
|
241
|
+
};
|
|
242
|
+
const combine = (kind, languages, owner) => {
|
|
243
|
+
c.step(owner, languages.length * 2 + 5);
|
|
244
|
+
const pending = languages.map(read), children = new Set();
|
|
245
|
+
while (pending.length) {
|
|
246
|
+
c.step(owner);
|
|
247
|
+
const child = pending.pop();
|
|
248
|
+
if (child.kind === kind)
|
|
249
|
+
for (const nested of child.children) {
|
|
250
|
+
c.step(owner);
|
|
251
|
+
pending.push(nested);
|
|
252
|
+
}
|
|
253
|
+
else if (child.kind !== 'leaf' && child.kind !== 'not' && !child.children.length)
|
|
254
|
+
return combine(child.kind, [], owner);
|
|
255
|
+
else {
|
|
256
|
+
c.step(owner);
|
|
257
|
+
children.add(child);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
for (const child of children) {
|
|
261
|
+
c.step(owner);
|
|
262
|
+
if (child.kind === 'not' && children.has(child.child))
|
|
263
|
+
return combine(kind === 'and' ? 'or' : 'and', [], owner);
|
|
264
|
+
}
|
|
265
|
+
if (children.size === 1)
|
|
266
|
+
return issue(children.values().next().value, owner);
|
|
267
|
+
c.step(owner, children.size ** 2 + children.size * 16 + 6);
|
|
268
|
+
const ordered = [...children].sort((a, b) => formulaIds.get(a) - formulaIds.get(b));
|
|
269
|
+
const key = kind + ':' + ordered.map(child => formulaIds.get(child)).join(',');
|
|
270
|
+
const known = booleanLanguages.get(key);
|
|
271
|
+
if (known)
|
|
272
|
+
return known;
|
|
273
|
+
const language = issue({ kind, children: ordered }, owner);
|
|
274
|
+
c.step(owner, 2);
|
|
275
|
+
booleanLanguages.set(key, language);
|
|
276
|
+
return language;
|
|
277
|
+
};
|
|
278
|
+
const negate = (language, owner) => {
|
|
279
|
+
c.step(owner, 2);
|
|
280
|
+
const child = read(language);
|
|
281
|
+
if (child.kind === 'not')
|
|
282
|
+
return issue(child.child, owner);
|
|
283
|
+
const known = complements.get(child);
|
|
284
|
+
if (known)
|
|
285
|
+
return known;
|
|
286
|
+
const result = issue({ kind: 'not', child }, owner);
|
|
287
|
+
c.step(owner, 2);
|
|
288
|
+
complements.set(child, result);
|
|
289
|
+
return result;
|
|
290
|
+
};
|
|
291
|
+
/** Breadth-first reachability on the finite product of subset machines. */
|
|
292
|
+
const explore = (language, owner, firstOnly) => {
|
|
293
|
+
const formula = read(language), machines = [], indices = new Map();
|
|
294
|
+
c.step(owner, 2);
|
|
295
|
+
const pending = [formula], order = [], seenFormula = new Set();
|
|
296
|
+
while (pending.length) {
|
|
297
|
+
c.step(owner, 3);
|
|
298
|
+
const node = pending.pop();
|
|
299
|
+
if (seenFormula.has(node))
|
|
300
|
+
continue;
|
|
301
|
+
seenFormula.add(node);
|
|
302
|
+
order.push(node);
|
|
303
|
+
if (node.kind === 'leaf') {
|
|
304
|
+
c.step(owner, 3);
|
|
305
|
+
indices.set(node, machines.length);
|
|
306
|
+
machines.push(node.machine);
|
|
307
|
+
}
|
|
308
|
+
else if (node.kind === 'not') {
|
|
309
|
+
c.step(owner);
|
|
310
|
+
pending.push(node.child);
|
|
311
|
+
}
|
|
312
|
+
else
|
|
313
|
+
for (const child of node.children) {
|
|
314
|
+
c.step(owner);
|
|
315
|
+
pending.push(child);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Evaluate a formula by an explicit stack; shared subexpressions are
|
|
319
|
+
// memoized per product state, independent of traversal order.
|
|
320
|
+
const accepts = (sets) => {
|
|
321
|
+
c.step(owner, 3);
|
|
322
|
+
const results = new Map(), stack = [{ node: formula, ready: false }];
|
|
323
|
+
while (stack.length) {
|
|
324
|
+
c.step(owner, 3);
|
|
325
|
+
const frame = stack.pop(), node = frame.node;
|
|
326
|
+
if (results.has(node))
|
|
327
|
+
continue;
|
|
328
|
+
if (node.kind === 'leaf') {
|
|
329
|
+
c.step(owner, sets[indices.get(node)].length);
|
|
330
|
+
results.set(node, sets[indices.get(node)].includes(node.machine.end));
|
|
331
|
+
}
|
|
332
|
+
else if (!frame.ready) {
|
|
333
|
+
c.step(owner, 3);
|
|
334
|
+
stack.push({ node, ready: true });
|
|
335
|
+
const children = node.kind === 'not' ? [node.child] : node.children;
|
|
336
|
+
for (const child of children) {
|
|
337
|
+
c.step(owner, 3);
|
|
338
|
+
stack.push({ node: child, ready: false });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (node.kind === 'not')
|
|
342
|
+
results.set(node, !results.get(node.child));
|
|
343
|
+
else {
|
|
344
|
+
c.step(owner, node.children.length);
|
|
345
|
+
results.set(node, node.kind === 'and'
|
|
346
|
+
? node.children.every(child => results.get(child)) : node.children.some(child => results.get(child)));
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return results.get(formula);
|
|
350
|
+
};
|
|
351
|
+
// An empty subset can never recover. Collapse products whose Boolean
|
|
352
|
+
// formula is therefore permanently false into one rejecting sink. Other
|
|
353
|
+
// machines must not keep generating unreachable combinations after an
|
|
354
|
+
// obligatory lexical/pattern machine has already rejected every suffix.
|
|
355
|
+
const impossible = (sets) => {
|
|
356
|
+
c.step(owner, sets.length + 1);
|
|
357
|
+
if (sets.every(set => set.length))
|
|
358
|
+
return false;
|
|
359
|
+
c.step(owner, 3);
|
|
360
|
+
const results = new Map(), stack = [{ node: formula, ready: false }];
|
|
361
|
+
while (stack.length) {
|
|
362
|
+
c.step(owner, 3);
|
|
363
|
+
const frame = stack.pop(), node = frame.node;
|
|
364
|
+
if (results.has(node))
|
|
365
|
+
continue;
|
|
366
|
+
if (node.kind === 'leaf')
|
|
367
|
+
results.set(node, sets[indices.get(node)].length ? undefined : false);
|
|
368
|
+
else if (!frame.ready) {
|
|
369
|
+
c.step(owner, 3);
|
|
370
|
+
stack.push({ node, ready: true });
|
|
371
|
+
for (const child of node.kind === 'not' ? [node.child] : node.children) {
|
|
372
|
+
c.step(owner, 3);
|
|
373
|
+
stack.push({ node: child, ready: false });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else if (node.kind === 'not') {
|
|
377
|
+
const value = results.get(node.child);
|
|
378
|
+
results.set(node, value === undefined ? undefined : !value);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
c.step(owner, node.children.length * 2 + 1);
|
|
382
|
+
const values = node.children.map(child => results.get(child));
|
|
383
|
+
results.set(node, node.kind === 'and' ? values.includes(false) ? false : values.every(value => value === true) ? true : undefined
|
|
384
|
+
: values.includes(true) ? true : values.every(value => value === false) ? false : undefined);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return results.get(formula) === false;
|
|
388
|
+
};
|
|
389
|
+
const productive = new WeakMap();
|
|
390
|
+
const productiveStates = (machine) => {
|
|
391
|
+
c.step(owner);
|
|
392
|
+
const known = productive.get(machine);
|
|
393
|
+
if (known)
|
|
394
|
+
return known;
|
|
395
|
+
c.step(owner, machine.edges.length * 2 + 5);
|
|
396
|
+
const incoming = machine.edges.map(() => []), result = new Set([machine.end]), pending = [machine.end];
|
|
397
|
+
for (let from = 0; from < machine.edges.length; from++)
|
|
398
|
+
for (const edge of machine.edges[from]) {
|
|
399
|
+
c.step(owner, 2);
|
|
400
|
+
if (edge.ranges === undefined || edge.ranges.length)
|
|
401
|
+
incoming[edge.to].push(from);
|
|
402
|
+
}
|
|
403
|
+
while (pending.length) {
|
|
404
|
+
c.step(owner);
|
|
405
|
+
const state = pending.pop();
|
|
406
|
+
for (const from of incoming[state]) {
|
|
407
|
+
c.step(owner);
|
|
408
|
+
if (!result.has(from)) {
|
|
409
|
+
c.step(owner, 2);
|
|
410
|
+
result.add(from);
|
|
411
|
+
pending.push(from);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
c.step(owner, 2);
|
|
416
|
+
productive.set(machine, result);
|
|
417
|
+
return result;
|
|
418
|
+
};
|
|
419
|
+
const closure = (machine, initial) => {
|
|
420
|
+
const useful = productiveStates(machine);
|
|
421
|
+
c.step(owner, initial.length * 3 + 4);
|
|
422
|
+
const starts = initial.filter(state => useful.has(state)), found = new Set(starts), pending = [...starts];
|
|
423
|
+
while (pending.length) {
|
|
424
|
+
c.step(owner);
|
|
425
|
+
const current = pending.pop();
|
|
426
|
+
for (const edge of machine.edges[current]) {
|
|
427
|
+
c.step(owner, 2);
|
|
428
|
+
if (!edge.ranges && useful.has(edge.to) && !found.has(edge.to)) {
|
|
429
|
+
c.step(owner, 2);
|
|
430
|
+
found.add(edge.to);
|
|
431
|
+
pending.push(edge.to);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
c.step(owner, found.size * found.size + found.size + 1);
|
|
436
|
+
return [...found].sort((a, b) => a - b);
|
|
437
|
+
};
|
|
438
|
+
const key = (sets) => {
|
|
439
|
+
c.step(owner, sets.length * 3 + 1);
|
|
440
|
+
for (const set of sets)
|
|
441
|
+
c.step(owner, set.length * 16 + 1);
|
|
442
|
+
return JSON.stringify(sets);
|
|
443
|
+
};
|
|
444
|
+
c.step(owner, machines.length * 2 + 4);
|
|
445
|
+
const initial = machines.map(machine => closure(machine, [machine.start]));
|
|
446
|
+
c.step(owner, 4);
|
|
447
|
+
const states = [{ sets: initial, transitions: [] }], visited = new Map([[key(initial), 0]]);
|
|
448
|
+
let dead;
|
|
449
|
+
for (let cursor = 0; cursor < states.length; cursor++) {
|
|
450
|
+
c.step(owner);
|
|
451
|
+
const current = states[cursor];
|
|
452
|
+
if (current.dead)
|
|
453
|
+
continue;
|
|
454
|
+
current.accepting = accepts(current.sets);
|
|
455
|
+
if (current.accepting && firstOnly) {
|
|
456
|
+
c.step(owner, 2);
|
|
457
|
+
const characters = [];
|
|
458
|
+
let index = cursor;
|
|
459
|
+
while (index !== undefined) {
|
|
460
|
+
c.step(owner, 3);
|
|
461
|
+
const state = states[index];
|
|
462
|
+
if (state.char)
|
|
463
|
+
characters.push(state.char);
|
|
464
|
+
index = state.previous;
|
|
465
|
+
}
|
|
466
|
+
c.step(owner, characters.length * 3 + 1);
|
|
467
|
+
return { word: characters.reverse().join(''), states };
|
|
468
|
+
}
|
|
469
|
+
c.step(owner, 2);
|
|
470
|
+
const boundaries = new Set();
|
|
471
|
+
for (const [lo, hi] of XML) {
|
|
472
|
+
c.step(owner, 2);
|
|
473
|
+
boundaries.add(lo);
|
|
474
|
+
boundaries.add(hi + 1);
|
|
475
|
+
}
|
|
476
|
+
for (let m = 0; m < machines.length; m++)
|
|
477
|
+
for (const state of current.sets[m])
|
|
478
|
+
for (const edge of machines[m].edges[state]) {
|
|
479
|
+
c.step(owner);
|
|
480
|
+
for (const [lo, hi] of edge.ranges ?? []) {
|
|
481
|
+
c.step(owner, 2);
|
|
482
|
+
boundaries.add(lo);
|
|
483
|
+
boundaries.add(hi + 1);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
c.step(owner, boundaries.size * boundaries.size + boundaries.size + 1);
|
|
487
|
+
const points = [...boundaries].sort((a, b) => a - b);
|
|
488
|
+
for (let p = 0; p < points.length - 1; p++) {
|
|
489
|
+
const cp = points[p];
|
|
490
|
+
c.step(owner, 5);
|
|
491
|
+
if (!XML.some(([lo, hi]) => cp >= lo && cp <= hi))
|
|
492
|
+
continue;
|
|
493
|
+
c.step(owner, machines.length * 2 + 1);
|
|
494
|
+
const sets = [];
|
|
495
|
+
for (let m = 0; m < machines.length; m++) {
|
|
496
|
+
c.step(owner, 2);
|
|
497
|
+
const next = new Set();
|
|
498
|
+
for (const state of current.sets[m])
|
|
499
|
+
for (const edge of machines[m].edges[state]) {
|
|
500
|
+
c.step(owner);
|
|
501
|
+
for (const [lo, hi] of edge.ranges ?? []) {
|
|
502
|
+
c.step(owner, 2);
|
|
503
|
+
if (cp >= lo && cp <= hi) {
|
|
504
|
+
c.step(owner);
|
|
505
|
+
next.add(edge.to);
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
c.step(owner, next.size);
|
|
511
|
+
sets.push(closure(machines[m], [...next]));
|
|
512
|
+
}
|
|
513
|
+
if (impossible(sets)) {
|
|
514
|
+
if (dead === undefined) {
|
|
515
|
+
c.step(owner, XML.length * 4 + 5);
|
|
516
|
+
dead = states.length;
|
|
517
|
+
states.push({ sets: [], accepting: false, dead: true, transitions: XML.map(([lo, hi]) => ({ to: dead, lo, hi })) });
|
|
518
|
+
}
|
|
519
|
+
c.step(owner, 4);
|
|
520
|
+
current.transitions.push({ to: dead, lo: cp, hi: points[p + 1] - 1 });
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const identity = key(sets);
|
|
524
|
+
let target = visited.get(identity);
|
|
525
|
+
if (target === undefined) {
|
|
526
|
+
c.step(owner, identity.length + 8);
|
|
527
|
+
target = states.length;
|
|
528
|
+
visited.set(identity, target);
|
|
529
|
+
states.push({ sets, previous: cursor, char: String.fromCodePoint(cp), transitions: [] });
|
|
530
|
+
}
|
|
531
|
+
c.step(owner, 4);
|
|
532
|
+
current.transitions.push({ to: target, lo: cp, hi: points[p + 1] - 1 });
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return { word: undefined, states };
|
|
536
|
+
};
|
|
537
|
+
const witness = (language, owner) => {
|
|
538
|
+
read(language);
|
|
539
|
+
c.step(owner);
|
|
540
|
+
const known = witnesses.get(language);
|
|
541
|
+
if (known) {
|
|
542
|
+
if (known.word !== undefined)
|
|
543
|
+
c.text(known.word, owner);
|
|
544
|
+
return known.word;
|
|
545
|
+
}
|
|
546
|
+
const word = explore(language, owner, true).word;
|
|
547
|
+
// An aborted exploration throws before this publication. Only a complete
|
|
548
|
+
// finite emptiness result or an actual lexical witness enters the cache.
|
|
549
|
+
c.step(owner, 3);
|
|
550
|
+
witnesses.set(language, { word });
|
|
551
|
+
return word;
|
|
552
|
+
};
|
|
553
|
+
/** Finite Moore refinement. Canonical adjacent interval coalescing compares
|
|
554
|
+
* transition functions without expanding the XML character alphabet. */
|
|
555
|
+
const minimize = (program, owner) => {
|
|
556
|
+
c.step(owner, program.states.length * 3 + 4);
|
|
557
|
+
let count = 0;
|
|
558
|
+
const initial = new Map();
|
|
559
|
+
let blocks = program.states.map(state => {
|
|
560
|
+
let block = initial.get(state.accepting);
|
|
561
|
+
if (block === undefined) {
|
|
562
|
+
c.step(owner, 2);
|
|
563
|
+
block = count++;
|
|
564
|
+
initial.set(state.accepting, block);
|
|
565
|
+
}
|
|
566
|
+
return block;
|
|
567
|
+
});
|
|
568
|
+
const row = (index, partition) => {
|
|
569
|
+
c.step(owner, program.states[index].transitions.length * 4 + 3);
|
|
570
|
+
const result = [];
|
|
571
|
+
for (const edge of program.states[index].transitions) {
|
|
572
|
+
c.step(owner, 2);
|
|
573
|
+
const to = partition[edge.to], previous = result.at(-1);
|
|
574
|
+
if (previous?.to === to && previous.hi + 1 === edge.lo)
|
|
575
|
+
previous.hi = edge.hi;
|
|
576
|
+
else {
|
|
577
|
+
c.step(owner, 4);
|
|
578
|
+
result.push({ to, lo: edge.lo, hi: edge.hi });
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
};
|
|
583
|
+
while (true) {
|
|
584
|
+
c.step(owner, program.states.length + 4);
|
|
585
|
+
const signatures = new Map(), next = [];
|
|
586
|
+
for (let index = 0; index < program.states.length; index++) {
|
|
587
|
+
const transitions = row(index, blocks);
|
|
588
|
+
c.step(owner, transitions.length * 64 + 16);
|
|
589
|
+
const key = JSON.stringify([program.states[index].accepting, transitions]);
|
|
590
|
+
let block = signatures.get(key);
|
|
591
|
+
if (block === undefined) {
|
|
592
|
+
c.step(owner, 2);
|
|
593
|
+
block = signatures.size;
|
|
594
|
+
signatures.set(key, block);
|
|
595
|
+
}
|
|
596
|
+
next.push(block);
|
|
597
|
+
}
|
|
598
|
+
const stable = signatures.size === count;
|
|
599
|
+
blocks = next;
|
|
600
|
+
count = signatures.size;
|
|
601
|
+
if (stable)
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
c.step(owner, count * 3 + program.states.length + 4);
|
|
605
|
+
const states = new Array(count);
|
|
606
|
+
for (let index = 0; index < program.states.length; index++)
|
|
607
|
+
if (!states[blocks[index]])
|
|
608
|
+
states[blocks[index]] = { accepting: program.states[index].accepting, transitions: row(index, blocks) };
|
|
609
|
+
return { start: blocks[program.start], states };
|
|
610
|
+
};
|
|
611
|
+
const automaton = (language, owner) => {
|
|
612
|
+
c.step(owner);
|
|
613
|
+
let program = deterministic.get(language);
|
|
614
|
+
if (!program) {
|
|
615
|
+
const { states } = explore(language, owner, false);
|
|
616
|
+
c.step(owner, states.length * 3 + 2);
|
|
617
|
+
program = minimize({ start: 0, states: states.map(state => ({ accepting: state.accepting, transitions: state.transitions })) }, owner);
|
|
618
|
+
deterministic.set(language, program);
|
|
619
|
+
}
|
|
620
|
+
// Returned programs are snapshots. Mutating one cannot alter the private
|
|
621
|
+
// cache or a subsequently composed proof.
|
|
622
|
+
c.step(owner, program.states.length * 3 + 2);
|
|
623
|
+
return { start: program.start, states: program.states.map(state => {
|
|
624
|
+
c.step(owner, state.transitions.length * 4 + 2);
|
|
625
|
+
return { accepting: state.accepting, transitions: state.transitions.map(edge => ({ ...edge })) };
|
|
626
|
+
}) };
|
|
627
|
+
};
|
|
628
|
+
const materialize = (language, owner) => {
|
|
629
|
+
c.step(owner);
|
|
630
|
+
const known = materialized.get(language);
|
|
631
|
+
if (known)
|
|
632
|
+
return known;
|
|
633
|
+
const formula = read(language);
|
|
634
|
+
// Thompson machines are already composable. Determinizing a leaf before
|
|
635
|
+
// every concatenation needlessly repeats the full subset construction.
|
|
636
|
+
if (formula.kind === 'leaf')
|
|
637
|
+
return formula.machine;
|
|
638
|
+
const program = automaton(language, owner), edges = [];
|
|
639
|
+
c.step(owner, program.states.length * 2 + 4);
|
|
640
|
+
const end = program.states.length;
|
|
641
|
+
for (const state of program.states) {
|
|
642
|
+
c.step(owner, state.transitions.length * 6 + 3);
|
|
643
|
+
const row = state.transitions.map(edge => ({ to: edge.to, ranges: [[edge.lo, edge.hi]] }));
|
|
644
|
+
if (state.accepting) {
|
|
645
|
+
c.step(owner, 2);
|
|
646
|
+
row.push({ to: end });
|
|
647
|
+
}
|
|
648
|
+
edges.push(row);
|
|
649
|
+
}
|
|
650
|
+
c.step(owner, 3);
|
|
651
|
+
edges.push([]);
|
|
652
|
+
const machine = { start: program.start, end, edges };
|
|
653
|
+
materialized.set(language, machine);
|
|
654
|
+
return machine;
|
|
655
|
+
};
|
|
656
|
+
const fromAutomaton = (program, owner) => {
|
|
657
|
+
c.step(owner, program.states.length * 2 + 3);
|
|
658
|
+
const edges = [], end = program.states.length;
|
|
659
|
+
for (const state of program.states) {
|
|
660
|
+
c.step(owner, state.transitions.length * 6 + 3);
|
|
661
|
+
const row = state.transitions.map(edge => ({ to: edge.to, ranges: [[edge.lo, edge.hi]] }));
|
|
662
|
+
if (state.accepting) {
|
|
663
|
+
c.step(owner, 2);
|
|
664
|
+
row.push({ to: end });
|
|
665
|
+
}
|
|
666
|
+
edges.push(row);
|
|
667
|
+
}
|
|
668
|
+
c.step(owner);
|
|
669
|
+
edges.push([]);
|
|
670
|
+
return issue({ kind: 'leaf', machine: { edges, start: program.start, end } }, owner);
|
|
671
|
+
};
|
|
672
|
+
const paths = (program, starts, ends, owner) => {
|
|
673
|
+
c.step(owner, program.states.length * 2 + starts.length * 2 + 5);
|
|
674
|
+
const edges = [], start = program.states.length, end = start + 1;
|
|
675
|
+
for (let index = 0; index < program.states.length; index++) {
|
|
676
|
+
const state = program.states[index];
|
|
677
|
+
c.step(owner, state.transitions.length * 6 + 3);
|
|
678
|
+
const row = state.transitions.map(edge => ({ to: edge.to, ranges: [[edge.lo, edge.hi]] }));
|
|
679
|
+
if (ends.has(index)) {
|
|
680
|
+
c.step(owner, 2);
|
|
681
|
+
row.push({ to: end });
|
|
682
|
+
}
|
|
683
|
+
edges.push(row);
|
|
684
|
+
}
|
|
685
|
+
edges.push(starts.map(to => ({ to })), []);
|
|
686
|
+
return issue({ kind: 'leaf', machine: { edges, start, end } }, owner);
|
|
687
|
+
};
|
|
688
|
+
/** {x | there exist p in prefix and s in suffix with p x s in source}. */
|
|
689
|
+
const quotient = (source, prefix, suffix, owner) => {
|
|
690
|
+
const a = automaton(source, owner), p = automaton(prefix, owner), s = automaton(suffix, owner);
|
|
691
|
+
c.step(owner, a.states.length * s.states.length * 3 + 8);
|
|
692
|
+
const pairs = a.states.map(() => s.states.map(() => 0)), incoming = [];
|
|
693
|
+
for (let ai = 0; ai < a.states.length; ai++)
|
|
694
|
+
for (let si = 0; si < s.states.length; si++) {
|
|
695
|
+
c.step(owner, 2);
|
|
696
|
+
pairs[ai][si] = incoming.length;
|
|
697
|
+
incoming.push([]);
|
|
698
|
+
}
|
|
699
|
+
const useful = new Set(), pending = [];
|
|
700
|
+
for (let ai = 0; ai < a.states.length; ai++)
|
|
701
|
+
for (let si = 0; si < s.states.length; si++) {
|
|
702
|
+
c.step(owner);
|
|
703
|
+
const id = pairs[ai][si];
|
|
704
|
+
if (a.states[ai].accepting && s.states[si].accepting) {
|
|
705
|
+
c.step(owner, 2);
|
|
706
|
+
useful.add(id);
|
|
707
|
+
pending.push(id);
|
|
708
|
+
}
|
|
709
|
+
for (const ae of a.states[ai].transitions)
|
|
710
|
+
for (const se of s.states[si].transitions) {
|
|
711
|
+
c.step(owner, 2);
|
|
712
|
+
if (Math.max(ae.lo, se.lo) <= Math.min(ae.hi, se.hi))
|
|
713
|
+
incoming[pairs[ae.to][se.to]].push(id);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
while (pending.length) {
|
|
717
|
+
c.step(owner);
|
|
718
|
+
const id = pending.pop();
|
|
719
|
+
for (const before of incoming[id]) {
|
|
720
|
+
c.step(owner);
|
|
721
|
+
if (!useful.has(before)) {
|
|
722
|
+
c.step(owner, 2);
|
|
723
|
+
useful.add(before);
|
|
724
|
+
pending.push(before);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
c.step(owner, a.states.length + 4);
|
|
729
|
+
const ends = new Set();
|
|
730
|
+
for (let ai = 0; ai < a.states.length; ai++) {
|
|
731
|
+
c.step(owner);
|
|
732
|
+
if (useful.has(pairs[ai][s.start]))
|
|
733
|
+
ends.add(ai);
|
|
734
|
+
}
|
|
735
|
+
c.step(owner, 5);
|
|
736
|
+
const frontier = [[a.start, p.start]], seen = new Set([a.start + ':' + p.start]), starts = new Set();
|
|
737
|
+
for (let cursor = 0; cursor < frontier.length; cursor++) {
|
|
738
|
+
c.step(owner);
|
|
739
|
+
const [ai, pi] = frontier[cursor];
|
|
740
|
+
if (p.states[pi].accepting) {
|
|
741
|
+
c.step(owner);
|
|
742
|
+
starts.add(ai);
|
|
743
|
+
}
|
|
744
|
+
for (const ae of a.states[ai].transitions)
|
|
745
|
+
for (const pe of p.states[pi].transitions) {
|
|
746
|
+
c.step(owner, 2);
|
|
747
|
+
if (Math.max(ae.lo, pe.lo) > Math.min(ae.hi, pe.hi))
|
|
748
|
+
continue;
|
|
749
|
+
c.step(owner, 32);
|
|
750
|
+
const id = ae.to + ':' + pe.to;
|
|
751
|
+
if (!seen.has(id)) {
|
|
752
|
+
c.step(owner, 3);
|
|
753
|
+
seen.add(id);
|
|
754
|
+
frontier.push([ae.to, pe.to]);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
c.step(owner, starts.size);
|
|
759
|
+
return paths(a, [...starts], ends, owner);
|
|
760
|
+
};
|
|
761
|
+
const concatenate = (languages, owner) => {
|
|
762
|
+
c.step(owner, 4);
|
|
763
|
+
const edges = [[]];
|
|
764
|
+
let previous = 0;
|
|
765
|
+
for (const language of languages) {
|
|
766
|
+
const machine = materialize(language, owner), offset = edges.length;
|
|
767
|
+
c.step(owner, 3);
|
|
768
|
+
edges[previous].push({ to: machine.start + offset });
|
|
769
|
+
for (const row of machine.edges) {
|
|
770
|
+
c.step(owner, row.length * 5 + 2);
|
|
771
|
+
edges.push(row.map(edge => ({ ...edge, to: edge.to + offset })));
|
|
772
|
+
}
|
|
773
|
+
previous = machine.end + offset;
|
|
774
|
+
}
|
|
775
|
+
return issue({ kind: 'leaf', machine: { edges, start: 0, end: previous } }, owner);
|
|
776
|
+
};
|
|
777
|
+
const repeat = (language, min, max, owner) => {
|
|
778
|
+
const machine = materialize(language, owner);
|
|
779
|
+
c.step(owner, 4);
|
|
780
|
+
const edges = [[], []];
|
|
781
|
+
const clone = () => {
|
|
782
|
+
const offset = edges.length;
|
|
783
|
+
for (const row of machine.edges) {
|
|
784
|
+
c.step(owner, row.length * 5 + 2);
|
|
785
|
+
edges.push(row.map(edge => ({ ...edge, to: edge.to + offset })));
|
|
786
|
+
}
|
|
787
|
+
return { start: machine.start + offset, end: machine.end + offset };
|
|
788
|
+
};
|
|
789
|
+
let previous = 0;
|
|
790
|
+
for (let count = 0; count < (max === 'unbounded' ? min : max); count++) {
|
|
791
|
+
c.step(owner, 4);
|
|
792
|
+
if (count >= min)
|
|
793
|
+
edges[previous].push({ to: 1 });
|
|
794
|
+
const next = clone();
|
|
795
|
+
c.step(owner, 2);
|
|
796
|
+
edges[previous].push({ to: next.start });
|
|
797
|
+
previous = next.end;
|
|
798
|
+
}
|
|
799
|
+
c.step(owner, 2);
|
|
800
|
+
edges[previous].push({ to: 1 });
|
|
801
|
+
if (max === 'unbounded') {
|
|
802
|
+
const loop = clone();
|
|
803
|
+
c.step(owner, 4);
|
|
804
|
+
edges[previous].push({ to: loop.start });
|
|
805
|
+
edges[loop.end].push({ to: previous });
|
|
806
|
+
}
|
|
807
|
+
return issue({ kind: 'leaf', machine: { edges, start: 0, end: 1 } }, owner);
|
|
808
|
+
};
|
|
809
|
+
/** Complete inverse of XML whitespace normalization on a normalized language. */
|
|
810
|
+
const whitespacePreimage = (language, mode, owner) => {
|
|
811
|
+
if (mode === 'preserve')
|
|
812
|
+
return language;
|
|
813
|
+
const program = automaton(language, owner), edges = [];
|
|
814
|
+
const ws = [[9, 10], [13, 13], [32, 32]];
|
|
815
|
+
c.step(owner, program.states.length * 2 + 6);
|
|
816
|
+
for (const _state of program.states)
|
|
817
|
+
edges.push([]);
|
|
818
|
+
const start = edges.length;
|
|
819
|
+
edges.push([]);
|
|
820
|
+
const end = edges.length;
|
|
821
|
+
edges.push([]);
|
|
822
|
+
const link = (from, to, ranges) => { c.step(owner, 4); edges[from].push({ to, ranges }); };
|
|
823
|
+
link(start, program.start);
|
|
824
|
+
if (mode === 'collapse')
|
|
825
|
+
link(start, start, ws);
|
|
826
|
+
for (let from = 0; from < program.states.length; from++) {
|
|
827
|
+
const state = program.states[from];
|
|
828
|
+
if (state.accepting)
|
|
829
|
+
link(from, end);
|
|
830
|
+
for (const edge of state.transitions) {
|
|
831
|
+
c.step(owner, 3);
|
|
832
|
+
// Normalized languages exclude tab/LF/CR. Only output space has
|
|
833
|
+
// extra raw forms; all remaining XML characters map identically.
|
|
834
|
+
for (const [lo, hi] of complement([[9, 10], [13, 13], [32, 32]], owner)) {
|
|
835
|
+
const a = Math.max(lo, edge.lo), b = Math.min(hi, edge.hi);
|
|
836
|
+
if (a <= b)
|
|
837
|
+
link(from, edge.to, [[a, b]]);
|
|
838
|
+
}
|
|
839
|
+
if (edge.lo <= 32 && edge.hi >= 32) {
|
|
840
|
+
if (mode === 'replace')
|
|
841
|
+
link(from, edge.to, ws);
|
|
842
|
+
else {
|
|
843
|
+
c.step(owner, 2);
|
|
844
|
+
const middle = edges.length;
|
|
845
|
+
edges.push([]);
|
|
846
|
+
link(from, middle, ws);
|
|
847
|
+
link(middle, middle, ws);
|
|
848
|
+
link(middle, edge.to);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
if (mode === 'collapse')
|
|
854
|
+
link(end, end, ws);
|
|
855
|
+
return issue({ kind: 'leaf', machine: { edges, start, end } }, owner);
|
|
856
|
+
};
|
|
857
|
+
/** Finite transducer image of raw XML whitespace normalization. */
|
|
858
|
+
const whitespaceImage = (language, mode, owner) => {
|
|
859
|
+
if (mode === 'preserve')
|
|
860
|
+
return language;
|
|
861
|
+
const program = automaton(language, owner), phases = mode === 'collapse' ? 3 : 1, edges = [];
|
|
862
|
+
c.step(owner, program.states.length * phases * 2 + 6);
|
|
863
|
+
for (let index = 0; index < program.states.length * phases + 1; index++)
|
|
864
|
+
edges.push([]);
|
|
865
|
+
const end = edges.length - 1, state = (input, phase) => input * phases + phase;
|
|
866
|
+
const ws = [[9, 10], [13, 13], [32, 32]], other = complement(ws, owner);
|
|
867
|
+
const link = (from, to, ranges) => { c.step(owner, 4); edges[from].push({ to, ranges }); };
|
|
868
|
+
for (let input = 0; input < program.states.length; input++)
|
|
869
|
+
for (let phase = 0; phase < phases; phase++) {
|
|
870
|
+
const from = state(input, phase);
|
|
871
|
+
if (program.states[input].accepting)
|
|
872
|
+
link(from, end);
|
|
873
|
+
for (const edge of program.states[input].transitions) {
|
|
874
|
+
for (const [lo, hi] of ws) {
|
|
875
|
+
c.step(owner, 3);
|
|
876
|
+
if (Math.max(lo, edge.lo) > Math.min(hi, edge.hi))
|
|
877
|
+
continue;
|
|
878
|
+
if (mode === 'replace')
|
|
879
|
+
link(from, state(edge.to, 0), [[32, 32]]);
|
|
880
|
+
else
|
|
881
|
+
link(from, state(edge.to, phase === 0 ? 0 : 2));
|
|
882
|
+
}
|
|
883
|
+
for (const [lo, hi] of other) {
|
|
884
|
+
c.step(owner, 3);
|
|
885
|
+
const a = Math.max(lo, edge.lo), b = Math.min(hi, edge.hi);
|
|
886
|
+
if (a > b)
|
|
887
|
+
continue;
|
|
888
|
+
const to = state(edge.to, mode === 'replace' ? 0 : 1);
|
|
889
|
+
if (phase !== 2)
|
|
890
|
+
link(from, to, [[a, b]]);
|
|
891
|
+
else {
|
|
892
|
+
c.step(owner, 2);
|
|
893
|
+
const middle = edges.length;
|
|
894
|
+
edges.push([]);
|
|
895
|
+
link(from, middle, [[32, 32]]);
|
|
896
|
+
link(middle, to, [[a, b]]);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return issue({ kind: 'leaf', machine: { edges, start: state(program.start, 0), end } }, owner);
|
|
902
|
+
};
|
|
903
|
+
const characterImage = (language, changes, owner) => {
|
|
904
|
+
const program = automaton(language, owner), edges = [], end = program.states.length;
|
|
905
|
+
c.step(owner, program.states.length * 2 + changes.length * 2 + 4);
|
|
906
|
+
for (const state of program.states) {
|
|
907
|
+
c.step(owner, state.transitions.length * 2 + 3);
|
|
908
|
+
const row = [];
|
|
909
|
+
if (state.accepting)
|
|
910
|
+
row.push({ to: end });
|
|
911
|
+
for (const edge of state.transitions) {
|
|
912
|
+
c.step(owner, changes.length * 4 + 4);
|
|
913
|
+
const points = new Set([edge.lo, edge.hi + 1]);
|
|
914
|
+
for (const change of changes)
|
|
915
|
+
if (change.lo <= edge.hi && change.hi >= edge.lo) {
|
|
916
|
+
points.add(Math.max(edge.lo, change.lo));
|
|
917
|
+
points.add(Math.min(edge.hi + 1, change.hi + 1));
|
|
918
|
+
}
|
|
919
|
+
c.step(owner, points.size ** 2 + points.size + 2);
|
|
920
|
+
const ordered = [...points].sort((a, b) => a - b);
|
|
921
|
+
for (let index = 0; index + 1 < ordered.length; index++) {
|
|
922
|
+
c.step(owner, changes.length + 4);
|
|
923
|
+
const lo = ordered[index], hi = ordered[index + 1] - 1, change = changes.find(change => lo >= change.lo && hi <= change.hi);
|
|
924
|
+
row.push({ to: edge.to, ranges: change?.remove ? undefined : [[lo + (change?.shift ?? 0), hi + (change?.shift ?? 0)]] });
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
edges.push(row);
|
|
928
|
+
}
|
|
929
|
+
c.step(owner);
|
|
930
|
+
edges.push([]);
|
|
931
|
+
return issue({ kind: 'leaf', machine: { edges, start: program.start, end } }, owner);
|
|
932
|
+
};
|
|
933
|
+
const reverse = (language, owner) => {
|
|
934
|
+
const machine = materialize(language, owner);
|
|
935
|
+
c.step(owner, machine.edges.length * 2 + 3);
|
|
936
|
+
const edges = machine.edges.map(() => []);
|
|
937
|
+
for (let from = 0; from < machine.edges.length; from++)
|
|
938
|
+
for (const edge of machine.edges[from]) {
|
|
939
|
+
c.step(owner, 4);
|
|
940
|
+
edges[edge.to].push({ to: from, ranges: edge.ranges });
|
|
941
|
+
}
|
|
942
|
+
return issue({ kind: 'leaf', machine: { edges, start: machine.end, end: machine.start } }, owner);
|
|
943
|
+
};
|
|
944
|
+
const fromNfa = (program, owner) => {
|
|
945
|
+
c.step(owner, program.edges.length * 2 + 3);
|
|
946
|
+
const edges = program.edges.map(row => {
|
|
947
|
+
c.step(owner, row.length * 4 + 2);
|
|
948
|
+
return row.map(edge => {
|
|
949
|
+
c.step(owner, (edge.ranges?.length ?? 0) * 3 + 2);
|
|
950
|
+
return { to: edge.to, ranges: edge.ranges?.map(([lo, hi]) => [lo, hi]) };
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
return issue({ kind: 'leaf', machine: { edges, start: program.start, end: program.end } }, owner);
|
|
954
|
+
};
|
|
955
|
+
const substitutionGraph = (count, start, end, labels, owner) => {
|
|
956
|
+
c.step(owner, count * 2 + labels.length * 2 + 4);
|
|
957
|
+
const edges = [];
|
|
958
|
+
for (let index = 0; index < count; index++)
|
|
959
|
+
edges.push([]);
|
|
960
|
+
for (const label of labels) {
|
|
961
|
+
const machine = materialize(label.language, owner), offset = edges.length;
|
|
962
|
+
c.step(owner, 4);
|
|
963
|
+
edges[label.from].push({ to: machine.start + offset });
|
|
964
|
+
for (const row of machine.edges) {
|
|
965
|
+
c.step(owner, row.length * 5 + 2);
|
|
966
|
+
edges.push(row.map(edge => ({ ...edge, to: edge.to + offset })));
|
|
967
|
+
}
|
|
968
|
+
c.step(owner, 2);
|
|
969
|
+
edges[machine.end + offset].push({ to: label.to });
|
|
970
|
+
}
|
|
971
|
+
return issue({ kind: 'leaf', machine: { edges, start, end } }, owner);
|
|
972
|
+
};
|
|
973
|
+
const jsonStringImage = (language, owner) => {
|
|
974
|
+
const program = automaton(language, owner), edges = [], end = program.states.length;
|
|
975
|
+
c.step(owner, program.states.length * 2 + 4);
|
|
976
|
+
for (let index = 0; index <= end; index++)
|
|
977
|
+
edges.push([]);
|
|
978
|
+
for (let from = 0; from < program.states.length; from++) {
|
|
979
|
+
if (program.states[from].accepting) {
|
|
980
|
+
c.step(owner, 2);
|
|
981
|
+
edges[from].push({ to: end });
|
|
982
|
+
}
|
|
983
|
+
for (const edge of program.states[from].transitions) {
|
|
984
|
+
c.step(owner, 14);
|
|
985
|
+
const points = [edge.lo, edge.hi + 1];
|
|
986
|
+
for (const cp of [9, 10, 13, 34, 92])
|
|
987
|
+
if (cp >= edge.lo && cp <= edge.hi)
|
|
988
|
+
points.push(cp, cp + 1);
|
|
989
|
+
c.step(owner, points.length ** 2 + 2);
|
|
990
|
+
points.sort((a, b) => a - b);
|
|
991
|
+
for (let index = 0; index + 1 < points.length; index++) {
|
|
992
|
+
const lo = points[index], hi = points[index + 1] - 1;
|
|
993
|
+
c.step(owner, 5);
|
|
994
|
+
if (lo > hi)
|
|
995
|
+
continue;
|
|
996
|
+
const escaped = lo === hi && [9, 10, 13, 34, 92].includes(lo);
|
|
997
|
+
if (!escaped)
|
|
998
|
+
edges[from].push({ to: edge.to, ranges: [[lo, hi]] });
|
|
999
|
+
else {
|
|
1000
|
+
c.step(owner, 6);
|
|
1001
|
+
const middle = edges.length;
|
|
1002
|
+
edges.push([]);
|
|
1003
|
+
edges[from].push({ to: middle, ranges: [[92, 92]] });
|
|
1004
|
+
const cp = lo === 9 ? 116 : lo === 10 ? 110 : lo === 13 ? 114 : lo;
|
|
1005
|
+
edges[middle].push({ to: edge.to, ranges: [[cp, cp]] });
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return issue({ kind: 'leaf', machine: { edges, start: program.start, end } }, owner);
|
|
1011
|
+
};
|
|
1012
|
+
/** Exhaustive words only when the productive deterministic graph is acyclic. */
|
|
1013
|
+
const finiteWords = (language, owner) => {
|
|
1014
|
+
const { states } = explore(language, owner, false);
|
|
1015
|
+
c.step(owner, states.length * 3 + 3);
|
|
1016
|
+
const incoming = states.map(() => []), productive = new Set(), pending = [];
|
|
1017
|
+
for (let from = 0; from < states.length; from++) {
|
|
1018
|
+
c.step(owner, 2);
|
|
1019
|
+
if (states[from].accepting) {
|
|
1020
|
+
c.step(owner, 2);
|
|
1021
|
+
productive.add(from);
|
|
1022
|
+
pending.push(from);
|
|
1023
|
+
}
|
|
1024
|
+
for (const transition of states[from].transitions) {
|
|
1025
|
+
c.step(owner);
|
|
1026
|
+
incoming[transition.to].push(from);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
while (pending.length) {
|
|
1030
|
+
c.step(owner);
|
|
1031
|
+
const current = pending.pop();
|
|
1032
|
+
for (const from of incoming[current]) {
|
|
1033
|
+
c.step(owner);
|
|
1034
|
+
if (!productive.has(from)) {
|
|
1035
|
+
c.step(owner, 2);
|
|
1036
|
+
productive.add(from);
|
|
1037
|
+
pending.push(from);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
c.step(owner, states.length * 2 + 2);
|
|
1042
|
+
const degrees = states.map(() => 0), queue = [];
|
|
1043
|
+
for (const from of productive)
|
|
1044
|
+
for (const transition of states[from].transitions) {
|
|
1045
|
+
c.step(owner);
|
|
1046
|
+
if (productive.has(transition.to))
|
|
1047
|
+
degrees[transition.to]++;
|
|
1048
|
+
}
|
|
1049
|
+
for (const from of productive) {
|
|
1050
|
+
c.step(owner);
|
|
1051
|
+
if (degrees[from] === 0)
|
|
1052
|
+
queue.push(from);
|
|
1053
|
+
}
|
|
1054
|
+
let removed = 0;
|
|
1055
|
+
for (let cursor = 0; cursor < queue.length; cursor++) {
|
|
1056
|
+
c.step(owner);
|
|
1057
|
+
const from = queue[cursor];
|
|
1058
|
+
removed++;
|
|
1059
|
+
for (const transition of states[from].transitions) {
|
|
1060
|
+
c.step(owner);
|
|
1061
|
+
if (productive.has(transition.to) && --degrees[transition.to] === 0) {
|
|
1062
|
+
c.step(owner);
|
|
1063
|
+
queue.push(transition.to);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
if (removed !== productive.size)
|
|
1068
|
+
return { kind: 'infinite' };
|
|
1069
|
+
function* words() {
|
|
1070
|
+
if (!productive.has(0))
|
|
1071
|
+
return;
|
|
1072
|
+
c.step(owner, 6);
|
|
1073
|
+
const stack = [{ state: 0, word: '', transition: 0, entered: false }];
|
|
1074
|
+
while (stack.length) {
|
|
1075
|
+
c.step(owner);
|
|
1076
|
+
const frame = stack.at(-1);
|
|
1077
|
+
if (!frame.entered) {
|
|
1078
|
+
frame.entered = true;
|
|
1079
|
+
if (states[frame.state].accepting) {
|
|
1080
|
+
c.text(frame.word, owner);
|
|
1081
|
+
yield frame.word;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
const edge = states[frame.state].transitions[frame.transition];
|
|
1085
|
+
if (!edge) {
|
|
1086
|
+
stack.pop();
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
if (!productive.has(edge.to)) {
|
|
1090
|
+
frame.transition++;
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
const cp = frame.point ?? edge.lo;
|
|
1094
|
+
if (cp === edge.hi) {
|
|
1095
|
+
frame.transition++;
|
|
1096
|
+
frame.point = undefined;
|
|
1097
|
+
}
|
|
1098
|
+
else
|
|
1099
|
+
frame.point = cp + 1;
|
|
1100
|
+
c.step(owner, frame.word.length + 8);
|
|
1101
|
+
stack.push({ state: edge.to, word: frame.word + String.fromCodePoint(cp), transition: 0, entered: false });
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
c.step(owner, 2);
|
|
1105
|
+
return { kind: 'finite', words: words() };
|
|
1106
|
+
};
|
|
1107
|
+
/** Fair exhaustive positive search; absence is never inferred from this. */
|
|
1108
|
+
const words = (language, owner) => {
|
|
1109
|
+
const program = automaton(language, owner);
|
|
1110
|
+
c.step(owner, program.states.length * 3 + 4);
|
|
1111
|
+
const incoming = program.states.map(() => []), useful = new Set(), pending = [];
|
|
1112
|
+
for (let from = 0; from < program.states.length; from++) {
|
|
1113
|
+
if (program.states[from].accepting) {
|
|
1114
|
+
c.step(owner, 2);
|
|
1115
|
+
useful.add(from);
|
|
1116
|
+
pending.push(from);
|
|
1117
|
+
}
|
|
1118
|
+
for (const edge of program.states[from].transitions) {
|
|
1119
|
+
c.step(owner);
|
|
1120
|
+
incoming[edge.to].push(from);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
while (pending.length) {
|
|
1124
|
+
c.step(owner);
|
|
1125
|
+
const state = pending.pop();
|
|
1126
|
+
for (const before of incoming[state]) {
|
|
1127
|
+
c.step(owner);
|
|
1128
|
+
if (!useful.has(before)) {
|
|
1129
|
+
c.step(owner, 2);
|
|
1130
|
+
useful.add(before);
|
|
1131
|
+
pending.push(before);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
function* enumerate() {
|
|
1136
|
+
if (!useful.has(program.start))
|
|
1137
|
+
return;
|
|
1138
|
+
c.step(owner, 4);
|
|
1139
|
+
let frontier = [{ state: program.start, word: '' }];
|
|
1140
|
+
while (frontier.length) {
|
|
1141
|
+
c.step(owner, 2);
|
|
1142
|
+
const next = [];
|
|
1143
|
+
for (const { state, word } of frontier) {
|
|
1144
|
+
c.step(owner);
|
|
1145
|
+
if (program.states[state].accepting) {
|
|
1146
|
+
c.text(word, owner);
|
|
1147
|
+
yield word;
|
|
1148
|
+
}
|
|
1149
|
+
for (const edge of program.states[state].transitions) {
|
|
1150
|
+
c.step(owner);
|
|
1151
|
+
if (!useful.has(edge.to))
|
|
1152
|
+
continue;
|
|
1153
|
+
c.step(owner, (edge.hi - edge.lo + 1) * (word.length + 6));
|
|
1154
|
+
for (let cp = edge.lo; cp <= edge.hi; cp++)
|
|
1155
|
+
next.push({ state: edge.to, word: word + String.fromCodePoint(cp) });
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
frontier = next;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return enumerate();
|
|
1162
|
+
};
|
|
1163
|
+
return { fromPattern, intersect: (languages, owner) => combine('and', languages, owner),
|
|
1164
|
+
union: (languages, owner) => combine('or', languages, owner), negate, witness, finiteWords,
|
|
1165
|
+
automaton, fromAutomaton, fromNfa, substitutionGraph, jsonStringImage, paths, quotient, reverse, concatenate, repeat, whitespacePreimage, whitespaceImage, characterImage, words };
|
|
1166
|
+
}
|