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

            Line data    Source code
       1              : //! The DashQL SQL grammar.
       2              : //!
       3              : //! [`tables`] holds the LALR(1) automaton and the actions that bison computes from the rules of
       4              : //! `//grammar` (`grammar/rules`), emitted through `//grammar/rust:tables.rs.m4`.
       5              : //!
       6              : //! [`scanner`] is a logos scanner of the grammar's tokens. [`parser`] runs the automaton with the
       7              : //! actions of `grammar/rules`.
       8              : 
       9              : use std::borrow::Cow;
      10              : 
      11              : pub mod attributes;
      12              : pub mod comment_blocks;
      13              : pub mod keywords;
      14              : pub mod names;
      15              : pub mod parser;
      16              : pub mod scanner;
      17              : pub mod span;
      18              : 
      19              : #[allow(dead_code, non_upper_case_globals, unused_braces, unused_parens, unused_variables, unused_mut)]
      20              : #[allow(clippy::all)]
      21              : #[rustfmt::skip]
      22              : pub mod tables;
      23              : 
      24              : pub use tables::symbol_kind;
      25              : 
      26              : /// A bison symbol kind: terminals in `0..YYNTOKENS`, nonterminals after them.
      27              : pub type SymbolKind = u16;
      28              : 
      29              : /// Is the symbol a terminal?
      30            2 : pub fn is_terminal(kind: SymbolKind) -> bool {
      31            2 :     (kind as usize) < tables::YYNTOKENS
      32            2 : }
      33              : 
      34              : /// The name of a symbol as bison's verbose error messages print it.
      35              : ///
      36              : /// Mirrors bison's `yytnamerr_`: a quoted alias such as `"identifier literal"` loses its
      37              : /// double quotes unless it contains an apostrophe, a comma or a backslash.
      38          335 : pub fn symbol_name(kind: SymbolKind) -> Cow<'static, str> {
      39          335 :     let name = tables::YYTNAME[kind as usize];
      40          335 :     let Some(quoted) = name.strip_prefix('"') else {
      41          206 :         return Cow::Borrowed(name);
      42              :     };
      43          129 :     let mut unquoted = String::with_capacity(quoted.len());
      44          129 :     let mut chars = quoted.chars();
      45         2418 :     while let Some(c) = chars.next() {
      46         2418 :         match c {
      47            0 :             '\'' | ',' => break,
      48            0 :             '\\' => match chars.next() {
      49            0 :                 Some('\\') => unquoted.push('\\'),
      50            0 :                 _ => break,
      51              :             },
      52          129 :             '"' => return Cow::Owned(unquoted),
      53         2289 :             c => unquoted.push(c),
      54              :         }
      55              :     }
      56            0 :     Cow::Borrowed(name)
      57          335 : }
      58              : 
      59              : #[cfg(test)]
      60              : mod tests {
      61              :     use super::*;
      62              : 
      63              :     #[test]
      64            1 :     fn automaton_size() {
      65            1 :         assert_eq!(tables::YYNTOKENS, 511);
      66            1 :         assert_eq!(tables::YYPACT.len(), tables::YYNSTATES);
      67            1 :         assert_eq!(tables::YYDEFACT.len(), tables::YYNSTATES);
      68            1 :         assert_eq!(tables::YYSTOS.len(), tables::YYNSTATES);
      69            1 :         assert_eq!(tables::YYR1.len(), tables::YYNRULES + 1);
      70            1 :         assert_eq!(tables::YYR2.len(), tables::YYNRULES + 1);
      71            1 :         assert_eq!(tables::YYPGOTO.len(), tables::YYNNTS);
      72            1 :         assert_eq!(tables::YYDEFGOTO.len(), tables::YYNNTS);
      73            1 :         assert_eq!(tables::YYTABLE.len(), tables::YYLAST as usize + 1);
      74            1 :         assert_eq!(tables::YYCHECK.len(), tables::YYLAST as usize + 1);
      75              :         // The symbol names end with bison's YY_NULLPTR sentinel.
      76            1 :         assert_eq!(tables::YYTNAME.len(), tables::YYNTOKENS + tables::YYNNTS + 1);
      77            1 :     }
      78              : 
      79              :     #[test]
      80            1 :     fn symbol_kinds() {
      81            1 :         assert_eq!(symbol_kind::S_YYEOF, 0);
      82            1 :         assert_eq!(symbol_kind::S_YYerror, 1);
      83            1 :         assert_eq!(symbol_kind::S_YYUNDEF, 2);
      84            1 :         assert_eq!(symbol_kind::S_IDENT, 3);
      85            1 :         assert!(is_terminal(symbol_kind::S_SELECT));
      86            1 :         assert!(!is_terminal(symbol_kind::S_sql_select_stmt));
      87            1 :     }
      88              : 
      89              :     #[test]
      90            1 :     fn symbol_names() {
      91            1 :         assert_eq!(symbol_name(symbol_kind::S_YYEOF), "EOF");
      92            1 :         assert_eq!(symbol_name(symbol_kind::S_IDENT), "identifier literal");
      93            1 :         assert_eq!(symbol_name(symbol_kind::S_SCONST), "string literal");
      94            1 :         assert_eq!(symbol_name(symbol_kind::S_YYUNDEF), "invalid token");
      95            1 :         assert_eq!(symbol_name(symbol_kind::S_SELECT), "SELECT");
      96            1 :         assert_eq!(symbol_name(symbol_kind::S_RRB), "RRB");
      97            1 :     }
      98              : }
        

Generated by: LCOV version 2.0-1