LCOV - code coverage report
Current view: top level - dashql-parser/src/parser - actions.rs Coverage Total Hit
Test: DashQL 6e74948 Lines: 97.6 % 126 123
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : //! The vocabulary of the grammar actions. The generated rules module (`grammar/rules_rs`) imports everything from here.
       2              : 
       3              : pub use super::context::{null, IntoNodeList, ParseContext, NO_PARENT};
       4              : pub use super::value::{ExprVariant, FromValue, NodeList, Str, Value};
       5              : pub use crate::names::NameId;
       6              : pub use dashql_buffers::parser::{
       7              :     AConstType, AttributeKey, CharacterType, ColumnConstraint, CombineModifier, CombineOperation, ConstraintAttribute,
       8              :     ExpressionOperator, ExtractTarget, GroupByItemType, IntervalType, JoinType, KeyActionCommand, KeyActionTrigger,
       9              :     KeyMatch, KnownFunction, Node, NodeType, NumericType, OnCommitOption, OrderDirection, OrderNullRule,
      10              :     RowLockingBlockBehavior, RowLockingStrength, SampleCountUnit, SubqueryQuantifier, SymbolSpan, TableConstraint,
      11              :     TempType, TrimDirection, WindowBoundDirection, WindowBoundMode, WindowExclusionMode, WindowRangeMode,
      12              : };
      13              : 
      14              : /// Attribute keys, as the grammar actions call them
      15              : pub type Key = AttributeKey;
      16              : /// Expression operators, as the grammar actions call them
      17              : pub type ExprFunc = ExpressionOperator;
      18              : 
      19              : /// An empty node list
      20              : pub const NO_NODES: &[Node; 0] = &[];
      21              : 
      22              : /// The parser stack as seen by an action
      23              : pub trait ReduceStack {
      24              :     /// The value of the i-th symbol from the top
      25              :     fn value_at(&self, i: usize) -> Value;
      26              :     /// The location of the i-th symbol from the top
      27              :     fn location_at(&self, i: usize) -> SymbolSpan;
      28              : }
      29              : 
      30              : /// An action failed
      31              : #[derive(Clone, Copy, Debug, PartialEq, Eq)]
      32              : pub enum ReduceError {
      33              :     /// The action raised `YYERROR`
      34              :     YyError,
      35              : }
      36              : 
      37              : /// Set the attribute key of a node
      38       402339 : pub fn attr(key: AttributeKey, node: Node) -> Node {
      39       402339 :     Node::new(node.symbol_span(), node.node_type(), key, node.parent(), node.children_begin_or_value(), node.children_count())
      40       402339 : }
      41              : 
      42              : /// An operator
      43          777 : pub fn operator_node(loc: SymbolSpan) -> Node {
      44          777 :     Node::new(&loc, NodeType::OPERATOR, AttributeKey::NONE, NO_PARENT, 0, 0)
      45          777 : }
      46              : 
      47              : /// A name from an identifier
      48        99796 : pub fn name_from_identifier(loc: SymbolSpan, name: NameId) -> Node {
      49        99796 :     Node::new(&loc, NodeType::NAME, AttributeKey::NONE, NO_PARENT, name, 0)
      50        99796 : }
      51              : 
      52              : /// A boolean
      53         3661 : pub fn bool_node(loc: SymbolSpan, v: bool) -> Node {
      54         3661 :     Node::new(&loc, NodeType::BOOL, AttributeKey::NONE, NO_PARENT, v as u32, 0)
      55         3661 : }
      56              : 
      57              : /// A constant literal
      58        29018 : pub fn const_node(loc: SymbolSpan, t: AConstType) -> Node {
      59        29018 :     let node_type = match t {
      60          530 :         AConstType::NULL_ => NodeType::LITERAL_NULL,
      61        17642 :         AConstType::INTEGER => NodeType::LITERAL_INTEGER,
      62          936 :         AConstType::FLOAT => NodeType::LITERAL_FLOAT,
      63         9910 :         AConstType::STRING => NodeType::LITERAL_STRING,
      64            0 :         AConstType::INTERVAL => NodeType::LITERAL_INTERVAL,
      65            0 :         _ => return null(),
      66              :     };
      67        29018 :     Node::new(&loc, node_type, AttributeKey::NONE, NO_PARENT, 0, 0)
      68        29018 : }
      69              : 
      70              : /// Enums that become enum nodes (`Enum(loc, e)`)
      71              : pub trait EnumNodeType: Copy {
      72              :     const NODE_TYPE: NodeType;
      73              :     fn value(self) -> u32;
      74              : }
      75              : 
      76              : macro_rules! enum_node_types {
      77              :     ($($t:ident => $node_type:ident),* $(,)?) => {
      78              :         $(
      79              :             impl EnumNodeType for $t {
      80              :                 const NODE_TYPE: NodeType = NodeType::$node_type;
      81        52483 :                 fn value(self) -> u32 {
      82        52483 :                     self.0 as u32
      83        52483 :                 }
      84              :             }
      85              :         )*
      86              :     };
      87              : }
      88              : 
      89              : enum_node_types! {
      90              :     AConstType => ENUM_SQL_CONST_TYPE,
      91              :     CharacterType => ENUM_SQL_CHARACTER_TYPE,
      92              :     ColumnConstraint => ENUM_SQL_COLUMN_CONSTRAINT,
      93              :     CombineModifier => ENUM_SQL_COMBINE_MODIFIER,
      94              :     CombineOperation => ENUM_SQL_COMBINE_OPERATION,
      95              :     ConstraintAttribute => ENUM_SQL_CONSTRAINT_ATTRIBUTE,
      96              :     ExpressionOperator => ENUM_SQL_EXPRESSION_OPERATOR,
      97              :     ExtractTarget => ENUM_SQL_EXTRACT_TARGET,
      98              :     GroupByItemType => ENUM_SQL_GROUP_BY_ITEM_TYPE,
      99              :     IntervalType => ENUM_SQL_INTERVAL_TYPE,
     100              :     JoinType => ENUM_SQL_JOIN_TYPE,
     101              :     KeyActionCommand => ENUM_SQL_KEY_ACTION_COMMAND,
     102              :     KeyActionTrigger => ENUM_SQL_KEY_ACTION_TRIGGER,
     103              :     KeyMatch => ENUM_SQL_KEY_MATCH,
     104              :     KnownFunction => ENUM_SQL_KNOWN_FUNCTION,
     105              :     NumericType => ENUM_SQL_NUMERIC_TYPE,
     106              :     OnCommitOption => ENUM_SQL_ON_COMMIT_OPTION,
     107              :     OrderDirection => ENUM_SQL_ORDER_DIRECTION,
     108              :     OrderNullRule => ENUM_SQL_ORDER_NULL_RULE,
     109              :     RowLockingBlockBehavior => ENUM_SQL_ROW_LOCKING_BLOCK_BEHAVIOR,
     110              :     RowLockingStrength => ENUM_SQL_ROW_LOCKING_STRENGTH,
     111              :     SampleCountUnit => ENUM_SQL_SAMPLE_UNIT_TYPE,
     112              :     SubqueryQuantifier => ENUM_SQL_SUBQUERY_QUANTIFIER,
     113              :     TableConstraint => ENUM_SQL_TABLE_CONSTRAINT,
     114              :     TempType => ENUM_SQL_TEMP_TYPE,
     115              :     TrimDirection => ENUM_SQL_TRIM_TARGET,
     116              :     WindowBoundDirection => ENUM_SQL_WINDOW_BOUND_DIRECTION,
     117              :     WindowBoundMode => ENUM_SQL_WINDOW_BOUND_MODE,
     118              :     WindowExclusionMode => ENUM_SQL_WINDOW_EXCLUSION_MODE,
     119              :     WindowRangeMode => ENUM_SQL_WINDOW_RANGE_MODE,
     120              : }
     121              : 
     122              : /// An enum value
     123        52483 : pub fn enum_node<E: EnumNodeType>(loc: SymbolSpan, e: E) -> Node {
     124        52483 :     Node::new(&loc, E::NODE_TYPE, AttributeKey::NONE, NO_PARENT, e.value(), 0)
     125        52483 : }
     126              : 
     127              : /// The span covering all spans (`Loc({..})`)
     128         6120 : pub fn loc(spans: &[SymbolSpan]) -> SymbolSpan {
     129        18235 :     let begin = spans.iter().map(|s| s.offset()).min().unwrap_or(0);
     130        18235 :     let end = spans.iter().map(|s| s.offset() + s.length()).max().unwrap_or(0);
     131         6120 :     SymbolSpan::new(begin, end - begin)
     132         6120 : }
     133              : 
     134              : /// Merge join types
     135          292 : pub fn merge_join(left: JoinType, right: JoinType) -> JoinType {
     136          292 :     JoinType(left.0 | right.0)
     137          292 : }
     138              : 
     139              : /// An index or slice indirection with a single index
     140            8 : pub fn indirection_index(ctx: &ParseContext, loc: SymbolSpan, index: Node) -> Node {
     141            8 :     ctx.object(loc, NodeType::OBJECT_SQL_INDIRECTION_INDEX, &[attr(Key::SQL_INDIRECTION_INDEX_VALUE, index)])
     142            8 : }
     143              : 
     144              : /// A slice indirection with bounds
     145           59 : pub fn indirection_index_bounds(ctx: &ParseContext, loc: SymbolSpan, lower: Node, upper: Node) -> Node {
     146              :     // Both bounds are optional, `[:]` stays an object without attributes
     147           59 :     ctx.object_ex(
     148           59 :         loc,
     149              :         NodeType::OBJECT_SQL_INDIRECTION_INDEX,
     150           59 :         &[attr(Key::SQL_INDIRECTION_INDEX_LOWER_BOUND, lower), attr(Key::SQL_INDIRECTION_INDEX_UPPER_BOUND, upper)],
     151              :         false,
     152              :         false,
     153              :     )
     154           59 : }
     155              : 
     156              : /// A temp table name
     157           62 : pub fn into_node(ctx: &ParseContext, loc: SymbolSpan, temp_type: Node, name: Node) -> Node {
     158           62 :     ctx.object(loc, NodeType::OBJECT_SQL_INTO, &[attr(Key::SQL_TEMP_TYPE, temp_type), attr(Key::SQL_TEMP_NAME, name)])
     159           62 : }
     160              : 
     161              : /// A column reference
     162        50368 : pub fn column_ref(ctx: &ParseContext, loc: SymbolSpan, path: NodeList) -> Node {
     163        50368 :     let path_nodes = ctx.array(loc, path);
     164        50368 :     ctx.object(loc, NodeType::OBJECT_SQL_COLUMN_REF, &[attr(Key::SQL_COLUMN_REF_PATH, path_nodes)])
     165        50368 : }
     166              : 
     167              : /// An expression without arguments
     168            7 : pub fn expr0(ctx: &ParseContext, loc: SymbolSpan, func: Node) -> Node {
     169            7 :     ctx.object(loc, NodeType::OBJECT_SQL_NARY_EXPRESSION, &[attr(Key::SQL_EXPRESSION_OPERATOR, func)])
     170            7 : }
     171              : 
     172              : /// A unary expression
     173          287 : pub fn expr1(ctx: &ParseContext, loc: SymbolSpan, func: Node, arg: impl Into<ExprVariant>) -> Node {
     174          287 :     let args = ctx.expression_array(loc, &[arg.into()]);
     175          287 :     ctx.object(
     176          287 :         loc,
     177              :         NodeType::OBJECT_SQL_NARY_EXPRESSION,
     178          287 :         &[attr(Key::SQL_EXPRESSION_OPERATOR, func), attr(Key::SQL_EXPRESSION_ARGS, args)],
     179              :     )
     180          287 : }
     181              : 
     182              : /// A postfix expression
     183            1 : pub fn expr_postfix(ctx: &ParseContext, loc: SymbolSpan, func: Node, arg: impl Into<ExprVariant>) -> ExprVariant {
     184            1 :     let args = [arg.into()];
     185            1 :     if let Some(merged) = ctx.try_merge(loc, func, &args) {
     186            0 :         return merged;
     187            1 :     }
     188            1 :     let postfix = bool_node(loc, true);
     189            1 :     let args = ctx.expression_array(loc, &args);
     190            1 :     ExprVariant::Node(ctx.object(
     191            1 :         loc,
     192            1 :         NodeType::OBJECT_SQL_NARY_EXPRESSION,
     193            1 :         &[
     194            1 :             attr(Key::SQL_EXPRESSION_OPERATOR, func),
     195            1 :             attr(Key::SQL_EXPRESSION_POSTFIX, postfix),
     196            1 :             attr(Key::SQL_EXPRESSION_ARGS, args),
     197            1 :         ],
     198            1 :     ))
     199            1 : }
     200              : 
     201        34052 : fn nary_expr(ctx: &ParseContext, loc: SymbolSpan, func: Node, args: &[ExprVariant]) -> ExprVariant {
     202        34052 :     if let Some(merged) = ctx.try_merge(loc, func, args) {
     203        11923 :         return merged;
     204        22129 :     }
     205        22129 :     let args = ctx.expression_array(loc, args);
     206        22129 :     ExprVariant::Node(ctx.object(
     207        22129 :         loc,
     208        22129 :         NodeType::OBJECT_SQL_NARY_EXPRESSION,
     209        22129 :         &[attr(Key::SQL_EXPRESSION_OPERATOR, func), attr(Key::SQL_EXPRESSION_ARGS, args)],
     210        22129 :     ))
     211        34052 : }
     212              : 
     213              : /// A binary expression
     214        32546 : pub fn expr2(
     215        32546 :     ctx: &ParseContext,
     216        32546 :     loc: SymbolSpan,
     217        32546 :     func: Node,
     218        32546 :     left: impl Into<ExprVariant>,
     219        32546 :     right: impl Into<ExprVariant>,
     220        32546 : ) -> ExprVariant {
     221        32546 :     nary_expr(ctx, loc, func, &[left.into(), right.into()])
     222        32546 : }
     223              : 
     224              : /// A ternary expression
     225         1506 : pub fn expr3(
     226         1506 :     ctx: &ParseContext,
     227         1506 :     loc: SymbolSpan,
     228         1506 :     func: Node,
     229         1506 :     arg0: impl Into<ExprVariant>,
     230         1506 :     arg1: impl Into<ExprVariant>,
     231         1506 :     arg2: impl Into<ExprVariant>,
     232         1506 : ) -> ExprVariant {
     233         1506 :     nary_expr(ctx, loc, func, &[arg0.into(), arg1.into(), arg2.into()])
     234         1506 : }
     235              : 
     236              : /// Negate an expression
     237          221 : pub fn negate(ctx: &ParseContext, loc: SymbolSpan, loc_minus: SymbolSpan, value: impl Into<ExprVariant>) -> Node {
     238          221 :     let op = enum_node(loc_minus, ExpressionOperator::NEGATE);
     239          221 :     let args = ctx.expression_array(loc, &[value.into()]);
     240          221 :     ctx.object(
     241          221 :         loc,
     242              :         NodeType::OBJECT_SQL_NARY_EXPRESSION,
     243          221 :         &[attr(Key::SQL_EXPRESSION_OPERATOR, op), attr(Key::SQL_EXPRESSION_ARGS, args)],
     244              :     )
     245          221 : }
     246              : 
     247              : /// A vararg field. Every level wraps the value, not the inner level.
     248           81 : pub fn vararg_field(ctx: &ParseContext, loc: SymbolSpan, path: NodeList, value: Node) -> Node {
     249           81 :     let mut root = value;
     250           81 :     let keys = ctx.state.borrow().lists_snapshot(path);
     251           81 :     for key in keys.into_iter().rev() {
     252           81 :         root = ctx.object(
     253           81 :             loc,
     254           81 :             NodeType::OBJECT_EXT_VARARG_FIELD,
     255           81 :             &[attr(Key::EXT_VARARG_FIELD_KEY, key), attr(Key::EXT_VARARG_FIELD_VALUE, value)],
     256           81 :         );
     257           81 :     }
     258           81 :     root
     259           81 : }
        

Generated by: LCOV version 2.0-1