empress 1.6.0

A D-Bus MPRIS daemon for controlling media players.
use serde_json::Number;

use super::super::{ast, lexer};

grammar<'i>;

extern {
  type Location = lexer::Pos;

  enum lexer::Token<'i> {
    Fragment => lexer::Token::Fragment(<&'i str>),
    "}}" => lexer::Token::BlockEnd,

    "." => lexer::Token::Dot,
    "," => lexer::Token::Comma,
    "|!" => lexer::Token::PipeBang,
    "|" => lexer::Token::Pipe,
    "??" => lexer::Token::Coalesce,
    "(" => lexer::Token::LParen,
    ")" => lexer::Token::RParen,
    "[" => lexer::Token::LBrack,
    "]" => lexer::Token::RBrack,
    Ident => lexer::Token::Ident(<&'i str>),
    Number => lexer::Token::Number(<Number>),
    String => lexer::Token::String(<String>),
  }
}

pub Format = <Segment*>;

Segment: ast::Segment<'i> = {
  Fragment => ast::Segment::Fragment(<>),
  Block => ast::Segment::Block(<>),
};

Block = <Expr?> "}}";

Expr: ast::Expr<'i> = {
  NullChain => ast::Expr(Box::new(<>)),
};

NullChain: ast::NullChain<'i> = {
  <l:NullChain> "??" <r:NullPipeline> => ast::NullChain::Chain(Box::new(l), r),
  NullPipeline => ast::NullChain::Bang(<>),
};

NullPipeline: ast::NullPipeline<'i> = {
  <l:NullPipeline> "|!" <r:Pipeline> => ast::NullPipeline::Bang(Box::new(l), r),
  Pipeline => ast::NullPipeline::Pipe(<>),
};

Pipeline: ast::Pipeline<'i> = {
  <l:Pipeline> "|" <r:Lens> => ast::Pipeline::Pipe(Box::new(l), r),
  Lens => ast::Pipeline::Lens(<>),
};

Lens: ast::Lens<'i> = {
  <l:Lens> "." <r:Ident> => ast::Lens::Dot(Box::new(l), r),
  <l:Lens> "[" <r:Expr> "]" => ast::Lens::Index(Box::new(l), r),
  Prim => ast::Lens::Prim(<>),
};

Prim: ast::Prim<'i> = {
  "(" <Expr> ")" => ast::Prim::Paren(<>),
  <Ident> "(" <Args?> ")" => ast::Prim::Call(<>),
  "[" <Args?> "]" => ast::Prim::Array(<>),
  Ident => ast::Prim::Ident(<>),
  Number => ast::Prim::Value(<>.into()),
  String => ast::Prim::Value(<>.into()),
};

Args: ast::Args<'i> = {
  <l:Args> "," <r:Expr> => ast::Args::Comma(Box::new(l), r),
  Expr => ast::Args::Expr(<>),
};