Last active
April 25, 2023 14:22
-
-
Save azatoth/786486ccf112f11dd407049ba8b81166 to your computer and use it in GitHub Desktop.
Nearly grammer for TFRs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@{% | |
const { DateTime } = require("luxon"); | |
%} | |
@builtin "postprocessors.ne" | |
@builtin "whitespace.ne" | |
notam -> "!" prefix __ | |
notam_id __ | |
airspace __ | |
part:? _ | |
preamble __:+ | |
bounded_by:? _ | |
height _ | |
effective_date:? _ | |
postamble __ | |
dates [^]:* {% | |
$({ | |
prefix: 1, | |
id: 3, | |
airspace: 5, | |
preamble: 9, | |
bounds: 11, | |
height: 13, | |
effective_date: 15, | |
postamble: 17, | |
dates: 19, | |
}) | |
%} | |
prefix -> [A-Z]:+ {% prefix %} | |
part -> "PART" __ ints __ "OF" __ ints {% $({current:2, total:6}) %} | |
end_part -> "END" __ "PART" __ [0-9]:+ __ "OF" __ [0-9]:+ {% $({current:1, total:3}) %} | |
notam_id -> [0-9]:+ "/" [0-9]:+ {% notam_id %} | |
airspace -> [A-Z]:+ {% airspace %} | |
preamble -> [A-Z0-9/.\s-;,]:+ {% preamble %} | |
bounded_by -> bounded_prefix _ (bound_radius | bound_list (_ to_point_of_origin):? ) {% bounded_by %} | |
bound_list -> delimited[coord_frd, __ "TO" __] ".":? {% bound_list %} | |
bound_radius -> xnm __ "RADIUS" __ "OF" __ coord_frd {% $({radius: 0, center: 6}) %} | |
xnm -> [0-9]:+ ".":? [0-9]:* "NM" {% xnm %} | |
coord_frd -> coord __:? frd:? {% $({coord: 0, frd: 2}) %} | |
frd -> "(" ([A-Z] [A-Z] [A-Z] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] ("." [0-9]):?) ")" {% frd %} | |
coord -> point "/":? point {% coord %} | |
point -> ([0-9]:+ [NEWS]) {% point %} | |
bounded_prefix -> "WI" "THIN":? __ "AN" __ ("AREA" __):? ( "BOUNDED" __ "BY" | "DEFINED" __ "AS" ) ".":? {% bounded_prefix %} | |
to_point_of_origin -> "TO" (__ "THE"):? __ "POINT" __ "OF" __ "ORIGIN" ".":? {% to_point_of_origin %} | |
effective_date -> "EFFECTIVE" __ date __ "UNTIL" __ date "." {% $({from: 2, to: 6}) %} | |
date -> utc_date __ "(" local_date ")" {% $({utc: 0, local: 3}) %} | |
utc_date -> (ii ii ii ii ii) __ "UTC" {% utc_date %} | |
local_date -> ii ii __ "LOCAL" __ ii "/" ii "/" ii {% local_date %} | |
ii -> [0-9] [0-9] {% d => d.join("") %} | |
height -> "SFC" "-" ( height_ft | height_unl | height_fl ) __ "MSL":? ".":? _ {% height %} | |
height_ft -> [0-9]:+ _ "FT" {% height_ft %} | |
height_unl -> "UNL" {% height_unl %} | |
height_fl -> "FL" _ [0-9]:+ {% height_fl %} | |
postamble -> ([A-Z0-9.\s/:,();-]):+ {% postamble %} | |
dates -> int10 "-" int10 {% dates %} | |
int10 -> [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] | |
ints -> [0-9]:+ {% d => parseInt(d.join("")) %} | |
@{% | |
const parseDate = (str) => { | |
return DateTime.fromFormat(str, "yyMMddHHmm", { zone: "utc" }).toJSON(); | |
}; | |
const parseLocalDate = (str) => { | |
return DateTime.fromFormat(str, "HHmm MM/dd/yy", { zone: "America/Chicago" }).toJSON(); | |
}; | |
const prefix = (d) => d[0].join(''); | |
const notam_id = (d) => d[0].join('') + "/" + d[2].join(''); | |
const airspace = (d) => d[0].join(''); | |
const preamble = (d,l,reject) => { | |
const str = d.flat().join("").replace(/\s+/gm, " ").trim() | |
if(/WI(THIN)?\sAN/.test(str) || /PART \d+ OF \d+/.test(str)) { | |
return reject; | |
} | |
return str | |
}; | |
const bounded_by = (d) => { | |
const list = d[2]; | |
if (d[3]) { | |
list.push(list[0]); | |
} | |
return list; | |
}; | |
const bound_list = (d) => d[0].flat(); | |
const point = (d) => d[0].flat().join(""); | |
const frd = (d) => d[1].flat().join(""); | |
const xnm = (d) => Number.parseFloat(d.slice(0,3).join(""), 10) + " " + d[3]; | |
const coord = (d) => d[0] + "/" + d[2]; | |
const bounded_prefix = (d) => d.join(""); | |
const to_point_of_origin = () => true; | |
const height = (d) => d[2].join(''); | |
const height_ft = (d) => d[0].join('') + "ft"; | |
const height_fl = (d) => "fl" + d[2].join(''); | |
const height_unl = () => "unlimited"; | |
const postamble = (d,l,reject) => { | |
const str = d.flat().join("").replace(/\s+/g, " ").trim(); | |
if(/\d{10}-\d{10}$/.test(d)) { | |
return reject; | |
} | |
return str; | |
}; | |
const dates = (d) => ({ | |
from: parseDate(d[0].join('')), | |
to: parseDate(d[2].join('')), | |
}); | |
const utc_date = (d) => parseDate(d[0].join("")) | |
const local_date = (d) => parseLocalDate(`${d[0]}${d[1]} ${d[5]}/${d[7]}/${d[9]}`); | |
%} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment