andygrove commented on issue #2893:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/issues/2893#issuecomment-6741222731

   A summary of the design and how it differs from v1.
   
   **Dialects.** The parser is generic over the dialect, and every grammar rule 
is a `Dialect` method defaulting to the core rule. Rules call each other 
through `D::`, so an override applies everywhere. The core has no dialect 
checks, where v1 has `dialect_of!` and `supports_*` flags.
   
   ```rust
   pub trait Dialect: 'static + Sized {
       type Ext: AstExt;
   
       fn parse_limit<'a>(p: &mut Parser<'a, Self>) -> PResult<Limit<'a, 
Self::Ext>> {
           grammar::parse_limit(p)
       }
       // ... one method per grammar rule
   }
   
   let statements = parse_sql::<Hive>(sql)?;
   ```
   
   **Expressions and shared rules.** The core is a Pratt parser, and an infix 
rule holds the binding power and the parse action together, so they can't 
disagree. Dialect rules are public generic functions, so related dialects build 
on each other: Redshift on Postgres, Hive and Databricks on Spark.
   
   ```rust
   impl Dialect for Hive {
       fn infix_rule<'a>(p: &Parser<'a, Self>) -> Option<InfixRule<'a, Self>> {
           if p.at_op("<=>") {
               return Some(InfixRule::binary(prec::COMPARE, 
BinaryOp::Named("<=>")));
           }
           spark::infix_rule(p)
       }
   }
   ```
   
   **Extensibility.** A dialect in another crate can add tokens, operators and 
AST nodes, through associated types on `AstExt`.
   
   ```rust
   impl AstExt for Acme {
       type Expr<'a> = Coalesce<'a>;
       type Statement<'a> = Ping<'a>;
       // ... other extension points
   }
   
   impl Dialect for Acme {
       type Ext = Self;
   
       fn parse_statement<'a>(p: &mut Parser<'a, Self>) -> 
PResult<Statement<'a, Self>> {
           if p.eat_keyword("PING") {
               let host = p.parse_ident()?;
               return Ok(Statement::Ext(Ping { host }));
           }
           grammar::parse_statement(p)
       }
   }
   ```
   
   **Zero-copy.** Tokens and AST nodes borrow from the input, and dispatch is 
static. Keywords are matched by source text, not a central enum.
   
   ```rust
   pub struct Token<'a> {
       pub kind: TokenKind,
       pub text: &'a str,
       pub span: Span,
   }
   
   pub struct Ident<'a> {
       pub text: &'a str,
       pub quote: Option<char>,
       pub span: Span,
   }
   ```
   
   **Trade-offs.** It's a breaking change: the AST borrows from the SQL and is 
generic over its extensions. Dialects are strict, rejecting other databases' 
syntax, and there's no `GenericDialect`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to