// strings
// TODO: think more about what/how to escape
char = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
string = @{ char* }
quoted_string = _{ "\"" ~ string ~ "\"" }
// comments
comment = _{ "#" ~ (!NEWLINE ~ ANY)* }
// header with version info
major = { ASCII_DIGIT+ }
minor = { ASCII_DIGIT+ }
patch = { ASCII_DIGIT+ }
version = { major ~ "." ~ minor ~ "." ~ patch}
header = _{ "OSMFilter " ~ version ~ NEWLINE{2}}
// modifier statements
set = { "SET " ~ quoted_string ~ " " ~ quoted_string }
rename = { "RENAME " ~ quoted_string ~ " " ~ quoted_string }
delete = { "DELETE " ~ quoted_string }
commit = { "COMMIT" }
drop = { "DROP" }
modifier = _{ set | rename | delete | commit | drop }
// selector statements
node = { "node" }
way = { "way" }
relation = { "relation" }
osm_type = _{ node | way | relation } // TODO: add "area"
type_selector = { "TYPE " ~ osm_type ~ (", " ~ osm_type)* }
has = { "HAS " ~ quoted_string }
equals = { "EQUALS " ~ quoted_string ~ " " ~ quoted_string }
// TODO: add timestamps, since, before, user, uid, id, version
selector = { type_selector | has | equals }
new_selection_block = _{
// if we were already indented,
PEEK_ALL ~ PUSH("\t") ~ statement ~
// subsequent lines in the block
(NEWLINE ~ PEEK_ALL ~ statement)* ~
// drop the last layer of indentation from the stack
DROP
}
selection_block = {
selector ~ (" "+ ~ comment)? ~ NEWLINE ~ new_selection_block
}
// bigger picture
statement = _{ (comment | modifier | selection_block) ~ (" "+ ~ comment)? }
body = { (statement | NEWLINE)+ }
file = _{ SOI ~ header ~ body ~ EOI }