//
// include/grammar.pest
//
// ftml - Library to parse Wikidot text
// Copyright (C) 2019-2021 Wikijump Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// A simple parser generation exclusively to extract [[include]] directives
// within the wikitext. Other elements should be ignored and left as-is.
// The "include" rule has some strange logic:
//
// [[include]]s can have leading *and* trailing pipe separators,
// for instance [[include page | a = 1 ]] or [[include page a = 1 | ]] (or both)
//
// Additionally, each argument must be separated from each other with a pipe.
// We encapsulate this logic by essentially doing "(parameter ~ pipe)* ~ (parameter ~ pipe?)?
// That is, all internal parameters need pipes inside, but the last does not,
// and is optional should the sequence end in a pipe.
include = {
SOI ~
"[[" ~ space ~ ^"include" ~ space ~
page_ref ~ space ~
"|"? ~ space ~
(argument ~ space ~ "|" ~ space)* ~
(argument ~ space ~ ("|" ~ space)?)? ~
"]]"
}
argument = {
identifier ~ space ~
"=" ~ space ~
value
}
// This implements Wikidot's logic of "escaping" newlines or ]]s in
// an argument's value by placing a space after.
value = {
(
("]]"? ~ " " ~ NEWLINE) |
(!("|" | "]]" | NEWLINE) ~ ANY)
)+
}
// Reference to a page, possibly not on this wiki
page_ref = {
(":" ~ identifier ~ ":")? ~ page_name
}
site_name = _{ identifier }
page_name = { (ASCII_ALPHANUMERIC | "-" | "_" | ":")+ }
// Helpers
identifier = { (ASCII_ALPHANUMERIC | "-" | "_")+ }
space = _{ (" " | "\n" | "\t")* }
// vim: set fdm=marker foldlevel=0: