// pest-typed. A statically typed version of pest.
// Copyright (c) 2023 黄博奕
// 
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

/// Regular rule.
Regular = { CharRange+ ~ "+" ~ CharRange+ }

/// Atomic rule.
Atomic = @{ ('0'..'9')+ }

/// Silent rule.
Silent = _{ "(" | ")" }

/// Compound atomic rule.
CompoundAtomic = ${ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }

/// Tagged rule.
Tag = { ANY ~ (#Second = (PUSH(CompoundAtomic) ~ &Silent ~ !Atomic))? ~ (#Third = NonAtomic* ~ Regular+)? }
// It's weird that this line can't be formatted.
/// Non-atomic rule.
NonAtomic       = !{ (CaseInsensitive? ~ CharRange+ ~ Tag*)? ~ ("b" | "BB" ~ "b"?)? ~ ^"c"* ~ (!Seq ~ Any)+ }
ExactString     =  { "r#" }
CaseInsensitive =  { ^"0x" }
CharRange       =  { '0'..'9' }
Any             =  { ANY }
Seq             =  { "1" ~ '2'..'9' ~ "." }
Choice          =  { "a" | ^"b"+ ~ RepAtLeastOnce | &"c" ~ Choice ~ Rep ~ Opt | Peek | PeekLeft | PeekRight | PeekLeftRight | Drop | PeekAll }
Rep             =  { ^"b"* }
RepAtLeastOnce  =  { '0'..'9'+ }
Opt             =  { "?"? }
RepExact        =  { RepAtLeastOnce{3} }
RepLeft         =  { RepExact{1, } }
RepRight        =  { RepLeft{, 2} }
RepLeftRight    =  { RepRight{1, 2} }

Pos = { &(SOI ~ RepLeftRight{2, 4}) }
Neg = { !(EOI ~ Pos) }

Push = { PUSH(RepLeft* ~ Neg ~ ExactString+ ~ Push ~ Pop ~ Push ~ PopAll) }

Pop    = { POP }
PopAll = { POP_ALL }

Peek          = { PEEK[..] }
PeekLeft      = { PEEK[1..] }
PeekRight     = { PEEK[..] }
PeekLeftRight = { PEEK[1..2] }

Drop = { DROP }

PeekAll = { PEEK_ALL }
