blob: 0d03ba8998e2eb62e0f5a683906ab55d76a584e6 [file] [log] [blame]
// pest. The Elegant Parser
// Copyright (c) 2018 DragoČ™ Tiselice
//
// 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.
grammar_rules = _{ SOI ~ grammar_rule+ ~ EOI }
grammar_rule = {
identifier ~ assignment_operator ~ modifier? ~
opening_brace ~ expression ~ closing_brace
}
assignment_operator = { "=" }
opening_brace = { "{" }
closing_brace = { "}" }
opening_paren = { "(" }
closing_paren = { ")" }
opening_brack = { "[" }
closing_brack = { "]" }
modifier = _{
silent_modifier |
atomic_modifier |
compound_atomic_modifier |
non_atomic_modifier
}
silent_modifier = { "_" }
atomic_modifier = { "@" }
compound_atomic_modifier = { "$" }
non_atomic_modifier = { "!" }
expression = { term ~ (infix_operator ~ term)* }
term = { prefix_operator* ~ node ~ postfix_operator* }
node = _{ opening_paren ~ expression ~ closing_paren | terminal }
terminal = _{ _push | peek_slice | identifier | string | insensitive_string | range }
prefix_operator = _{ positive_predicate_operator | negative_predicate_operator }
infix_operator = _{ sequence_operator | choice_operator }
postfix_operator = _{
optional_operator |
repeat_operator |
repeat_once_operator |
repeat_exact |
repeat_min |
repeat_max |
repeat_min_max
}
positive_predicate_operator = { "&" }
negative_predicate_operator = { "!" }
sequence_operator = { "~" }
choice_operator = { "|" }
optional_operator = { "?" }
repeat_operator = { "*" }
repeat_once_operator = { "+" }
repeat_exact = { opening_brace ~ number ~ closing_brace }
repeat_min = { opening_brace ~ number ~ comma ~ closing_brace }
repeat_max = { opening_brace ~ comma ~ number ~ closing_brace }
repeat_min_max = { opening_brace ~ number ~ comma ~ number ~ closing_brace }
number = @{ '0'..'9'+ }
integer = @{ number | "-" ~ "0"* ~ '1'..'9' ~ number? }
comma = { "," }
_push = { "PUSH" ~ opening_paren ~ expression ~ closing_paren }
peek_slice = { "PEEK" ~ opening_brack ~ integer? ~ range_operator ~ integer? ~ closing_brack }
identifier = @{ !"PUSH" ~ ("_" | alpha) ~ ("_" | alpha_num)* }
alpha = _{ 'a'..'z' | 'A'..'Z' }
alpha_num = _{ alpha | '0'..'9' }
string = ${ quote ~ inner_str ~ quote }
insensitive_string = { "^" ~ string }
range = { character ~ range_operator ~ character }
character = ${ single_quote ~ inner_chr ~ single_quote }
inner_str = @{ (!("\"" | "\\") ~ ANY)* ~ (escape ~ inner_str)? }
inner_chr = @{ escape | ANY }
escape = @{ "\\" ~ ("\"" | "\\" | "r" | "n" | "t" | "0" | "'" | code | unicode) }
code = @{ "x" ~ hex_digit{2} }
unicode = @{ "u" ~ opening_brace ~ hex_digit{2, 6} ~ closing_brace }
hex_digit = @{ '0'..'9' | 'a'..'f' | 'A'..'F' }
quote = { "\"" }
single_quote = { "'" }
range_operator = { ".." }
newline = _{ "\n" | "\r\n" }
WHITESPACE = _{ " " | "\t" | newline }
block_comment = _{ "/*" ~ (block_comment | !"*/" ~ ANY)* ~ "*/" }
COMMENT = _{ block_comment | ("//" ~ (!newline ~ ANY)*) }