pub trait ParserContext: Sized {
Show 18 methods
// Required methods
fn new_context() -> Self;
fn new_fragment(&self) -> Self;
fn push_literal<T: 'static + Clone>(&mut self, value: T, span: Span);
fn apply_op(
&mut self,
op_lookup: &OpLookup,
name: &str,
arity: usize,
start: Span,
end: Span,
) -> Result<()>;
fn apply_member(
&mut self,
lookup: &OpLookup,
name: &str,
name_span: ExprSpan,
explicit_args: Option<usize>,
start: Span,
end: Span,
) -> Result<()>;
fn make_record(
&mut self,
lookup: &OpLookup,
name: &str,
name_span: ExprSpan,
fields: Vec<(String, ExprSpan)>,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>;
fn apply_logical(
&mut self,
name: &str,
rhs: Self,
start: Span,
end: Span,
) -> Result<()>;
fn join2(
&mut self,
then_fragment: Self,
else_fragment: Option<Self>,
start: Span,
end: Span,
) -> Result<()>;
fn make_tuple(
&mut self,
n: usize,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>;
fn make_array(
&mut self,
n: usize,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>;
fn make_annotated_array(
&mut self,
n: usize,
ambient_start: usize,
annotation: AnnotatedArray<'_>,
start: Span,
end: Span,
) -> Result<()>;
fn peek_tuple_arity(&self) -> Option<usize>;
fn tuple_index(
&mut self,
index: usize,
start: Span,
end: Span,
) -> Result<()>;
fn current_stack_offset(&self) -> usize;
fn apply_cast(
&mut self,
op_lookup: &OpLookup,
type_name: &str,
start: Span,
end: Span,
) -> Result<()>;
// Provided methods
fn resolves_closure_types() -> bool { ... }
fn push_closure(
&mut self,
param_types: Vec<ValueType>,
params: Vec<ClosureParam>,
body: Self,
span: Span,
) -> Result<()> { ... }
fn output_type_id(&self) -> Option<TypeId> { ... }
}Expand description
The pluggable target a grammar production emits into.
Each method mirrors one operation the grammar in lib.rs needs. Implementations decide what
“emitting” means: DynSegmentContext executes immediately into a stack machine; a future
AST-building context would instead record a tree node.
Required Methods§
Sourcefn new_context() -> Self
fn new_context() -> Self
Creates a fresh, empty context with no operations recorded yet.
Sourcefn new_fragment(&self) -> Self
fn new_fragment(&self) -> Self
Creates an empty fragment for building an alternate branch (one side of a
short-circuiting ||/&&, or an if/else branch), independent of self.
- Precondition:
selfmatches whatever precondition the implementation’s equivalent ofDynSegment::new_fragmentrequires (forDynSegmentContext, a condition value already present).
Sourcefn push_literal<T: 'static + Clone>(&mut self, value: T, span: Span)
fn push_literal<T: 'static + Clone>(&mut self, value: T, span: Span)
Pushes a literal value with the source span of the token it came from.
Sourcefn apply_op(
&mut self,
op_lookup: &OpLookup,
name: &str,
arity: usize,
start: Span,
end: Span,
) -> Result<()>
fn apply_op( &mut self, op_lookup: &OpLookup, name: &str, arity: usize, start: Span, end: Span, ) -> Result<()>
Applies a named operator or zero-arity identifier lookup, using op_lookup to resolve it
against whatever this context currently holds.
§Errors
Returns Err if op_lookup cannot resolve name for arity operands.
Sourcefn apply_member(
&mut self,
lookup: &OpLookup,
name: &str,
name_span: ExprSpan,
explicit_args: Option<usize>,
start: Span,
end: Span,
) -> Result<()>
fn apply_member( &mut self, lookup: &OpLookup, name: &str, name_span: ExprSpan, explicit_args: Option<usize>, start: Span, end: Span, ) -> Result<()>
Applies a direct named operation to the receiver and explicit arguments in source order.
None preserves .name; Some(0) preserves .name(). Both consume one receiver.
name_span identifies the member label for diagnostics; start/end cover the expression.
- Precondition: the receiver and
explicit_args.unwrap_or(0)arguments are emitted. - Complexity: O(n) for n operands, plus operation lookup in runtime contexts.
§Errors
Returns an error if a runtime context cannot resolve the operation.
§Examples
use cel_parser::{AstContext, ExprSpan, OpLookup};
use cel_parser::parser_context::ParserContext;
use proc_macro2::Span;
let mut context = AstContext::new_context();
let span = Span::call_site();
context.push_literal(1i32, span);
context.apply_member(&OpLookup::new(), "custom", ExprSpan { start: span, end: span },
None, span, span).unwrap();Sourcefn make_record(
&mut self,
lookup: &OpLookup,
name: &str,
name_span: ExprSpan,
fields: Vec<(String, ExprSpan)>,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>
fn make_record( &mut self, lookup: &OpLookup, name: &str, name_span: ExprSpan, fields: Vec<(String, ExprSpan)>, ambient_start: usize, start: Span, end: Span, ) -> Result<()>
Constructs a record from named fields emitted exactly once in source order.
- Precondition: one value per field follows
ambient_startin this context. - Complexity: O(f² + f * d + r) for f fields, descriptor depth d and r schemas.
§Errors
Runtime contexts reject unknown schemas, invalid field sets, mismatched types, or constructor emitter failures; syntax-only contexts preserve unresolved names.
§Examples
Sourcefn apply_logical(
&mut self,
name: &str,
rhs: Self,
start: Span,
end: Span,
) -> Result<()>
fn apply_logical( &mut self, name: &str, rhs: Self, start: Span, end: Span, ) -> Result<()>
Applies a short-circuiting logical operator ("||" or "&&"), consuming a leading
condition value already present on self and folding in rhs, the already-parsed
right-hand-side fragment.
- Precondition:
nameis"||"or"&&", andrhsproduces exactly one value.
§Errors
Implementations that validate operand types during parsing (e.g. DynSegmentContext)
return Err if the leading condition value isn’t a bool. Implementations that defer
type validation to a later phase (e.g. crate::ast::AstContext) never return Err
here.
Sourcefn join2(
&mut self,
then_fragment: Self,
else_fragment: Option<Self>,
start: Span,
end: Span,
) -> Result<()>
fn join2( &mut self, then_fragment: Self, else_fragment: Option<Self>, start: Span, end: Span, ) -> Result<()>
Joins a previously-built fragment into self, consuming a leading condition value already
present on self. then_fragment’s contribution is used when the condition is true;
else_fragment’s when false, or None if the source had no else/else if at all.
start/end cover the whole if/else construct.
- Precondition: neither fragment takes arguments, and each produces exactly one value.
§Errors
Implementations that validate operand types during parsing (e.g. DynSegmentContext)
return Err if the leading condition value isn’t a bool or if the fragments’ produced
types don’t match — including when else_fragment is None, which such implementations
treat as an implicit () fragment (so a non-() then-branch with no else is still an
error). Implementations that defer type validation to a later phase (e.g.
crate::ast::AstContext) never return Err here, and record whether else_fragment was
None directly (see crate::Expr::If) instead of synthesizing anything.
Sourcefn make_tuple(
&mut self,
n: usize,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>
fn make_tuple( &mut self, n: usize, ambient_start: usize, start: Span, end: Span, ) -> Result<()>
Combines the last n emitted values into a single tuple value. start/end cover the
whole (...) construct.
§Errors
Returns an error if the tuple’s frame or canonical layout cannot be represented.
Sourcefn make_array(
&mut self,
n: usize,
ambient_start: usize,
start: Span,
end: Span,
) -> Result<()>
fn make_array( &mut self, n: usize, ambient_start: usize, start: Span, end: Span, ) -> Result<()>
Combines the last n emitted values into a single homogeneous array value. start/end
cover the whole [...] construct, and ambient_start is the stack offset the first
element was emitted at (as reported by Self::current_stack_offset before parsing it).
- Precondition:
n >= 1and exactlynvalues have been emitted sinceambient_start.
§Errors
Implementations that validate operand types during parsing (e.g. DynSegmentContext)
return Err if the elements’ complete recursive runtime shapes differ, or if the array’s storage
layout cannot be represented. Implementations that defer type validation to a later phase
(e.g. crate::ast::AstContext) never return Err here.
Sourcefn make_annotated_array(
&mut self,
n: usize,
ambient_start: usize,
annotation: AnnotatedArray<'_>,
start: Span,
end: Span,
) -> Result<()>
fn make_annotated_array( &mut self, n: usize, ambient_start: usize, annotation: AnnotatedArray<'_>, start: Span, end: Span, ) -> Result<()>
Combines the last n emitted values into a single array value, honoring annotation’s
optional type ascription.
This is the method the grammar actually calls for every array literal; Self::make_array
is the unannotated special case an implementation may delegate to. There is deliberately
no default implementation: an annotation changes what the literal means ([]: [Celsius]
is an empty array of a specific type), so an implementation that silently dropped it
would misreport the literal’s type rather than fail to compile.
An implementation that needs runtime array metadata immediately (e.g.
DynSegmentContext) calls AnnotatedArray::resolve_element_type; one that defers
semantic checking (e.g. crate::ast::AstContext) records the syntax returned by
AnnotatedArray::into_parts.
- Precondition: exactly
nvalues have been emitted sinceambient_start.
§Errors
Returns Err under Self::make_array’s conditions, and additionally — for an
implementation that resolves the annotation here — if the annotation names an unknown
type, does not name a complete array type, or disagrees with the collected elements.
Sourcefn peek_tuple_arity(&self) -> Option<usize>
fn peek_tuple_arity(&self) -> Option<usize>
Returns the arity of the tuple currently on top, or None if the top value isn’t a
tuple.
Sourcefn tuple_index(&mut self, index: usize, start: Span, end: Span) -> Result<()>
fn tuple_index(&mut self, index: usize, start: Span, end: Span) -> Result<()>
Replaces the tuple on top with its index-th element. start/end cover the base
expression through the index token.
- Precondition:
peek_tuple_arity()returnsSome(arity)withindex < arity.
§Errors
Returns an error if the selected field’s transfer frame cannot be represented.
Sourcefn current_stack_offset(&self) -> usize
fn current_stack_offset(&self) -> usize
Returns the current stack offset, used to compute tuple layouts.
Sourcefn apply_cast(
&mut self,
op_lookup: &OpLookup,
type_name: &str,
start: Span,
end: Span,
) -> Result<()>
fn apply_cast( &mut self, op_lookup: &OpLookup, type_name: &str, start: Span, end: Span, ) -> Result<()>
Applies a cast (expr as Type), consuming the operand already present on self
and replacing it with the converted value. type_name is the target type’s bare
identifier text (e.g. "i32", "bool", "String"), unresolved by the grammar itself.
§Errors
Implementations that validate operand types during parsing (e.g. DynSegmentContext)
return Err if type_name isn’t a recognized cast-target type, or if no conversion
from the operand’s current type to it is registered. Implementations that defer type
validation to a later phase (e.g. crate::ast::AstContext) never return Err here.
Provided Methods§
Sourcefn resolves_closure_types() -> bool
fn resolves_closure_types() -> bool
Returns whether closure annotations must resolve while parsing rather than remain syntax.
§Examples
use cel_parser::{AstContext, parser_context::ParserContext};
assert!(!AstContext::resolves_closure_types());Sourcefn push_closure(
&mut self,
param_types: Vec<ValueType>,
params: Vec<ClosureParam>,
body: Self,
span: Span,
) -> Result<()>
fn push_closure( &mut self, param_types: Vec<ValueType>, params: Vec<ClosureParam>, body: Self, span: Span, ) -> Result<()>
Packages a fully-parsed, independent nested context — the body of a closure literal — as
a value pushed onto self, given the closure’s declared parameter types in two parallel
forms: param_types (each parameter’s complete runtime shape, in order) for an implementation
that executes, and params (each parameter’s name, span, and unresolved type expression)
for one that builds an AST instead. An implementation uses whichever it needs and ignores
the other.
The default implementation reports closures as unsupported, so a ParserContext
implementation that has no use for them needs no changes to keep compiling.
- Precondition:
bodywas built viaSelf::new_context()and its own argument-binding mechanism, in the same styleSelf::new_context’s other consumers already use.
§Errors
Returns Err if this ParserContext implementation doesn’t support closures, or (for an
implementation that validates during parsing) if body is otherwise unsuitable — e.g.
DynSegmentContext rejects a body that doesn’t produce exactly one value.
Sourcefn output_type_id(&self) -> Option<TypeId>
fn output_type_id(&self) -> Option<TypeId>
Returns the TypeId of the single value self currently holds, or None if that isn’t
known/applicable for this ParserContext implementation.
Used by the closure-literal grammar production to infer a closure’s return type from its
already-compiled body, mirroring Self::peek_tuple_arity’s “ask the context what it
currently holds” shape, generalized from “is it a tuple” to “what type is it”.
The default implementation returns None, matching Self::push_closure’s default
“unsupported” behavior — an implementation with no notion of a parse-time runtime type
(e.g. an AST-building context) simply can’t answer this, which surfaces to the caller the
same way an empty or multi-valued body does (a plain parse error), and in practice never
matters for such an implementation anyway, since its push_closure override (if any)
would reject the closure regardless.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".