Skip to content

Instantly share code, notes, and snippets.

@hideshi
Created December 29, 2013 07:57
Show Gist options
  • Save hideshi/8168448 to your computer and use it in GitHub Desktop.
Save hideshi/8168448 to your computer and use it in GitHub Desktop.
This is a parser for METAR which is a format for weather information. See also: http://d.hatena.ne.jp/hideshi_o/20130105/1357376552
import scala.util.parsing.combinator.RegexParsers
abstract class Bulletin
case class MetarBulletin (
icao:String
,datetime:String
,windDirection:String
,windSpeed:String
,windShift:String
,visibility:String
,rvr:List[String]
,weather:String
,cloud:List[String]
,temperature:String
,airPressure:String
,significant:String
,remarks:List[String]
) extends Bulletin
class MetarParser extends RegexParsers {
def parse(data:String) = parseAll(all, data)
def all:Parser[MetarBulletin] = {
icao ~ datetime ~ wind ~ opt(windShift) ~ visibility ~ rep(rvr) ~ weather ~ rep(cloud) ~ temperature ~ airPressure ~ opt(significant) ~ """(RMK)?""".r ~ opt(rep(remarks)) ^^ {
case icao ~ datetime ~ wind ~ windShift ~ visibility ~ rvr ~ weather ~ cloud ~ temperature ~ airPressure ~ significant ~ rmk ~ remarks =>
MetarBulletin(
icao
,datetime
,wind._1
,wind._2
,windShift.getOrElse("")
,visibility
,rvr
,weather
,cloud
,temperature
,airPressure
,significant.getOrElse("")
,remarks.getOrElse(List())
)
}
}
def icao:Parser[String] = {
"""[A-Z]{4}""".r
}
def datetime:Parser[String] = {
"""[0-9]{6}Z""".r
}
def wind:Parser[(String, String)] = {
"""([0-9]{3}|VRB)[0-9]{2}KT""".r ^^ {
case wind:String => wind.splitAt(3)
}
}
def windShift:Parser[String] = {
"""[0-9]{3}V[0-9]{3}""".r
}
def visibility:Parser[String] = {
"""[0-9]{4}""".r
}
def rvr:Parser[String] = {
"""R[0-9]{2}/P[0-9]{4}[UN]""".r
}
def weather:Parser[String] = {
"""[+-]?(TS|SH|FZ|BC|MI|PR)?(RA|SN|DZ|SG|GR|GS|IC|PL)?(BA|FG|SA|FU|DU|HZ|VA)?""".r
}
def cloud:Parser[String] = {
"""(FEW|SCT|BKN|OVC)([0-9]{3}|[/]{3})(CB)?""".r
}
def temperature:Parser[String] = {
"""M?[0-9]{2}/M?[0-9]{2}""".r
}
def airPressure:Parser[String] = {
"""Q[0-9]{4}""".r
}
def significant:Parser[String] = {
"""(NOSIG|BECMG|TEMPO|WS)(\s[0-9]{5}KT)?""".r
}
def remarks:Parser[String] = {
"""[A-Z0-9]+""".r
}
}
val bulletin = List(
"RJCC 030810Z 21010KT 140V260 9999 SHRA FEW025 BKN030 FEW030CB 07/03 Q1001 RMK 1CU025 6CU030 2CB030 A2957 CB OHD MOV"
,"RJAA 050800Z 08003KT 9999 FEW030 BKN/// 04/M02 Q1019 BECMG 04005KT RMK 1CU030 A3009"
,"RJAA 050730Z 10004KT 050V130 9999 FEW030 SCT040 BKN/// 04/M02 Q1019 NOSIG RMK 1CU030 3SC040 A3009"
,"RJAA 050700Z 12004KT 070V160 9999 FEW030 BKN040 BKN/// 05/M02 Q1019 NOSIG RMK 1CU030 5SC040 A3010"
,"RJAA 050630Z VRB02KT 9999 FEW030 BKN040 BKN/// 05/M03 Q1019 BECMG 09005KT RMK 1CU030 5SC040 A3009"
,"RJAA 050600Z 06003KT 350V100 9999 FEW030 BKN/// 05/M03 Q1018 BECMG 07005KT RMK 1CU030 A3008"
,"RJAA 050530Z 01003KT 310V040 9999 FEW030 SCT050 BKN/// 05/M03 Q1018 NOSIG"
,"RJAA 050500Z 03004KT 350V070 9999 FEW030 SCT060 BKN/// 05/M04 Q1018 NOSIG RMK 1CU030 3SC060 A3008"
,"RJAA 050430Z 01004KT 330V050 9999 FEW030 BKN060 BKN/// 05/M04 Q1019 NOSIG RMK 1CU030 5SC060 A3009"
,"RJAA 050400Z 01004KT 310V060 9999 FEW030 BKN060 BKN/// 05/M04 Q1019 NOSIG RMK 1CU030 5SC060 A3010"
,"RJAA 050330Z 02004KT 340V070 9999 FEW030 BKN060 BKN/// 05/M05 Q1020 BECMG 07005KT RMK 1CU030 5SC060 A3012"
,"RJAA 050300Z 03006KT 350V070 9999 FEW030 BKN060 BKN/// 04/M05 Q1020 NOSIG RMK 1CU030 5SC060 A3013"
,"RJAA 050230Z 36007KT 320V040 9999 FEW030 BKN070 BKN/// 04/M06 Q1021 NOSIG"
,"RJBB 050800Z VRB02KT 9999 FEW030 BKN160 BKN/// 05/M06 Q1020 NOSIG"
,"RJBB 050730Z VRB02KT 9999 FEW030 SCT160 BKN/// 05/M06 Q1020 NOSIG"
,"RJBB 050700Z 07003KT 050V110 9999 FEW030 BKN/// 05/M06 Q1020 NOSIG"
,"RJBB 050630Z VRB01KT 9999 FEW025 BKN/// 05/M07 Q1020 NOSIG"
,"RJBB 050600Z VRB02KT 9999 FEW025 BKN/// 05/M07 Q1020 NOSIG"
,"RJBB 050530Z VRB02KT 9999 FEW020 BKN/// 05/M08 Q1020 NOSIG"
,"RJBB 050500Z 33003KT 260V070 9999 FEW020 SCT150 BKN/// 05/M08 Q1020 BECMG 28005KT"
,"RJBB 050430Z 35005KT 300V060 9999 FEW020 SCT160 BKN/// 05/M07 Q1020 BECMG 28005KT"
,"RJBB 050400Z 01004KT 330V060 9999 FEW020 SCT160 BKN/// 05/M08 Q1020 BECMG 28005KT"
,"RJBB 050330Z VRB02KT 9999 FEW020 SCT160 BKN/// 05/M08 Q1021 BECMG 28005KT"
,"RJBB 050300Z VRB02KT 9999 FEW020 SCT160 BKN/// 05/M08 Q1021 BECMG 28005KT"
,"RJBB 050230Z VRB02KT 9999 FEW020 SCT160 BKN/// 05/M08 Q1022 NOSIG"
,"RJAH 050800Z 05003KT 9999 FEW030 BKN040 BKN/// 02/M04 Q1018"
,"RJAH 050700Z 05005KT 9999 FEW030 BKN050 BKN210 04/M04 Q1018"
,"RJAH 050600Z 06005KT 9999 FEW030 BKN060 BKN240 05/M04 Q1018"
,"RJAH 050500Z 03004KT 350V070 9999 FEW030 BKN070 BKN240 05/M06 Q1018"
,"RJAH 050400Z 06004KT 020V110 9999 FEW030 BKN060 BKN240 05/M07 Q1019"
,"RJAH 050342Z 06005KT 020V100 9999 FEW030 BKN050 BKN240 05/M07 Q1019 RMK 1CU030 5SC050 A3011"
,"RJAH 050300Z 01005KT 320V070 9999 FEW030 SCT050 BKN240 04/M08 Q1020"
,"RJCC 050800Z 14004KT 9999 FEW030 M03/M10 Q1015 RMK 1CU030 A2998"
,"RJCC 050730Z 14004KT 9999 FEW030 M04/M10 Q1015 RMK 1CU030 A2999"
,"RJCC 050700Z 15005KT 120V180 9999 FEW030 M02/M11 Q1015 RMK 1CU030 A2999"
,"RJCC 050630Z 19008KT 9999 FEW030 SCT050 M03/M10 Q1016 RMK 1CU030 3CU050 A3000"
,"RJCC 050600Z 11008KT 9999 FEW030 M02/M10 Q1016 RMK 2CU030 A3000"
,"RJCC 050530Z 14009KT 9999 FEW030 M03/M10 Q1016 RMK 2CU030 A3000"
,"RJCC 050500Z 13009KT 9999 FEW030 M03/M10 Q1016 RMK 2CU030 A3001"
,"RJCC 050430Z 13008KT 9999 FEW030 M03/M10 Q1016 RMK 2CU030 A3002"
,"RJCC 050400Z 15007KT 9999 FEW030 M03/M10 Q1016 RMK 1CU030 A3002"
,"RJCC 050330Z 14009KT 9999 FEW030 M03/M11 Q1017 RMK 1CU030 A3004"
,"RJCC 050300Z 13009KT 9999 FEW030 SCT040 M04/M11 Q1017 RMK 1CU030 3CU040 A3005"
,"RJCC 050230Z 14008KT 9999 FEW030 M05/M12 Q1018 RMK 1CU030 A3007"
,"RJGG 050800Z 04004KT 350V080 9999 FEW030 04/M04 Q1019 NOSIG"
,"RJGG 050730Z 02006KT 9999 FEW030 04/M04 Q1020 NOSIG"
,"RJGG 050700Z 36007KT 9999 FEW030 SCT/// 05/M05 Q1019 NOSIG"
,"RJGG 050630Z 01007KT 9999 FEW030 BKN/// 05/M04 Q1019 NOSIG"
,"RJGG 050600Z 35006KT 320V030 9999 FEW030 BKN/// 05/M04 Q1019 NOSIG"
,"RJGG 050530Z 34006KT 9999 FEW030 BKN/// 05/M04 Q1019 NOSIG"
,"RJGG 050500Z 32006KT 9999 FEW030 BKN/// 05/M03 Q1019 NOSIG"
,"RJGG 050430Z 33005KT 290V010 9999 FEW030 BKN/// 04/M05 Q1019 NOSIG"
,"RJGG 050400Z 34007KT 9999 FEW030 BKN/// 04/M04 Q1020 NOSIG"
,"RJGG 050330Z 33008KT 9999 FEW030 SCT150 BKN/// 04/M03 Q1020 NOSIG"
,"RJGG 050300Z 34007KT 9999 FEW030 SCT160 BKN/// 04/M04 Q1021 NOSIG"
,"RJGG 050230Z 36006KT 330V030 9999 FEW030 SCT160 BKN/// 03/M04 Q1021 NOSIG"
)
val parser = new MetarParser
bulletin.map(parser.parse(_)).foreach(println(_))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment