//
// include/grammar.pest
//
// ftml - Library to parse Wikidot text
// Copyright (C) 2019-2025 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.
// Wikidot's "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.
// Normal version ([[include]] only)
include_normal = {
SOI ~ // Because we slice from the start of an include block using regex
"[[" ~ space? ~ ^"include" ~ space ~
page_ref ~ space? ~
("|" ~ space?)? ~
(argument ~ space? ~ "|" ~ space?)* ~
(argument ~ space? ~ "|"?)? ~
space? ~ include_end
}
// Compatibility version (accepts [[include]] too)
include_compatibility = {
SOI ~ // Because we slice from the start of an include block using regex
"[[" ~ space? ~ (^"include" | ^"include") ~ space ~
page_ref ~ space? ~
("|" ~ space?)? ~
(argument ~ space? ~ "|" ~ space?)* ~
(argument ~ space? ~ "|"?)? ~
space? ~ include_end
}
include_end = _{
"]]" ~ &(NEWLINE | EOI)
}
argument = {
identifier ~ space? ~
"=" ~ space? ~
value
}
value = {
(!(include_end | "|") ~ ANY)+
}
// Reference to a page, possibly not on this wiki
page_ref = {
(":" ~ site_name ~ ":")? ~ page_name
}
site_name = _{ (!(" " | "\n" | "\t" | "[" | "|" | "]" | ":") ~ ANY)+ }
page_name = _{ (!(" " | "\n" | "\t" | "[" | "|" | "]") ~ ANY)+ }
// Helpers
identifier = { (ASCII_ALPHANUMERIC | "-" | "_")+ }
space = _{ (" " | "\n" | "\t")+ }
// vim: set fdm=marker foldlevel=0: