feat(runtime-expressions): improve ABNF grammar clarity#454
feat(runtime-expressions): improve ABNF grammar clarity#454frankkilcommins wants to merge 4 commits intoOAI:v1.1-devfrom
Conversation
examples/1.0.0/bnpl-arazzo.yaml
Outdated
| "firstName": "{$inputs.customer#/firstName}", | ||
| "lastName": "{$inputs.customer#/lastName}", | ||
| "dateOfBirth": "{$inputs.customer#/dateOfBirth}", | ||
| "postalCode": "{$inputs.customer#/postalCode}" |
There was a problem hiding this comment.
It would be great to include more complex and diverse examples demonstrating the application of ABNF syntax.
| component-name = identifier | ||
|
|
||
| ; Identifier rule | ||
| identifier = 1*( ALPHA / DIGIT / "." / "-" / "_" ) |
There was a problem hiding this comment.
The PR's identifier = 1*( ALPHA / DIGIT / "." / "-" / "_" ) is used for all IDs (stepId, workflowId, sourceDescriptionName, component keys, input/output names). But the spec defines two
different patterns:
- stepId, workflowId, sourceDescriptionName: SHOULD [A-Za-z0-9_-]+ (no dot)
- Components keys: MUST ^[a-zA-Z0-9.-_]+$ (with dot)
A single shared identifier rule conflates these — it allows dots in step/workflow IDs where the spec says they shouldn't be, and it's only SHOULD-level enforcement anyway. Separate rules would
be more faithful to the spec's intent.
| field-name = identifier | ||
|
|
||
| ; Source descriptions expressions | ||
| source-reference = source-name "." reference-id |
There was a problem hiding this comment.
source-reference is too restrictive with identifier
The proposed grammar uses:
source-reference = source-name "." reference-id
reference-id = identifier
The <reference> part can be an operationId from an OpenAPI description or a workflowId from
an Arazzo document. OpenAPI does not constrain operationId to any specific character set —
it's just a string. This means operationIds like get/pets, get pets, or create-user@v2 are
technically valid in OpenAPI but would be rejected by the identifier rule.
I'd suggest using a less restrictive rule for reference-id — something like 1*CHAR (any
character except { and }) — to avoid rejecting valid OpenAPI operationIds.
There was a problem hiding this comment.
updated to:
; Source descriptions expressions
source-reference = source-name "." reference-id
source-name = identifier-strict
reference-id = 1*CHAR
; operationIds have no character restrictions in OpenAPI/AsyncAPI
; Resolution priority defined in spec text: (1) operationId/workflowId, (2) field names
Restructure the ABNF grammar to use explicit, typed reference rules in the primary grammar instead of relying on secondary grammars with two-pass parsing. This improves grammar clarity and aligns with the proposed spec changes in OAI/Arazzo-Specification#454. Key changes: - Add $self expression support - Add $inputs/$outputs JSON Pointer support (e.g., $inputs.customer#/firstName) - Inline all secondary grammars into the primary grammar - Extract shared identifier and identifier-strict rules - Adapt json-pointer to exclude { and } from unescaped for unambiguous embedded expression parsing, fixing the body expression extract limitation - Require explicit component types (parameters/successActions/failureActions) - Update README with current grammar and examples Resolves: OAI/Arazzo-Specification#424, OAI/Arazzo-Specification#425, OAI/Arazzo-Specification#426, OAI/Arazzo-Specification#428 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementation VerificationI implemented the proposed grammar changes in my ABNF parser at swaggerexpert/arazzo-runtime-expression#116 to verify the grammar is correct and parseable. All 152 tests pass. Below are the findings from the implementation. Issue:
|
| unescaped = %x00-2E / %x30-7D / %x7F-10FFFF | ||
| ; %x2F ('/') and %x7E ('~') excluded from 'unescaped' | ||
| unescaped = %x00-2E / %x30-7A / %x7C / %x7E-10FFFF | ||
| ; Excludes / (%x2F), { (%x7B), } (%x7D), and ~ (%x7E) |
There was a problem hiding this comment.
Will it make sense to explicitly define some other literals, like boolean, undefined, null?
They can be used in runtime expressions.
// Boolean literals for true and false
Boolean
= "true" / "false"
// Null literal
Null
= "null"
Undefined
= "undefined"
There was a problem hiding this comment.
The literals (boolean, null, undefined) are used in Criterion Object conditions alongside runtime expressions, not within runtime expressions themselves. These are already defined in the Criterion Object section as part of the condition syntax. The ABNF grammar here specifically defines the structure of runtime expressions ($inputs.foo, $statusCode, etc.), which reference values but don't contain literals. The condition evaluation syntax is separate from the runtime expression parsing syntax.
Do you have scenarios that you're thinking of? I'd tend to scope that under a different enhancement issue if warranted.
|
Hi @frankkilcommins, Hi Frank, Great progress on the grammar updates — the I noticed a couple of issues with the latest changes.
|
$components now requires explicit component type (parameters/successActions/failureActions). Generic components.name pattern removed. Note: This was already semantically invalid per spec.
fixes: #424
fixes: #425
fixes: #426
fixes: #428
fixes: #437
resolves: #427