// pest. The Elegant Parser // Copyright (c) 2018 DragoČ™ Tiselice // // Licensed under the Apache License, Version 2.0 // or the MIT // license , 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 = { choice_operator? ~ 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)*) }