RiffDB Contract Language Reference v26
This is the complete grammar-version-26 parser source. Grammar v26 adds
contextual mutate first selection under statically proved pool ownership.
Normative semantics, bounds, compatibility gates, and the prohibition on
general loops and raw transactions are defined by ADR-0002 as amended by
ADR-0015, ADR-0107, ADR-0109, ADR-0133, ADR-0136, ADR-0153, ADR-0173, ADR-0256, ADR-0262, and ADR-0264. Semantic actions below construct only the
source-oriented AST; they are not typed IR, an executable plan, or a durable
encoding.
Complete Grammar
use crate::ast::*;
use crate::diagnostic::SyntaxDiagnostic;
use crate::lexer::Token;
use crate::parser::{self, ParsedExpression};
use crate::span::Spanned;
grammar;
pub ContractDocument: ContractDocument = {
<contract:ContractDeclaration> => ContractDocument { contract },
};
ContractDeclaration: Spanned<Contract> = {
<lo:@L> "contract" <name:Identifier> "version" <version:UnsignedInteger>
"{" <declarations:Declaration*> "}" <hi:@R>
=> parser::spanned(Contract { name, version, declarations }, lo, hi),
};
Declaration: Spanned<Declaration> = {
<lo:@L> <entity:EntityDeclaration> <hi:@R>
=> parser::spanned(Declaration::Entity(entity), lo, hi),
<lo:@L> <event:EventDeclaration> <hi:@R>
=> parser::spanned(Declaration::Event(event), lo, hi),
<lo:@L> <enumeration:EnumDeclaration> <hi:@R>
=> parser::spanned(Declaration::Enum(enumeration), lo, hi),
<lo:@L> <aggregate:AggregateDeclaration> <hi:@R>
=> parser::spanned(Declaration::Aggregate(aggregate), lo, hi),
<lo:@L> <command:CommandDeclaration> <hi:@R>
=> parser::spanned(Declaration::Command(command), lo, hi),
<lo:@L> <workflow:WorkflowDeclaration> <hi:@R>
=> parser::spanned(Declaration::Workflow(workflow), lo, hi),
<lo:@L> <projection:ProjectionDeclaration> <hi:@R>
=> parser::spanned(Declaration::Projection(projection), lo, hi),
<lo:@L> <columnar:ColumnarProjectionDeclaration> <hi:@R>
=> parser::spanned(Declaration::ColumnarProjection(columnar), lo, hi),
<lo:@L> <fact:PrincipalFactDeclaration> <hi:@R>
=> parser::spanned(Declaration::PrincipalFact(fact), lo, hi),
<lo:@L> <policy:RowPolicyDeclaration> <hi:@R>
=> parser::spanned(Declaration::RowPolicy(policy), lo, hi),
};
PrincipalFactDeclaration: PrincipalFactDeclaration = {
"principal" "fact" <name:Identifier> ":" <ty:TypeExpression>
=> PrincipalFactDeclaration { name, ty },
};
RowPolicyDeclaration: RowPolicyDeclaration = {
"row" "policy" <name:Identifier> "on" <entity:Identifier>
"{" <rules:RowPolicyRule+> "}"
=> RowPolicyDeclaration { name, entity, rules },
};
RowPolicyRule: Spanned<RowPolicyRule> = {
<lo:@L> "allow" <operation:RowPolicyOperation> "when"
<expression:RowPolicyExpression> <hi:@R>
=> parser::spanned(RowPolicyRule { operation, expression: expression.into_syntax() }, lo, hi),
};
RowPolicyOperation: Spanned<RowPolicyOperation> = {
<lo:@L> "read" <hi:@R> => parser::spanned(RowPolicyOperation::Read, lo, hi),
<lo:@L> "create" <hi:@R> => parser::spanned(RowPolicyOperation::Create, lo, hi),
<lo:@L> "update" <hi:@R> => parser::spanned(RowPolicyOperation::Update, lo, hi),
<lo:@L> "delete" <hi:@R> => parser::spanned(RowPolicyOperation::Delete, lo, hi),
};
RowPolicyExpression: parser::ParsedRowPolicyExpression = RowPolicyOrExpression;
RowPolicyOrExpression: parser::ParsedRowPolicyExpression = {
<left:RowPolicyAndExpression> <rest:(<OrOperator> <RowPolicyAndExpression>)*>
=>? parser::grammar_result(parser::row_policy_binary_chain(left, rest)),
};
RowPolicyAndExpression: parser::ParsedRowPolicyExpression = {
<left:RowPolicyPredicate> <rest:(<AndOperator> <RowPolicyPredicate>)*>
=>? parser::grammar_result(parser::row_policy_binary_chain(left, rest)),
};
RowPolicyPredicate: parser::ParsedRowPolicyExpression = {
<left:RowPolicyUnary> <operator:ComparisonOperator> <right:RowPolicyUnary>
=>? parser::grammar_result(parser::row_policy_binary(left, operator, right)),
<needle:RowPolicyUnary> "in" <haystack:RowPolicyUnary>
=>? parser::grammar_result(parser::row_policy_in(needle, haystack)),
<value:RowPolicyUnary> "is" <negated:("not")?> "null"
=>? parser::grammar_result(parser::row_policy_is_null(value, negated.is_some())),
RowPolicyUnary,
};
RowPolicyUnary: parser::ParsedRowPolicyExpression = {
<lo:@L> "!" <value:RowPolicyUnary> <hi:@R>
=>? parser::grammar_result(parser::row_policy_not(value, parser::span(lo, hi))),
RowPolicyPrimary,
};
RowPolicyPrimary: parser::ParsedRowPolicyExpression = {
<literal:Literal> => parser::row_policy_literal(literal),
<path:RowPolicyPath> => parser::row_policy_path(path),
<lo:@L> "(" <expression:RowPolicyExpression> ")" <hi:@R>
=>? parser::grammar_result(parser::row_policy_parenthesized(expression, parser::span(lo, hi))),
<lo:@L> "exists" <entity:Identifier> "." <index:Identifier>
"(" <arguments:RowPolicyArgumentList> ")" <hi:@R>
=>? parser::grammar_result(parser::row_policy_exists(entity, index, arguments, parser::span(lo, hi))),
};
RowPolicyArgumentList: Vec<parser::ParsedRowPolicyExpression> = {
<head:RowPolicyExpression> <tail:("," <RowPolicyExpression>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head];
values.extend(tail);
values
},
};
RowPolicyPath: Spanned<Path> = {
<lo:@L> <head:RowPolicyPathSegment> <tail:("." <RowPolicyPathSegment>)*> <hi:@R> => {
let mut segments = vec![head];
segments.extend(tail);
parser::spanned(Path { segments }, lo, hi)
},
};
RowPolicyPathSegment: Spanned<String> = {
Identifier,
};
WorkflowDeclaration: WorkflowDeclaration = {
"workflow" <name:Identifier> "{"
"entity" <entity:Identifier>
"state" <state_field:Identifier>
<initial_state:("initial" <Identifier>)?>
<transitions:WorkflowTransitionDeclaration+>
<lease:WorkflowLeaseDeclaration?>
"}" => WorkflowDeclaration { name, entity, state_field, initial_state, transitions, lease },
};
WorkflowTransitionDeclaration: Spanned<WorkflowTransitionDeclaration> = {
<lo:@L> "transition" <name:Identifier> "from" "(" <source_states:IdentifierList> ")"
"to" <destination:Identifier> <hi:@R>
=> parser::spanned(WorkflowTransitionDeclaration {
name,
source_states,
destination,
}, lo, hi),
};
WorkflowLeaseDeclaration: Spanned<WorkflowLeaseDeclaration> = {
<lo:@L> "lease" <name:Identifier> "{"
"owner" <owner_field:Identifier>
"expires_at" <expiry_field:Identifier>
"fencing_token" <fencing_token_field:Identifier>
<attempt_field:WorkflowLeaseAttempts?>
"duration_seconds" "(" <minimum_duration_seconds:UnsignedInteger> ","
<maximum_duration_seconds:UnsignedInteger> ")"
"}" <hi:@R> => parser::spanned(WorkflowLeaseDeclaration {
name,
owner_field,
expiry_field,
fencing_token_field,
attempt_field,
minimum_duration_seconds,
maximum_duration_seconds,
}, lo, hi),
};
WorkflowLeaseAttempts: Spanned<String> = {
"attempts" <field:Identifier> => field,
};
EntityDeclaration: EntityDeclaration = {
"entity" <name:Identifier> "{" <items:EntityItem*> "}"
=> EntityDeclaration { name, items },
};
EntityItem: Spanned<EntityItem> = {
<lo:@L> "key" "(" <fields:TypedFieldList> ")" <hi:@R>
=> parser::spanned(EntityItem::Key(KeyDeclaration { fields }), lo, hi),
<lo:@L> "field" <field:TypedField> <hi:@R>
=> parser::spanned(EntityItem::Field(FieldDeclaration {
secret: None,
name: field.name,
ty: field.ty,
}), lo, hi),
// Contextual: the classification modifier is an ordinary identifier
// everywhere except between `field` and the field name, so `field
// secret: ...` stays a valid field named `secret` (ADR-0118 additive
// compatibility).
<lo:@L> "field" <modifier:Identifier> <field:TypedField> <hi:@R>
=>? parser::grammar_result(parser::classified_field_item(modifier, field, lo, hi)),
<lo:@L> <invariant:InvariantDeclaration> <hi:@R>
=> parser::spanned(EntityItem::Invariant(invariant), lo, hi),
<lo:@L> "index" <name:Identifier> "(" <fields:IdentifierList> ")"
<options:IndexOption*> <hi:@R>
=> parser::spanned(EntityItem::Index(IndexDeclaration { name, fields, options }), lo, hi),
<lo:@L> "unique" <name:Identifier> "(" <fields:IdentifierList> ")" <hi:@R>
=> parser::spanned(EntityItem::Unique(UniqueDeclaration { name, fields }), lo, hi),
<lo:@L> "reference" <name:Identifier> "(" <source_fields:IdentifierList> ")"
"->" <target_entity:Identifier> "(" <target_fields:IdentifierList> ")" <hi:@R>
=> parser::spanned(EntityItem::Reference(ReferenceDeclaration {
name,
source_fields,
target_entity,
target_fields,
}), lo, hi),
<lo:@L> "vector_field" <name:Identifier> "(" <dimension:UnsignedInteger> ","
<metric:VectorMetric> "," "(" <source_fields:IdentifierList> ")" ","
<slo_keyword:Identifier> <staleness_slo:UnsignedInteger>
<production:VectorProductionClause?>
<ann:VectorAnnClause?> ")" <hi:@R>
=>? parser::grammar_result(parser::vector_field_item(
name,
dimension,
metric,
source_fields,
slo_keyword,
staleness_slo,
production,
ann,
lo,
hi,
)),
<lo:@L> "text_index" <name:Identifier> "(" "(" <source_fields:TextIndexSourceList> ")"
"," <analyzer_keyword:Identifier> <analyzer:Identifier>
"," <slo_keyword:Identifier> <staleness_slo:UnsignedInteger>
"," <age_keyword:Identifier> <replay_age_seconds:UnsignedInteger>
"," <bytes_keyword:Identifier> <replay_bytes:UnsignedInteger>
"," <backlog_keyword:Identifier> <replay_backlog:UnsignedInteger>
"," <result_keyword:Identifier> <result_model:Identifier>
"," <terms_keyword:Identifier> <max_terms:UnsignedInteger>
"," <candidates_keyword:Identifier> <max_candidates:UnsignedInteger>
"," <results_keyword:Identifier> <max_results:UnsignedInteger>
")" <hi:@R>
=>? parser::grammar_result(parser::text_index_item(
name,
source_fields,
analyzer_keyword,
analyzer,
slo_keyword,
staleness_slo,
age_keyword,
replay_age_seconds,
bytes_keyword,
replay_bytes,
backlog_keyword,
replay_backlog,
result_keyword,
result_model,
terms_keyword,
max_terms,
candidates_keyword,
max_candidates,
results_keyword,
max_results,
lo,
hi,
)),
<lo:@L> "pattern_index" <name:Identifier> "(" <field:Identifier>
"," <profile_keyword:Identifier> <profile:Identifier>
"," <operators_keyword:Identifier> "(" <operators:IdentifierList> ")"
"," <bounds:LongPatternBounds> ")" <hi:@R>
=>? parser::grammar_result(parser::long_pattern_item(
name,
field,
profile_keyword,
profile,
operators_keyword,
operators,
bounds,
lo,
hi,
)),
<lo:@L> "delete_policy" "no_inbound" <hi:@R>
=> parser::spanned(EntityItem::DeletePolicy(DeletePolicyDeclaration::NoInbound), lo, hi),
<lo:@L> "delete_policy" "restrict" <source_entity:Identifier> "." <index:Identifier> <hi:@R>
=> parser::spanned(EntityItem::DeletePolicy(DeletePolicyDeclaration::Restrict {
source_entity,
index,
}), lo, hi),
<lo:@L> "delete_policy" "cascade" "{" <relationships:CascadeRelationship+> "}" <hi:@R>
=> parser::spanned(EntityItem::DeletePolicy(DeletePolicyDeclaration::Cascade {
relationships,
}), lo, hi),
};
LongPatternBounds: Vec<LongPatternBoundDeclaration> = {
<head:LongPatternBound> <tail:("," <LongPatternBound>)*> => {
let mut values = vec![head];
values.extend(tail);
values
},
};
LongPatternBound: LongPatternBoundDeclaration = {
<name:Identifier> <value:UnsignedInteger> => LongPatternBoundDeclaration { name, value },
};
TextIndexSourceList: Vec<Spanned<TextIndexSourceDeclaration>> = {
=> Vec::new(),
<head:TextIndexSource> <tail:("," <TextIndexSource>)*> <_trailing:Comma?> => {
let mut values = vec![head];
values.extend(tail);
values
},
};
TextIndexSource: Spanned<TextIndexSourceDeclaration> = {
<lo:@L> <field:Identifier> <weight_keyword:Identifier> <weight:UnsignedInteger> <hi:@R>
=> parser::spanned(TextIndexSourceDeclaration { field, weight_keyword, weight }, lo, hi),
};
VectorProductionClause: VectorProductionDeclaration = {
"," <model_keyword:Identifier> <model_identity:StringLiteral>
"," <version_keyword:Identifier> <current_model_version:StringLiteral>
"," <age_keyword:Identifier> <replay_age_seconds:UnsignedInteger>
"," <bytes_keyword:Identifier> <replay_bytes:UnsignedInteger>
"," <backlog_keyword:Identifier> <replay_backlog:UnsignedInteger>
=>? parser::grammar_result(parser::vector_production_declaration(
model_keyword,
model_identity,
version_keyword,
current_model_version,
age_keyword,
replay_age_seconds,
bytes_keyword,
replay_bytes,
backlog_keyword,
replay_backlog,
)),
};
CascadeRelationship: Spanned<CascadeRelationshipDeclaration> = {
<lo:@L> "relationship" <source_entity:Identifier> "." <relationship:Identifier>
"using" <index_entity:Identifier> "." <index:Identifier>
"maximum" <maximum:UnsignedInteger> <hi:@R>
=> parser::spanned(CascadeRelationshipDeclaration {
source_entity,
relationship,
index_entity,
index,
maximum,
}, lo, hi),
};
VectorAnnClause: VectorAnnDeclaration = {
"," <threshold_keyword:Identifier> <row_threshold:UnsignedInteger>
"," <recall_keyword:Identifier> <recall_target_bps:UnsignedInteger>
=>? parser::grammar_result(parser::vector_ann_declaration(
threshold_keyword,
row_threshold,
recall_keyword,
recall_target_bps,
)),
};
IndexOption: Spanned<IndexOption> = {
<lo:@L> "cover" "(" <fields:IdentifierList> ")" <hi:@R>
=> parser::spanned(IndexOption::Cover { fields }, lo, hi),
<lo:@L> "presence" "(" <field:Identifier> ")" <hi:@R>
=> parser::spanned(IndexOption::Presence { field }, lo, hi),
<lo:@L> "text_key" "(" <field:Identifier> "," <profile:TextKeyProfile> ")" <hi:@R>
=> parser::spanned(IndexOption::TextKey { field, profile }, lo, hi),
};
TextKeyProfile: Spanned<TextKeyProfile> = {
<lo:@L> "binary_utf8_v1" <hi:@R>
=> parser::spanned(TextKeyProfile::BinaryUtf8V1, lo, hi),
<lo:@L> "unicode_fold_v1" <hi:@R>
=> parser::spanned(TextKeyProfile::UnicodeFoldV1, lo, hi),
};
// Contextual: the metric names and `staleness_slo` are ordinary identifiers
// everywhere except inside a vector_field declaration, so `field cosine: ...`
// stays valid (the WP-591 hard keywords broke that additively-claimed
// compatibility).
VectorMetric: Spanned<VectorMetricKeyword> = {
<metric:Identifier> =>? parser::grammar_result(parser::vector_metric(metric)),
};
EventDeclaration: EventDeclaration = {
"event" <name:Identifier> "{" <partition_by:EventPartition?>
<policy_anchor:EventPolicyAnchor?> <fields:SpannedTypedField*> "}"
=> EventDeclaration { name, partition_by, policy_anchor, fields },
};
EventPartition: Spanned<Vec<Spanned<String>>> = {
<lo:@L> "partition_by" "(" <fields:IdentifierList> ")" <hi:@R>
=> parser::spanned(fields, lo, hi),
};
EventPolicyAnchor: Spanned<EventPolicyAnchorDeclaration> = {
<lo:@L> "policy_anchor" <current:Identifier> <entity:Identifier>
"(" <fields:EventPolicyAnchorFieldList> ")" <hi:@R> =>? {
parser::grammar_result(parser::event_policy_anchor(current, entity, fields, parser::span(lo, hi)))
},
};
EventPolicyAnchorFieldList: Vec<Spanned<EventPolicyAnchorField>> = {
<head:EventPolicyAnchorField> <tail:("," <EventPolicyAnchorField>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head];
values.extend(tail);
values
},
};
EventPolicyAnchorField: Spanned<EventPolicyAnchorField> = {
<lo:@L> <entity_field:Identifier> ":" <payload_field:Identifier> <hi:@R>
=> parser::spanned(EventPolicyAnchorField { entity_field, payload_field }, lo, hi),
};
EnumDeclaration: EnumDeclaration = {
"enum" <name:Identifier> "{" <variants:IdentifierList> "}"
=> EnumDeclaration { name, variants },
};
AggregateDeclaration: AggregateDeclaration = {
"aggregate" <name:Identifier> "{" <items:AggregateItem*> "}"
=> AggregateDeclaration { name, items },
};
AggregateItem: Spanned<AggregateItem> = {
<lo:@L> "root" <name:Identifier> <hi:@R>
=> parser::spanned(AggregateItem::Root(name), lo, hi),
<lo:@L> "child" <name:Identifier> <hi:@R>
=> parser::spanned(AggregateItem::Child(name), lo, hi),
<lo:@L> "partition_by" <expression:Expression> <hi:@R>
=> parser::spanned(AggregateItem::PartitionBy(expression.into_syntax()), lo, hi),
<lo:@L> "conflict_key" "(" <expressions:ExpressionList> ")" <hi:@R>
=> parser::spanned(AggregateItem::ConflictKey(expressions), lo, hi),
<lo:@L> <invariant:InvariantDeclaration> <hi:@R>
=> parser::spanned(AggregateItem::Invariant(invariant), lo, hi),
};
InvariantDeclaration: InvariantDeclaration = {
"invariant" <name:Identifier> ":" <expression:Expression>
=> InvariantDeclaration { name, expression: expression.into_syntax() },
};
TypedField: TypedField = {
<name:Identifier> ":" <ty:TypeExpression> => TypedField { name, ty },
};
SpannedTypedField: Spanned<TypedField> = {
<lo:@L> <field:TypedField> <hi:@R> => parser::spanned(field, lo, hi),
};
TypedFieldList: Vec<Spanned<TypedField>> = {
<head:SpannedTypedField> <tail:("," <SpannedTypedField>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head];
values.extend(tail);
values
},
};
IdentifierList: Vec<Spanned<String>> = {
<head:Identifier> <tail:("," <Identifier>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head];
values.extend(tail);
values
},
};
TypeExpression: Spanned<TypeExpression> = {
<lo:@L> "bool" <hi:@R> => parser::spanned(TypeExpression::Bool, lo, hi),
<lo:@L> "i64" <hi:@R> => parser::spanned(TypeExpression::I64, lo, hi),
<lo:@L> "u64" <hi:@R> => parser::spanned(TypeExpression::U64, lo, hi),
<lo:@L> "timestamp" <hi:@R> => parser::spanned(TypeExpression::Timestamp, lo, hi),
<lo:@L> "date" <hi:@R> => parser::spanned(TypeExpression::Date, lo, hi),
<lo:@L> "uuid" <hi:@R> => parser::spanned(TypeExpression::Uuid, lo, hi),
<lo:@L> "decimal" "<" <precision:UnsignedInteger> "," <scale:UnsignedInteger> ">" <hi:@R>
=> parser::spanned(TypeExpression::Decimal { precision, scale }, lo, hi),
<lo:@L> "money" "<" <currency:Identifier> ">" <hi:@R>
=>? parser::grammar_result(parser::currency_type(currency, parser::span(lo, hi))),
<lo:@L> "string" "<" <maximum:UnsignedInteger> ">" <hi:@R>
=> parser::spanned(TypeExpression::String { maximum }, lo, hi),
<lo:@L> "bytes" "<" <maximum:UnsignedInteger> ">" <hi:@R>
=> parser::spanned(TypeExpression::Bytes { maximum }, lo, hi),
<lo:@L> "vector" "<" <dimension:UnsignedInteger> ">" <hi:@R>
=> parser::spanned(TypeExpression::Vector { dimension }, lo, hi),
<lo:@L> "optional" "<" <inner:TypeExpression> ">" <hi:@R>
=> parser::spanned(TypeExpression::Optional(Box::new(inner)), lo, hi),
<lo:@L> "list" "<" <element:TypeExpression> "," <bound:ListBound> ">" <hi:@R>
=> parser::spanned(TypeExpression::List {
element: Box::new(element),
minimum: bound.0,
maximum: bound.1,
}, lo, hi),
<lo:@L> <name:Identifier> <hi:@R>
=> parser::spanned(TypeExpression::Named(name), lo, hi),
};
ListBound: (Option<Spanned<String>>, Spanned<String>) = {
<maximum:UnsignedInteger> => (None, maximum),
<lo:@L> <range:"unsigned integer range"> <hi:@R> => {
let (minimum, maximum) = range;
(Some(parser::spanned(minimum, lo, hi)), parser::spanned(maximum, lo, hi))
},
};
CommandDeclaration: CommandDeclaration = {
<kind:ApplicationCommandKind> <name:Identifier> "{"
<inputs:InputDeclaration*>
<service_values:ServiceValueDeclaration*>
<idempotency:IdempotencyClause?>
<bindings:Binding*>
<decisions:CommandDecision*>
<bulk_iteration:BulkIteration?>
<requirements:Requirement*>
<effects:Effect*>
<return_clause:ReturnClause>
"}" => CommandDeclaration {
kind,
name,
inputs,
service_values,
idempotency,
bindings,
decisions,
bulk_iteration,
reconstitution: None,
requirements,
effects,
return_clause,
},
"reimport" "command" <name:Identifier> "{"
<inputs:InputDeclaration+>
<reconstitution:ReconstitutionClause>
<return_clause:ReturnClause>
"}" => CommandDeclaration {
kind: CommandKind::Reimport,
name,
inputs,
service_values: Vec::new(),
idempotency: None,
bindings: Vec::new(),
decisions: Vec::new(),
bulk_iteration: None,
reconstitution: Some(reconstitution),
requirements: Vec::new(),
effects: Vec::new(),
return_clause,
},
};
ApplicationCommandKind: CommandKind = {
"command" => CommandKind::Ordinary,
"bulk" "command" => CommandKind::Bulk,
};
ReconstitutionClause: Spanned<ReconstitutionClause> = {
<lo:@L> "reconstitute" <entity:Identifier> "from" <source:Identifier>
"else" <failure:OutcomeExpression> <hi:@R>
=> parser::spanned(ReconstitutionClause { entity, source, failure }, lo, hi),
};
BulkIteration: Spanned<BulkIteration> = {
<lo:@L> "for" <element:Identifier> "in" <collection:Identifier> "{"
<bindings:Binding*>
<decisions:CommandDecision*>
<requirements:Requirement*>
<effects:Effect*>
"}" <hi:@R> => parser::spanned(BulkIteration {
element,
collection,
bindings,
decisions,
requirements,
effects,
}, lo, hi),
};
CommandDecision: Spanned<CommandDecision> = {
<lo:@L> "observe_or_initialize" <binding:InitializedEntityBinding>
"decide" <subject:Identifier> "{"
<when_arms:DecisionWhenArm+>
<else_action:DecisionElseArm>
"}" <hi:@R>
=> parser::spanned(CommandDecision {
binding,
subject,
when_arms,
else_action,
}, lo, hi),
};
DecisionWhenArm: Spanned<DecisionArm> = {
<lo:@L> "when" <predicate:Expression> "=>" <action:DecisionAction> <hi:@R>
=> parser::spanned(DecisionArm {
predicate: predicate.into_syntax(),
action,
}, lo, hi),
};
DecisionElseArm: Spanned<DecisionAction> = {
"else" "=>" <action:DecisionAction> => action,
};
DecisionAction: Spanned<DecisionAction> = {
<lo:@L> "apply" "{" <bindings:Binding*> <effects:Effect*> "}" <hi:@R>
=> parser::spanned(DecisionAction::Apply { bindings, effects }, lo, hi),
<lo:@L> "no_effect" <hi:@R>
=> parser::spanned(DecisionAction::NoEffect, lo, hi),
<lo:@L> "reject" <outcome:OutcomeExpression> <hi:@R>
=> parser::spanned(DecisionAction::Reject(outcome), lo, hi),
};
ServiceValueDeclaration: Spanned<ServiceValueDeclaration> = {
<lo:@L> "service" <name:Identifier> ":" <kind:ServiceValueKind> <hi:@R>
=> parser::spanned(ServiceValueDeclaration { name, kind }, lo, hi),
};
ServiceValueKind: Spanned<ServiceValueKind> = {
<lo:@L> "uuid_v7" <hi:@R> => parser::spanned(ServiceValueKind::UuidV7, lo, hi),
<lo:@L> "transaction_time" <hi:@R>
=> parser::spanned(ServiceValueKind::TransactionTime, lo, hi),
};
InputDeclaration: Spanned<InputDeclaration> = {
<lo:@L> "input" <field:TypedField>
<aggregate_bytes:("aggregate_bytes" "<=" <UnsignedInteger>)?> <hi:@R>
=> parser::spanned(InputDeclaration { field, aggregate_bytes }, lo, hi),
};
IdempotencyClause: Spanned<IdempotencyClause> = {
<lo:@L> "idempotency_key" <expression:Expression> <hi:@R>
=> parser::spanned(IdempotencyClause { expression: expression.into_syntax() }, lo, hi),
};
Binding: Spanned<Binding> = {
<lo:@L> "mutate" <modifier:Identifier> <entity:Identifier> "." <index:Identifier>
"(" <arguments:ExpressionList> ")" "as" <binding:Identifier> "else" <failure:OutcomeExpression> <hi:@R>
=>? parser::grammar_result(parser::selected_binding(modifier, EntityBinding {
selection_index: Some(index), entity, arguments, binding, failure,
restriction_failure: None, cascade_failure: None,
}, lo, hi)),
<lo:@L> "read" <binding:EntityBinding> <hi:@R>
=> parser::spanned(Binding::Read(binding), lo, hi),
<lo:@L> "mutate" <binding:EntityBinding> <hi:@R>
=> parser::spanned(Binding::Mutate(binding), lo, hi),
<lo:@L> "create" <binding:EntityBinding> <hi:@R>
=> parser::spanned(Binding::Create(binding), lo, hi),
<lo:@L> "init_or_mutate" <binding:InitializedEntityBinding> <hi:@R>
=> parser::spanned(Binding::InitOrMutate(binding), lo, hi),
<lo:@L> "delete" <binding:DeleteEntityBinding> <hi:@R>
=> parser::spanned(Binding::Delete(binding), lo, hi),
};
InitializedEntityBinding: InitializedEntityBinding = {
<entity:Identifier> "(" <arguments:ExpressionList> ")"
"as" <binding:Identifier> "initialize" <initializer:ObjectLiteral>
=> InitializedEntityBinding {
entity,
arguments,
binding,
initializer,
},
};
EntityBinding: EntityBinding = {
<entity:Identifier> "(" <arguments:ExpressionList> ")"
"as" <binding:Identifier> "else" <failure:OutcomeExpression>
=> EntityBinding {
selection_index: None,
entity,
arguments,
binding,
failure,
restriction_failure: None,
cascade_failure: None,
},
};
DeleteEntityBinding: EntityBinding = {
<entity:Identifier> "(" <arguments:ExpressionList> ")"
"as" <binding:Identifier> "else" <failure:OutcomeExpression>
<restriction_failure:("restrict" <OutcomeExpression>)?>
<cascade_failure:("cascade" <OutcomeExpression>)?>
=> EntityBinding {
selection_index: None,
entity,
arguments,
binding,
failure,
restriction_failure,
cascade_failure,
},
};
Requirement: Spanned<Requirement> = {
<lo:@L> "require" <name:Identifier> ":" <condition:Expression>
"else" <rejection:OutcomeExpression> <hi:@R>
=> parser::spanned(Requirement {
name,
condition: condition.into_syntax(),
rejection,
}, lo, hi),
};
Effect: Spanned<Effect> = {
<lo:@L> "set" <target:Path> "=" <value:Expression> <checked_by:("checked_by" <Identifier>)?> <reveals:RevealAnnotation*> <hi:@R>
=> parser::spanned(Effect::Set(SetEffect {
spelling: WriteSpelling::Set,
checked_by,
target,
value: value.into_syntax(),
reveals,
}), lo, hi),
<lo:@L> "overwrite" <target:Path> "=" <value:Expression> <checked_by:("checked_by" <Identifier>)?> <reveals:RevealAnnotation*> <hi:@R>
=> parser::spanned(Effect::Set(SetEffect {
spelling: WriteSpelling::Overwrite,
checked_by,
target,
value: value.into_syntax(),
reveals,
}), lo, hi),
<lo:@L> "embed" <target:Path> "=" <value:Expression>
"from" "(" <model_identity:Expression> "," <model_version:Expression> ")" <hi:@R>
=> parser::spanned(Effect::Embed(EmbeddingEffect {
target,
value: value.into_syntax(),
model_identity: model_identity.into_syntax(),
model_version: model_version.into_syntax(),
}), lo, hi),
<lo:@L> "emit" <event:Identifier> <payload:ObjectLiteral> <hi:@R>
=> parser::spanned(Effect::Emit(EmitEffect { event, payload }), lo, hi),
<lo:@L> "transition" <transition:Identifier> "on" <binding:Identifier>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"illegal" <illegal:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowTransition(WorkflowTransitionEffect {
transition,
binding,
expected_revision: expected_revision.into_syntax(),
stale,
illegal,
}), lo, hi),
<lo:@L> "lease" "claim" <lease:Identifier> "on" <binding:Identifier>
"owner" <owner:Expression>
"duration_seconds" <duration_seconds:Expression>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"unavailable" <unavailable:OutcomeExpression>
"invalid" <invalid:OutcomeExpression>
"exhausted" <exhausted:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowLease(Box::new(WorkflowLeaseEffect {
lease,
binding,
operation: WorkflowLeaseOperation::Claim {
owner: owner.into_syntax(),
duration_seconds: duration_seconds.into_syntax(),
expected_revision: expected_revision.into_syntax(),
stale,
unavailable,
invalid,
exhausted,
},
})), lo, hi),
<lo:@L> "lease" "renew" <lease:Identifier> "on" <binding:Identifier>
"owner" <owner:Expression>
"fencing_token" <fencing_token:Expression>
"duration_seconds" <duration_seconds:Expression>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"invalid" <invalid:OutcomeExpression>
"expired" <expired:OutcomeExpression>
"exhausted" <exhausted:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowLease(Box::new(WorkflowLeaseEffect {
lease,
binding,
operation: WorkflowLeaseOperation::Renew {
owner: owner.into_syntax(),
fencing_token: fencing_token.into_syntax(),
duration_seconds: duration_seconds.into_syntax(),
expected_revision: expected_revision.into_syntax(),
stale,
invalid,
expired,
exhausted,
},
})), lo, hi),
<lo:@L> "lease" "release" <lease:Identifier> "on" <binding:Identifier>
"owner" <owner:Expression>
"fencing_token" <fencing_token:Expression>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"invalid" <invalid:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowLease(Box::new(WorkflowLeaseEffect {
lease,
binding,
operation: WorkflowLeaseOperation::Release {
owner: owner.into_syntax(),
fencing_token: fencing_token.into_syntax(),
expected_revision: expected_revision.into_syntax(),
stale,
invalid,
},
})), lo, hi),
<lo:@L> "lease" "expire" <lease:Identifier> "on" <binding:Identifier>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"active" <active:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowLease(Box::new(WorkflowLeaseEffect {
lease,
binding,
operation: WorkflowLeaseOperation::Expire {
expected_revision: expected_revision.into_syntax(),
stale,
active,
},
})), lo, hi),
<lo:@L> "lease" "fence" <lease:Identifier> "on" <binding:Identifier>
"owner" <owner:Expression>
"fencing_token" <fencing_token:Expression>
"revision" <expected_revision:Expression>
"stale" <stale:OutcomeExpression>
"invalid" <invalid:OutcomeExpression>
"expired" <expired:OutcomeExpression> <hi:@R>
=> parser::spanned(Effect::WorkflowLease(Box::new(WorkflowLeaseEffect {
lease,
binding,
operation: WorkflowLeaseOperation::Fence {
owner: owner.into_syntax(),
fencing_token: fencing_token.into_syntax(),
expected_revision: expected_revision.into_syntax(),
stale,
invalid,
expired,
},
})), lo, hi),
};
ReturnClause: Spanned<ReturnClause> = {
<lo:@L> "return" <outcome:OutcomeExpression> <hi:@R>
=> parser::spanned(ReturnClause { outcome }, lo, hi),
};
OutcomeExpression: Spanned<OutcomeExpression> = {
<lo:@L> <name:Identifier> <payload:ObjectLiteral> <hi:@R>
=> parser::spanned(OutcomeExpression { name, payload }, lo, hi),
};
ObjectLiteral: Spanned<ObjectLiteral> = {
<lo:@L> "{" <fields:ObjectFieldList?> "}" <hi:@R>
=> parser::spanned(ObjectLiteral { fields: fields.unwrap_or_default() }, lo, hi),
};
ObjectFieldList: Vec<Spanned<ObjectField>> = {
<head:ObjectField> <tail:("," <ObjectField>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head];
values.extend(tail);
values
},
};
ObjectField: Spanned<ObjectField> = {
<lo:@L> <name:Identifier> ":" <value:Expression> <reveals:RevealAnnotation*> <hi:@R>
=> parser::spanned(ObjectField { name, value: value.into_syntax(), reveals }, lo, hi),
};
RevealAnnotation: Spanned<Path> = {
"reveals" <source:Path> => source,
};
ProjectionDeclaration: ProjectionDeclaration = {
"projection" <name:Identifier> "{"
"source" "event" <source_event:Identifier>
<filter:WhereClause?>
"key" "(" <key:ProjectionKeyList> ")"
<measures:Measure+>
<frontier:FrontierClause>
"}" => ProjectionDeclaration {
name,
source_event,
filter,
key,
measures,
frontier,
},
};
ColumnarProjectionDeclaration: ColumnarProjectionDeclaration = {
"columnar_projection" <name:Identifier> "{"
"source" "entity" <source_entity:Identifier>
<fields_keyword:Identifier> "(" <fields:IdentifierList> ")"
"}" =>? parser::grammar_result(parser::columnar_projection_declaration(
name,
source_entity,
fields_keyword,
fields,
)),
};
ProjectionKeyList: Vec<Spanned<Expression>> = {
<head:ProjectionKeyExpression> <tail:("," <ProjectionKeyExpression>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head.into_syntax()];
values.extend(tail.into_iter().map(ParsedExpression::into_syntax));
values
},
};
ProjectionKeyExpression: ParsedExpression = {
<lo:@L> <callee:Identifier> "(" <operand:Expression> ")" <hi:@R>
=>? parser::grammar_result(parser::temporal_bucket_expression(callee, operand, parser::span(lo, hi))),
Expression,
};
WhereClause: Spanned<Expression> = {
"where" <expression:Expression> => expression.into_syntax(),
};
Measure: Spanned<Measure> = {
<lo:@L> "measure" <name:Identifier> "=" <aggregation:Aggregation> <hi:@R>
=> parser::spanned(Measure { name, aggregation }, lo, hi),
};
Aggregation: Spanned<Aggregation> = {
<lo:@L> "count" "(" ")" <hi:@R>
=> parser::spanned(Aggregation::Count, lo, hi),
<lo:@L> "sum" "(" <expression:Expression> ")" <hi:@R>
=> parser::spanned(Aggregation::Sum(expression.into_syntax()), lo, hi),
<lo:@L> <callee:Identifier> "(" <expression:Expression> ")" <hi:@R>
=>? parser::grammar_result(parser::named_aggregation(callee, expression, lo, hi)),
};
FrontierClause: Spanned<Frontier> = {
<lo:@L> "frontier" "transactionally_ordered" <hi:@R>
=> parser::spanned(Frontier::TransactionallyOrdered, lo, hi),
};
ExpressionList: Vec<Spanned<Expression>> = {
<head:Expression> <tail:("," <Expression>)*> <trailing:Comma?> => {
let _ = trailing;
let mut values = vec![head.into_syntax()];
values.extend(tail.into_iter().map(ParsedExpression::into_syntax));
values
},
};
Expression: ParsedExpression = OrExpression;
OrExpression: ParsedExpression = {
<left:AndExpression> <rest:(<OrOperator> <AndExpression>)*>
=>? parser::grammar_result(parser::binary_chain(left, rest)),
};
AndExpression: ParsedExpression = {
<left:ComparisonExpression> <rest:(<AndOperator> <ComparisonExpression>)*>
=>? parser::grammar_result(parser::binary_chain(left, rest)),
};
ComparisonExpression: ParsedExpression = {
<left:AdditiveExpression> <rest:(<ComparisonOperator> <AdditiveExpression>)*>
=>? parser::grammar_result(parser::binary_chain(left, rest)),
};
AdditiveExpression: ParsedExpression = {
<left:MultiplicativeExpression> <rest:(<AdditiveOperator> <MultiplicativeExpression>)*>
=>? parser::grammar_result(parser::binary_chain(left, rest)),
};
MultiplicativeExpression: ParsedExpression = {
<left:UnaryExpression> <rest:(<MultiplicativeOperator> <UnaryExpression>)*>
=>? parser::grammar_result(parser::binary_chain(left, rest)),
};
UnaryExpression: ParsedExpression = {
<lo:@L> <operator:UnaryOperator> <operand:UnaryExpression> <hi:@R>
=>? parser::grammar_result(parser::unary_expression(operator, operand, parser::span(lo, hi))),
PrimaryExpression,
};
PrimaryExpression: ParsedExpression = {
<literal:Literal> => parser::literal_expression(literal),
<path:Path> => parser::path_expression(path),
<lo:@L> "(" <expression:Expression> ")" <hi:@R>
=>? parser::grammar_result(parser::parenthesized_expression(expression, parser::span(lo, hi))),
};
Literal: Spanned<Literal> = {
<lo:@L> "true" <hi:@R> => parser::spanned(Literal::Bool(true), lo, hi),
<lo:@L> "false" <hi:@R> => parser::spanned(Literal::Bool(false), lo, hi),
<lo:@L> "null" <hi:@R> => parser::spanned(Literal::Null, lo, hi),
<lo:@L> <value:"unsigned integer literal"> <hi:@R>
=> parser::spanned(Literal::UInt(value), lo, hi),
<lo:@L> <value:"fixed decimal literal"> <hi:@R>
=> parser::spanned(Literal::FixedDecimal(value), lo, hi),
<lo:@L> <value:"string literal"> <hi:@R>
=> parser::spanned(Literal::String(value), lo, hi),
};
Path: Spanned<Path> = {
<lo:@L> <head:Identifier> <tail:("." <PathSegment>)*> <hi:@R> => {
let mut segments = vec![head];
segments.extend(tail);
parser::spanned(Path { segments }, lo, hi)
},
};
PathSegment: Spanned<String> = {
Identifier,
<lo:@L> "date" <hi:@R> => parser::spanned("date".to_owned(), lo, hi),
};
UnaryOperator: Spanned<UnaryOperator> = {
<lo:@L> "!" <hi:@R> => parser::spanned(UnaryOperator::Not, lo, hi),
<lo:@L> "-" <hi:@R> => parser::spanned(UnaryOperator::Negate, lo, hi),
};
MultiplicativeOperator: Spanned<BinaryOperator> = {
<lo:@L> "*" <hi:@R> => parser::spanned(BinaryOperator::Multiply, lo, hi),
<lo:@L> "/" <hi:@R> => parser::spanned(BinaryOperator::Divide, lo, hi),
};
AdditiveOperator: Spanned<BinaryOperator> = {
<lo:@L> "+" <hi:@R> => parser::spanned(BinaryOperator::Add, lo, hi),
<lo:@L> "-" <hi:@R> => parser::spanned(BinaryOperator::Subtract, lo, hi),
};
ComparisonOperator: Spanned<BinaryOperator> = {
<lo:@L> "==" <hi:@R> => parser::spanned(BinaryOperator::Equal, lo, hi),
<lo:@L> "!=" <hi:@R> => parser::spanned(BinaryOperator::NotEqual, lo, hi),
<lo:@L> "<" <hi:@R> => parser::spanned(BinaryOperator::Less, lo, hi),
<lo:@L> "<=" <hi:@R> => parser::spanned(BinaryOperator::LessEqual, lo, hi),
<lo:@L> ">" <hi:@R> => parser::spanned(BinaryOperator::Greater, lo, hi),
<lo:@L> ">=" <hi:@R> => parser::spanned(BinaryOperator::GreaterEqual, lo, hi),
};
AndOperator: Spanned<BinaryOperator> = {
<lo:@L> "&&" <hi:@R> => parser::spanned(BinaryOperator::And, lo, hi),
};
OrOperator: Spanned<BinaryOperator> = {
<lo:@L> "||" <hi:@R> => parser::spanned(BinaryOperator::Or, lo, hi),
};
Identifier: Spanned<String> = {
<lo:@L> <value:"identifier"> <hi:@R> => parser::spanned(value, lo, hi),
<lo:@L> "cover" <hi:@R> => parser::spanned("cover".to_owned(), lo, hi),
<lo:@L> "presence" <hi:@R> => parser::spanned("presence".to_owned(), lo, hi),
<lo:@L> "text_key" <hi:@R> => parser::spanned("text_key".to_owned(), lo, hi),
<lo:@L> "binary_utf8_v1" <hi:@R>
=> parser::spanned("binary_utf8_v1".to_owned(), lo, hi),
<lo:@L> "unicode_fold_v1" <hi:@R>
=> parser::spanned("unicode_fold_v1".to_owned(), lo, hi),
<lo:@L> "cascade" <hi:@R> => parser::spanned("cascade".to_owned(), lo, hi),
<lo:@L> "relationship" <hi:@R>
=> parser::spanned("relationship".to_owned(), lo, hi),
<lo:@L> "using" <hi:@R> => parser::spanned("using".to_owned(), lo, hi),
<lo:@L> "maximum" <hi:@R> => parser::spanned("maximum".to_owned(), lo, hi),
<lo:@L> "idempotency_key" <hi:@R>
=> parser::spanned("idempotency_key".to_owned(), lo, hi),
<lo:@L> "workflow" <hi:@R> => parser::spanned("workflow".to_owned(), lo, hi),
<lo:@L> "state" <hi:@R> => parser::spanned("state".to_owned(), lo, hi),
<lo:@L> "initial" <hi:@R> => parser::spanned("initial".to_owned(), lo, hi),
<lo:@L> "transition" <hi:@R> => parser::spanned("transition".to_owned(), lo, hi),
<lo:@L> "from" <hi:@R> => parser::spanned("from".to_owned(), lo, hi),
<lo:@L> "to" <hi:@R> => parser::spanned("to".to_owned(), lo, hi),
<lo:@L> "lease" <hi:@R> => parser::spanned("lease".to_owned(), lo, hi),
<lo:@L> "claim" <hi:@R> => parser::spanned("claim".to_owned(), lo, hi),
<lo:@L> "renew" <hi:@R> => parser::spanned("renew".to_owned(), lo, hi),
<lo:@L> "release" <hi:@R> => parser::spanned("release".to_owned(), lo, hi),
<lo:@L> "expire" <hi:@R> => parser::spanned("expire".to_owned(), lo, hi),
<lo:@L> "fence" <hi:@R> => parser::spanned("fence".to_owned(), lo, hi),
<lo:@L> "owner" <hi:@R> => parser::spanned("owner".to_owned(), lo, hi),
<lo:@L> "expires_at" <hi:@R> => parser::spanned("expires_at".to_owned(), lo, hi),
<lo:@L> "fencing_token" <hi:@R> => parser::spanned("fencing_token".to_owned(), lo, hi),
<lo:@L> "attempts" <hi:@R> => parser::spanned("attempts".to_owned(), lo, hi),
<lo:@L> "duration_seconds" <hi:@R>
=> parser::spanned("duration_seconds".to_owned(), lo, hi),
<lo:@L> "service" <hi:@R> => parser::spanned("service".to_owned(), lo, hi),
<lo:@L> "uuid_v7" <hi:@R> => parser::spanned("uuid_v7".to_owned(), lo, hi),
<lo:@L> "transaction_time" <hi:@R>
=> parser::spanned("transaction_time".to_owned(), lo, hi),
<lo:@L> "on" <hi:@R> => parser::spanned("on".to_owned(), lo, hi),
<lo:@L> "revision" <hi:@R> => parser::spanned("revision".to_owned(), lo, hi),
<lo:@L> "stale" <hi:@R> => parser::spanned("stale".to_owned(), lo, hi),
<lo:@L> "illegal" <hi:@R> => parser::spanned("illegal".to_owned(), lo, hi),
<lo:@L> "unavailable" <hi:@R> => parser::spanned("unavailable".to_owned(), lo, hi),
<lo:@L> "invalid" <hi:@R> => parser::spanned("invalid".to_owned(), lo, hi),
<lo:@L> "exhausted" <hi:@R> => parser::spanned("exhausted".to_owned(), lo, hi),
<lo:@L> "expired" <hi:@R> => parser::spanned("expired".to_owned(), lo, hi),
<lo:@L> "active" <hi:@R> => parser::spanned("active".to_owned(), lo, hi),
<lo:@L> "principal" <hi:@R> => parser::spanned("principal".to_owned(), lo, hi),
<lo:@L> "fact" <hi:@R> => parser::spanned("fact".to_owned(), lo, hi),
<lo:@L> "row" <hi:@R> => parser::spanned("row".to_owned(), lo, hi),
<lo:@L> "policy" <hi:@R> => parser::spanned("policy".to_owned(), lo, hi),
<lo:@L> "allow" <hi:@R> => parser::spanned("allow".to_owned(), lo, hi),
<lo:@L> "when" <hi:@R> => parser::spanned("when".to_owned(), lo, hi),
<lo:@L> "update" <hi:@R> => parser::spanned("update".to_owned(), lo, hi),
<lo:@L> "delete" <hi:@R> => parser::spanned("delete".to_owned(), lo, hi),
<lo:@L> "in" <hi:@R> => parser::spanned("in".to_owned(), lo, hi),
<lo:@L> "is" <hi:@R> => parser::spanned("is".to_owned(), lo, hi),
<lo:@L> "not" <hi:@R> => parser::spanned("not".to_owned(), lo, hi),
<lo:@L> "reveals" <hi:@R> => parser::spanned("reveals".to_owned(), lo, hi),
};
UnsignedInteger: Spanned<String> = {
<lo:@L> <value:"unsigned integer literal"> <hi:@R>
=> parser::spanned(value, lo, hi),
};
StringLiteral: Spanned<String> = {
<lo:@L> <value:"string literal"> <hi:@R>
=> parser::spanned(value, lo, hi),
};
Comma: () = { "," => () };
extern {
type Location = usize;
type Error = SyntaxDiagnostic;
enum Token {
"contract" => Token::Contract,
"version" => Token::Version,
"entity" => Token::Entity,
"key" => Token::Key,
"field" => Token::Field,
"invariant" => Token::Invariant,
"index" => Token::Index,
"cover" => Token::Cover,
"presence" => Token::Presence,
"text_key" => Token::TextKey,
"binary_utf8_v1" => Token::BinaryUtf8V1,
"unicode_fold_v1" => Token::UnicodeFoldV1,
"unique" => Token::Unique,
"reference" => Token::Reference,
"vector_field" => Token::VectorField,
"text_index" => Token::TextIndex,
"pattern_index" => Token::LongPattern,
"delete_policy" => Token::DeletePolicy,
"no_inbound" => Token::NoInbound,
"restrict" => Token::Restrict,
"cascade" => Token::Cascade,
"relationship" => Token::Relationship,
"using" => Token::Using,
"maximum" => Token::Maximum,
"event" => Token::Event,
"enum" => Token::Enum,
"aggregate" => Token::Aggregate,
"root" => Token::Root,
"child" => Token::Child,
"partition_by" => Token::PartitionBy,
"policy_anchor" => Token::PolicyAnchor,
"conflict_key" => Token::ConflictKey,
"projection" => Token::Projection,
"columnar_projection" => Token::ColumnarProjection,
"source" => Token::Source,
"where" => Token::Where,
"measure" => Token::Measure,
"count" => Token::Count,
"sum" => Token::Sum,
"frontier" => Token::Frontier,
"transactionally_ordered" => Token::TransactionallyOrdered,
"command" => Token::Command,
"bulk" => Token::Bulk,
"reimport" => Token::Reimport,
"reconstitute" => Token::Reconstitute,
"for" => Token::For,
"workflow" => Token::Workflow,
"state" => Token::State,
"initial" => Token::Initial,
"transition" => Token::Transition,
"from" => Token::From,
"to" => Token::To,
"lease" => Token::Lease,
"claim" => Token::Claim,
"renew" => Token::Renew,
"release" => Token::Release,
"expire" => Token::Expire,
"fence" => Token::Fence,
"owner" => Token::Owner,
"expires_at" => Token::ExpiresAt,
"fencing_token" => Token::FencingToken,
"attempts" => Token::Attempts,
"duration_seconds" => Token::DurationSeconds,
"service" => Token::Service,
"uuid_v7" => Token::UuidV7,
"transaction_time" => Token::TransactionTime,
"on" => Token::On,
"revision" => Token::Revision,
"stale" => Token::Stale,
"illegal" => Token::Illegal,
"unavailable" => Token::Unavailable,
"invalid" => Token::Invalid,
"exhausted" => Token::Exhausted,
"expired" => Token::Expired,
"active" => Token::Active,
"input" => Token::Input,
"aggregate_bytes" => Token::AggregateBytes,
"idempotency_key" => Token::IdempotencyKey,
"read" => Token::Read,
"mutate" => Token::Mutate,
"create" => Token::Create,
"init_or_mutate" => Token::InitOrMutate,
"observe_or_initialize" => Token::ObserveOrInitialize,
"decide" => Token::Decide,
"apply" => Token::Apply,
"no_effect" => Token::NoEffect,
"reject" => Token::Reject,
"initialize" => Token::Initialize,
"as" => Token::As,
"else" => Token::Else,
"require" => Token::Require,
"set" => Token::Set,
"overwrite" => Token::Overwrite,
"checked_by" => Token::CheckedBy,
"embed" => Token::Embed,
"emit" => Token::Emit,
"return" => Token::Return,
"reveals" => Token::Reveals,
"principal" => Token::Principal,
"fact" => Token::Fact,
"row" => Token::Row,
"policy" => Token::Policy,
"allow" => Token::Allow,
"when" => Token::When,
"update" => Token::Update,
"delete" => Token::Delete,
"in" => Token::In,
"is" => Token::Is,
"not" => Token::Not,
"exists" => Token::Exists,
"bool" => Token::Bool,
"i64" => Token::I64,
"u64" => Token::U64,
"timestamp" => Token::Timestamp,
"date" => Token::Date,
"uuid" => Token::Uuid,
"decimal" => Token::Decimal,
"money" => Token::Money,
"string" => Token::String,
"bytes" => Token::Bytes,
"vector" => Token::Vector,
"optional" => Token::Optional,
"list" => Token::List,
"true" => Token::True,
"false" => Token::False,
"null" => Token::Null,
"{" => Token::LeftBrace,
"}" => Token::RightBrace,
"(" => Token::LeftParen,
")" => Token::RightParen,
"<=" => Token::LessEqual,
">=" => Token::GreaterEqual,
"->" => Token::Arrow,
"=>" => Token::FatArrow,
"==" => Token::EqualEqual,
"!=" => Token::BangEqual,
"&&" => Token::AndAnd,
"||" => Token::OrOr,
"<" => Token::Less,
">" => Token::Greater,
"," => Token::Comma,
":" => Token::Colon,
"." => Token::Dot,
"=" => Token::Equal,
"!" => Token::Bang,
"-" => Token::Minus,
"*" => Token::Star,
"/" => Token::Slash,
"+" => Token::Plus,
"fixed decimal literal" => Token::FixedDecimalLiteral(<String>),
"unsigned integer literal" => Token::UIntLiteral(<String>),
"unsigned integer range" => Token::UIntRange(<(String, String)>),
"string literal" => Token::StringLiteral(<String>),
"identifier" => Token::Identifier(<String>),
}
}