ããŒã4.å³ããçŸå®Parboiledãããã«é«éã«åäœãããæ¹æ³ã¯ïŒ ã©ã®ãããªééããé¿ããã®ãæåã§ããïŒ Parboiled1ã®åœ¢åŒã®ç¶æ¿ãã©ãããŸããïŒ ã·ãªãŒãºã®æçµèšäºã§ã¯ããããã®è³ªåããã®ä»ã®è³ªåã«çããããæ±ããããŠããŸãã
ãµã€ã¯ã«æ§é ïŒæ§èœ
Parboiled2ã¯é«éã§ãããå Žåã«ãã£ãŠã¯ããã«é«éã«å®è¡ãããããšããããŸãã ãã®ã»ã¯ã·ã§ã³ã§ã¯ãå©çšå¯èœãªãã€ã¯ãæé©åã«ã€ããŠèª¬æããŸãã æé©åãå®è¡ããéã®äž»ãªãã®ã¯ã驿æ§ã§ãã ãããã衚çŸåã倱ãããšãªããããå°ãæé©ãªã³ãŒããããã«äœæã§ããå Žåã¯ããã®æ©äŒãå¿
ã䜿çšããå¿
èŠããããŸãã
å°ããn <= 4ã®n.times
ãn.times
ããŸã
å°ãã
nã«å¯ŸããŠãæŒç®å
nåãç¹°ãè¿ã代ããã«ãããã€ãã®ç¹°ãè¿ãã«ãŒã«ãåçŽã«é£éã
n.times
ããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸãã å±éããã®ãçã«ããªã£ãŠããç¹°ãè¿ãã®æ°-ç¶æ³ã«ãã£ãŠç°ãªããŸããããã®æ°ã¯4ãè¶
ããããšã¯ã»ãšãã©ãããŸããã
ãã®æé©åã®é¢é£æ§ã¯ãMatthiasèªèº«ã«ãã£ãŠ
çºè¡šãããŸããããä»®ã«ã
n.times
æŒç®åã¯ãããèªåã§å®è¡ã§ããå¯èœæ§ããããŸãã
n.times
ã¹ã¿ãã¯æäœã®n.times
åæ§ã®ææ³ã䜿çšãããšãå€ã¹ã¿ãã¯ããããŒã¿ãæœåºãããšãã«ããã©ãŒãã³ã¹ãå°ãçµãããšãã§ããŸãã ããšãã°ãåã®ã«ãŒã«ã«é©çšã§ããŸãïŒ
def Digit4 = rule { Digit ~ Digit ~ Digit ~ Digit ~ push( #(charAt(-4))*1000 + #(charAt(-3))*100 + #(charAt(-2))*10 + #(lastChar) ) }
CharPredicate
åäœæããªãã§ãã ãã
CharPredicate
ã¯ã©ã¹ã®æ°ããæ©èœã楜ããã®ã¯ãŸã£ããæ®éã®ããšã§ããã
rule
ãããã¯å
ã«
CharPredicate
åã®ç¬èªã®ã€ã³ã¹ã¿ã³ã¹ãäœæããªãã§ãã ãããã«ãŒã«ãå®è¡ããããã³ã«è¿°èªãåäœæãããããŒãµãŒã®ããã©ãŒãã³ã¹ãåçã«äœäžããŸãã ãããã£ãŠãæ¯åã·ã³ããªãã¯è¿°èªãäœæãã代ããã«ãããŒãµãŒå
ã§ãããã宿°ãšããŠå®çŸ©ããŸãã
class MyParser(val input: ParserInput) extends Parser { val Uppercase = CharPredicate.from(_.isUpper) ... }
ãŸãã¯ãããã«è¯ãããšã«ããã®å®£èšãããŒãµãŒã®ã³ã³ãããªã³ãªããžã§ã¯ãã«éä¿¡ããŸãã
class MyParser(val input: ParserInput) extends Parser { ... } object MyParser { val Uppercase = CharPredicate.from(_.isUpper) }
ã»ãã³ãã£ãã¯è¿°èªã䜿çšãã
ãããã®ã«ãŒã«ã®ç¹åŸŽã¯ãå€ã¹ã¿ãã¯ãšçžäºäœçšããªãããšã§ãã 詳现ã«ã€ããŠã¯ãããã¥ã¡ã³ãã«èšèŒãããŠããŸããããããã«ã€ããŠç¥ã£ãŠããã¹ãæãéèŠãªããšã¯æ¬¡ã®ãšããã§ãã
ã»ãã³ãã£ãã¯è¿°èªã䜿çšããå ŽåãããŒãµãŒã¯é²è¡ããŸãããã€ãŸããã«ãŒãœã«ãæ¬¡ã®æåã«ç§»åããŸããã ãããã£ãŠãããããç¡æèã«äœ¿çšããããšãããŒãµãŒã¯ã«ãŒãããå¯èœæ§ããããŸãã
倧æåã®æåè¿°èªå®£èšãèŠããŠããŸããïŒ ã»ãã³ãã£ãã¯è¿°èª
test
ã䜿çšããŠåãããšãè¡ãããšãã§ããŸãã
def JavaUpperCase = rule { oneOrMore(test(currentChar.isUpper) ~ ANY) }
CharPredicate.All
ã衚瀺ããCharPredicate.All
å Žæã䜿çšããŸã
æ²ããããªã
CharPredicate.All
ã¯å€§ããªæåç¯å²ã«å¯ŸããŠã¯é
ãã
CharPredicate.All
ãé«éã§ãã ãã®ç¥èãæŽ»çšããŠãã ããã
éè¿°èªã䜿çšãã
ããŒãµãŒãæ¹è¡ã®åã«ãã¹ãŠã®æåããã£ããã£ããããšãæ³åããŠãã ããïŒæç¢ºã«ããããã«ãUnixã¹ã¿ã€ã«ã§ïŒã ãã¡ãããããã¯
noneOf
ã§å®è¡ã§ããŸãããéè¿°èªã¯ããé«éã«ãªããŸãã
def foo = rule { capture(zeroOrMore(noneOf("\n"))) }
æ®å¿µãªããããã®èŠæ ãã®è¯ãäŸã¯ã«ãŒãããŸããããŒãµãŒã¯é²è¡ããªãããã§ãã ãããä¿®æ£ããã«ã¯ãããŒãµãŒã«ãŒãœã«ãç§»åããããã¹ã¿ãã¯ã¯å€æŽããªãã«ãŒã«ãå¿
èŠã§ãã ããšãã°ãããã¯æ¬¡ã®ãšããã§ãã
def foo = rule { capture(zeroOrMore( !'\n' ~ ANY )) }
foo
ã«ãŒã«ã¯ã
EOI
ãšæ¹è¡ãé€ããã¹ãŠãå®å
šã«åžåããŸãã
ãã°ã¬ããŒã
ç¡å¹ãªå
¥åã«å¯ŸããŠæå³ã®ãªãã¡ãã»ãŒãžãçæããããŒãµãŒã䜿çšããããšã¯æããªãã§ãããã Parboiled2ã䜿çšãããšããšã©ãŒã«ã€ããŠéåžžã«æç¢ºã«äŒããããšãã§ããŸãã
æžåŒèšå®
ãããã£ãŠãäœãã
ParseError
ã«ãªã£ãå ŽåãããŒãµãŒã¯ãã¿ã€ã
ParseError
ãªããžã§ã¯ããèªç±ã«æž¡ããŸãããã®ãªããžã§ã¯ãã¯ã
formatError
ã¡ãœããã䜿çšããŠèªã¿åãå¯èœãªåœ¢åŒã«ã§ããŸãã
val errorMessage = parser formatError error
äœããã®çç±ã§ããã©ã«ãã®æžåŒèšå®ãããªãã«åããªãå Žåã¯ãæç€ºçã«ããŒãµãŒã«åžæãæž¡ãå¿
èŠããããŸãã
val errorMessage parser.formatError(error, new ErrorFormatter(showTraces = true))
ErrorFormatter
ãèšè¿°ãããå Žåã
ParseError
ã¯ã©ã¹ã®æ§é ã
ParseError
ã§åŠçãã
ParseError
ããã
ParseError
ãããã¯ããã®æ¹æ³ã§Parboiledã®äžéšã§å®£èšãããŸãã
case class ParseError(position: Position, charCount: Int, traces: Seq[RuleTrace]) extends RuntimeException
ãŸãããšã©ãŒã¡ãã»ãŒãžããŠãŒã¶ãŒã«é
ä¿¡ããããã®ããã€ãã®ã¹ããŒã ã®ååšã«æ³šç®ãã䟡å€ããããŸãããªã¯ãšã¹ãã§ã¯ã
ParseError
ã¯ã
Try
ãªããžã§ã¯ããšããŠã ãã§ãªããããšãã°ãããªã¢ãŒãã£ãã¯åãŸãã¯
ParseError
ãšããŠè¡šãããšãã§ããŸãã 詳现ã¯
ãã¡ããã芧ãã ãã ã
def Foo = rule { "foo" | fail(" !") }
埮調æŽ
çµã¿èŸŒã¿ã®ãšã©ãŒå ±åã¡ã«ããºã ãåé¿ãããªãã·ã§ã³ããããŸãã ãããè¡ãã«ã¯ããšã©ãŒã®å Žåã«è¡šç€ºããã¡ãã»ãŒãžã§
fail
ã«ãŒã«ã䜿çšããŸãã
def Goldfinger = rule { "talk" | fail("to die") }
ãã®åŸãæ©äŒãçãããšãããããæ¬¡ã®åœ¢åŒã§ãšã©ãŒã¡ãã»ãŒãžãè¿ãããŸãã
Invalid input 'Bond', expected to die. (line 1, column 1):
ååä»ãã«ãŒã«
ãã®ã¿ã€ãã®ã«ãŒã«ã®äœ¿çšã¯ããšã©ãŒããã£ããããããã ãã§ãªããéåžžã«äŸ¿å©ã§ãã ãã®ã¡ã«ããºã ã«ã€ããŠã¯ãããã¹ããã©ã¯ãã£ã¹ãã»ã¯ã·ã§ã³ã§è©³ãã説æããŠããŸãã
ã¢ãããã¯
Parboiled2ã¯ãPEGããŒã¹ã®ããŒãµãŒãçæããŸãã ããã¯ãããŒãµãŒãæååã§ã¯ãªãæååã§åäœããããšãæå³ããŸãïŒå€ãã®äººãèããããã«ïŒããããã£ãŠãæåã¬ãã«ã§ãšã©ãŒã衚瀺ãããŸãã åæããŸã-ãããã«XããããYãŸãã¯Zãäºæ³ãããŸããããªã©ã®ã¡ãã»ãŒãžã¯ããããã«XXããããXYãŸãã¯XZã衚瀺ããããšäºæ³ãããŸãããããã粟ç¥çãªåªåãå¿
èŠã§ãã ãšã©ãŒã¬ããŒãã®è¡å
šäœã衚瀺ããã«ã¯ã
atomi
ããŒã«ãŒããããã«ãŒã«ããã®äžã«ã©ããããŸãã
def AtomicRuleTest = rule { atomic("foo") | atomic("fob") | atomic("bar") }
å
¥ãå£ã§
foxes
ããã«
Invalid input "fox", expected "foo", "fob" or "bar" (line 1, column 1): foxes ^
éããª
éžæè¢ãå€ãããå Žåãèãããããã¹ãŠã®éžæè¢ããŠãŒã¶ãŒã«åžžã«éç¥ããå¿
èŠã¯ãããŸããã ããšãã°ãç¹å®ã®å Žæã§ã¯ãããŒãµãŒã¯ç¹å®ã®ã«ãŒã«ã«é¢é£ããŠå€ãã®ç©ºçœãäºæããŸãã ã¬ããŒãã®åé·æ§ãæé€ããããã«ãã¹ããŒã¹ã«ã€ããŠé»ã£ãŠããããšãã§ããŸãã
quiet
ããŒã¯ã³ã®äœ¿çšã¯éåžžã«ç°¡åã§ãã
def OptionalWhitespaces = rule { quiet(zeroOrMore(anyOf(" \t\n"))) }
æ£çŽãªãšãããç§ã¯ãã®ã«ãŒã«ã®äœ¿çšã奚å±ããç¶æ³ã«ééããããšã¯ãããŸããã
atomic
ãã
ã«ãããã¥ã¡ã³ãã§è©³çްã«èª¬æã
ããŠããŸã ã
ãšã©ãŒå埩
Parboiled1ãåã€ã»ãšãã©å¯äžã®ãšããœãŒããParboiled2ã¯ããŸãããŸããã£ãŠããŸããïŒããŒãµãŒã¯ãæåã«ééãããšã©ãŒã®ç®ããã®ã¿ããããããŸãã ã»ãšãã©ã®ã·ããªãªã§ã¯ãããã¯çŽ æŽãããã§ããããšãã°ããã°ã®è§£æãããã¹ããããã³ã«ãæ§æãã¡ã€ã«ïŒå€ãã®å ŽåïŒã«å¹²æžããŸããããDSLãIDEã®ãããªããŒã«ã®éçºè
ã¯ãã®ç¶æ³ã奜ãŸãªãã§ãããã
Matiasã¯ãã
ãä¿®æ£ããããšãçŽæããŠããããã仿¥ãã®æ©èœãæ¬åœã«å¿
èŠãªå Žåã¯ããã°ãã©ãã«ãŒã«æžã蟌ãã§ãã ãããéçºããã»ã¹ãã¹ããŒãã¢ããããå¯èœæ§ããããŸãã
Parboiled1ã«ã¯ãããããå Žé¢
ã«å¯Ÿå¿ãã
èšå€§ãªæ°ã®ParserRunnerããããŸãã ãšã©ãŒãçºçããå Žåã«è§£æãç¶è¡ããå¿
èŠãããå Žåã¯ã
RecoveringParserRunner
ãŠãã ããã
ãã¹ãäž
è€éãªéçºè
ã¯ããã¹ãã«specs2ãã¬ãŒã ã¯ãŒã¯ã䜿çšãããã«ããŒã¯ã©ã¹
TestParserSpecã§è£è¶³ããŸãã scalatestã䜿çšãã人ã«ãšã£ãŠã¯äžäŸ¿ã«æããŸããããã®åºæ¬çãªèãæ¹ã¯æ¡çšã§ããŸãã ããã£ã¢ã¹ããã®ç§å¯ã§ãåœŒã®æ±ºå®ã¯ãå¯å€ç¶æ
ã«äŸåããŠãããããç¹ã«æ£ç¢ºã§ã¯ãããŸããã ããããå°æ¥çã«ã¯ããã¹ãçšã®æ¬æ Œçãªãã¬ãŒã ã¯ãŒã¯ã«äŒŒããã®ãæåŸ
ããã§ãããã
ã«ãŒã«ã¯ãåå¥ã«ãã¹ãããããšãäžç·ã«ãã¹ãããããšãã§ããŸãã å人çã«ãç§ã¯åã«ãŒã«ã§ã¯ãªããã¹ããæžãããšã奜ã¿ãŸããããç¹å¥ãªãã±ãŒã¹ã§ã®ã¿ã¡ã€ã³ã«ãŒã«ããã§ãã¯ããŸãïŒ
å€ãã®åœ¢åŒãæšæºåããããã®ã§ãããéåžžã«è峿·±ãç¹ãèŠã€ããããšãã§ããŸãã ããšãã°ãBSDã®ãããªRFC 3164ã¡ãã»ãŒãžåœ¢åŒã§ã¯ãæ°åèªäœã«1ããããããå Žåã§ãã åžžã« 2ã€ã®äœçœ®ãæã®æ¥ä»ã«å²ãåœãŠãããŸãã RFCèªäœããã®äŸã次ã«ç€ºããŸãã
æã®æ¥ã10æªæºã®å Žåã¯ãã¹ããŒã¹ãšæ°åã§è¡šãå¿
èŠããããŸãã ããšãã°ã8æ7æ¥ã¯"Aug 7"
ãšããŠè¡šããã "g"
ãš"7"
éã«2ã€ã®ã¹ããŒã¹ããããŸãã
ãã®çš®ã®ãè峿·±ãç¹ãã«å ããŠãããŒãµãŒæååã«éãæ¬åŒ§ãç¡å¹ãªæåãå
¥åããå€ã¹ã¿ãã¯ã§æäœã®é åºã確èªã§ããŸãã
ãã¹ãã§ã¯ãããã«ééããå¥ã®åŸ®åŠãªç¹ããããŸãã æ¬¡ã®ã«ãŒã«ããã¹ããããšããŸãã
def Decimal: Rule0 = rule { ("+" | "-").? ~ Digit.+ ~ "." ~ Digit.+ }
ãããè¡ãã«ã¯ãæããã«ééã£ãå
¥åãããŒãµãŒã«éä¿¡ããåºåã§ãšã©ãŒãåŸ
ã¡ãŸãã
ãããããã¹ããå®è¡ãããšãããŒãµãŒãæåããçµæãè¿ããããšãããããŸãã ãªããã ã«ãŒã«ã«ã¯
EOI
ã¯ãããŸãããã
EOI
ã远å ãããšã
Decimal
ã䜿çšãããã¹ãŠã®ã«ãŒã«ãå°ç¡ãã«ãªããŸãã ãããã£ãŠãããšãã°ãunningãª
ã¡ã¿ã«ãŒã«ã¡ã«ããºã ã䜿çšããŠãç¹å¥ãªãã¹ãã«ãŒã«ãäœæããå¿
èŠããããŸãã åã®äŸã®æåŸã«EOIã远å ããããŒãµãŒããšã©ãŒã§ã¯ã©ãã·ã¥ããããšã確èªããŸãããã
Failure(ParseError(Position(5,1,6), Position(5,1,6), <2 traces>))
ããŒãã€ã«ãã®æ¬ ç¹
ããŒãã€ã«ã2
人ã
ã«æ¬ é¥ããããªãããªãã©ã€ãã©ãªãŒã«æ¬ é¥ããªãã®ã§ããïŒ ããã§ã¯ãParboiled2ãäŸå€ã§ã¯ãããŸããã
- C ++ã®æé«ã®äŒçµ±ã«ãããããšã©ãŒã«é¢ããé·ããããŸãã«ãäžè¬çã§å®å
šã«çè§£ã§ããªãã³ã³ãã€ã©ã¡ãã»ãŒãžã äžã®å³ã«é®®æãªäŸã瀺ããŸãïŒ
~
æŒç®åã¯èª€ã£ãŠã«ãŒã«ã§çç¥ãããŸããïŒã ãã®çç±ã¯ãå°æ¥ã®ããŒãžã§ã³ã§åé€ãããèŠèŸŒã¿ã®ããã¿ã€ãã§é«åºŠãªãã§ãã¯ãå®è¡ããããšã«é¢é£ããŠããŸãã

ã³ã³ãã€ã©ã¯æ±ãããšãèªããŸã
- ãã®åé¡ã¯Parboiled2ã§ã¯ãªããscalacã«é©çšãããŸãã ã¹ã¿ãã¯ããå€ãååŸããã©ã ãã«ãæç€ºçã«ïŒæªïŒå®çŸ©ãããåŒæ°ã®åãããå Žåãã³ã³ãã€ã©ãç Žå£ã§ããŸãã
åäœãããã®ãšåäœããªããã®ã¯ãã³ã³ãã€ã©ã®ããŒãžã§ã³ã«äŸåããŸãã
- å€ãã®IDEã¯ãŸã ãã¯ã衚çŸããµããŒãããæ¹æ³ãåŠãã§ããããParboiled2ã¯æ¯æŽãªãã§æ§ç¯ãããŸããã ãããã£ãŠãéçºç°å¢ã®äžç·ãä¿¡ããŠã¯ãªããŸããã äžåºŠããããå¿ããŠããŸã£ããããç§ã¯äžæ¥äžãæåéãçªç¶ååšããªããšã©ãŒãæ¢ããŠéãããŸããã
- 倱æããè§£æã®ããã®å埩ã¡ã«ããºã ã®æ¬ åŠã ãã¡ã€ã³åºæã®èšèªããŸãã¯Parboiled2ãã³ã³ãã€ã©ã®ããã³ããšã³ããšããŠäœ¿çšãããèšèªãèšèšããå Žåãããã¯éåžžã«å€±æããŸãã ãããã圌ãã¯ããã«åãçµãã§ããŸãã ãã®æ©äŒãèŠããå Žå-æžããŠãããã¯éçºãã¹ããŒãã¢ããããŸãã
- å°ããªIDEãããã¹ããšãã£ã¿ãŒã®éçºè
ã®å€ãã¯ãçŸåšæäŸãããŠãããšã©ãŒã¡ãã»ãŒãžãããæè»ãªãšã©ãŒã¡ãã»ãŒãžãèŠãããšæã£ãŠããŸãã çŸæç¹ã§ã¯ããããã«åœ±é¿ãäžããæ¹æ³ã¯2ã€ãããããŸããã
- ååä»ãèŠå
- ååä»ãã®ãã¹ããããã«ãŒã«ã
ãã§ã1
ã»ãšãã©ã®ãããžã§ã¯ãã¯ãŸã Parboiled1ã§èšè¿°ãããŠãããåçã«ïŒäŒæ¥å
ã§ïŒåçã«å€åããå¯èœæ§ã¯äœããããParboiled1ã«ã¯å€ãã®æ¬ ç¹ããããŸãã éåžžã«éãããDSLã«å ããŠãParboiledã«ã¯ãRule8ãã®åé¡ãããããã°ã®ããŒãµãŒã®äœæãè€éã«ãªããŸãã Parboiled1ã¯ãNåã®èŠçŽ ãæã€åã«ãŒã«ã«å¯ŸããŠãSkalovã¿ãã«ãšã®é¡æšã«ããã¯ã©ã¹ãååšããããã«æ§ç¯ãããŸãïŒ
Rule0
ã
Rule1
ã
Rule7
ã ããã¯ãJavaãªã©ã®è€éãªããã°ã©ãã³ã°èšèªãè§£æããã®ã«ååã§ãããå®éã«ããªãŒæ§é ãè§£æãããšãã«å€§ããªåé¡ãåŒãèµ·ããããšã¯ãããŸããã ãã ãããã°ãã¡ã€ã«ã¡ãã»ãŒãžãªã©ã®ç·åœ¢æ§é ããããŒã¿ãæœåºããå¿
èŠãããå Žåããã®å¶éã¯éåžžã«ç°¡åã«å®è¡ã§ããŸãã ããã¯ãåäžã®çµæã«ãŒã«ã®ä»£ããã«ã¿ãã«ã䜿çšããããšã§è§£æ±ºãããŸãã 以äžã«äŸã瀺ããŸãã
def Event: Rule1[LogEvent] = rule { Header ~ " " ~ UserData ~ " " ~ Message ~~> { (header, data, message) => SyslogEvent ( header._1, header._2, header._3, header._4, header._5, data._1, data._2, message ) } }
æšãã«èŠããããåé¡ã¯è§£æ±ºããŸããã
ãã¹ããã©ã¯ãã£ã¹
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãParboiled2ã«åºæã®ãã¥ã¢ã³ã¹ã ãã§ãªããããŒãµãŒã³ã³ãããŒã¿ãŒã§æ©èœããäžè¬çãªçå®ã«ã€ããŠèª¬æããŸãã
ã·ã£ã«ã«ãã£ã«ã¹
ããã¥ã¡ã³ãã«èšèŒãããŠããªã䟿å©ãªãªããžã§ã¯ãã1ã€ãããŸãïŒ
CharUtilsã§ãã ããã«ã¯ãããšãã°ãæåã®å€§æåå°æåã®å€æŽããšã¹ã±ãŒãã察å¿ããæåïŒæååïŒãžã®æŽæ°å€ã®å€æãªã©ãçæŽ»ã楜ã«ããéçã¡ãœããã倿°å«ãŸããŠããŸãã ãªã©ãããã䜿çšãããšãæéãç¯çŽã§ããŸãã
åäœãã¹ããæžã
1ã€ã®å°ããªã倱æãã倿Žã¯ãææ³ãç Žããæ¥æ§çŽè
žçãåŒãèµ·ããå¯èœæ§ããããŸãã ããã¯å€ãã®äººãç¡èŠããŠãããããµããã¢ããã€ã¹ã§ãã ããŒãµãŒã¯ãããšãã°IOã»ã©ãã¹ãããã®ã¯é£ãããããŸããããã®ã«ãŒãã³ã«ã¯Mockãªããžã§ã¯ãããã®ä»ã®ããªãã¯ã¯å¿
èŠãããŸããããéåžžã«äŸ¡å€ã®ããäœæ¥ã§ãã ããŒãµãŒã®ã€ã³ãã©ã¹ãã©ã¯ãã£å
šäœããããŸããã ãããŠç§ãä¿¡ããŠãã ããããšã©ãŒãæ¢ããšãã«æåã«ããããšã¯ããšã©ãŒããªããã°ã座ã£ãŠãã¹ããæžãããšã§ããã
ããŒãµãŒãšã«ãŒã«ãå°ãããã
ããŒãµãŒããµãããŒãµãŒã«åé¢ããŸãã åã³ã³ããŒãã³ãã¯ãéåžžã«å
·äœçãªããšãè¡ãå¿
èŠããããŸãã ããšãã°ãTimestampãã£ãŒã«ããå®çŸ©ãããŠããLogEventãè§£æããå ŽåïŒç¹ã«ãã®Timestampãäžéšã®Rfcã«å¯Ÿå¿ããå ŽåïŒãã¬ã€ãžãŒã«ãªããã«åå¥ã«åãåºããŸãã
- 第äžã«ãããã¯ããªãã®ã¡ã€ã³ã®ãã¬ã€ã€ãŒã®ã³ãŒããæžããããããããèŠãããããŸãã
- 第äºã«ããã¹ããéåžžã«å®¹æã«ãªããŸãã ãµãããŒãµãŒãåäœãã¹ãã§ã«ããŒããŸãã ãã®åŸãã¡ã€ã³ããŒãµãŒã®éçºãéå§ããŸã
ããŸããŸãªã¢ãããŒãããããŸãã
- ããŒãµãŒãç¹æ§ã«åå²ããèªå·±å
¥ååã®åç
§ã䜿çšããŸãïŒãã®æ¹æ³ã奜ãŸããã§ãïŒã
- ããŒãµãŒãåå¥ã®ãšã³ãã£ãã£ãšããŠå®£èšããæ§æã䜿çšããŸãã
- çµã¿èŸŒã¿ã®ã¡ã«ããºã ã䜿çšããŠããµãããŒãµãŒãäœæããŸãã
ã«ãŒã«ã¯å¯èœãªéãã³ã³ãã¯ãã«ããå¿
èŠããããŸãããã³ã³ãã¯ãã«ããããšã¯ã§ããŸããã ã«ãŒã«ãå°ããã»ã©ãææ³ã®ééããèŠã€ãããããªããŸãã éçºè
ãã«ãŒã«ãé·ãããåæã«
capture
åå©çš
capture
å Žåãéçºè
ã®ããžãã¯ãçè§£ããããšã¯éåžžã«å°é£ã§ãã æé»ã®ãã£ããã£ã¯ç¶æ³ãæªåãããå¯èœæ§ããããŸãã ã«ãŒã«ã®ã¿ã€ããæå®ããããšããµããŒãã«åœ¹ç«ã¡ãŸãã
å€ã¹ã¿ãã¯ã®æååã®ä»£ããã«ã±ãŒã¹ãªããžã§ã¯ããéä¿¡ãã
ãã®ã¢ããã€ã¹ã¯ãããŒãµãŒã®åäœãé«éåãããããæé©åã«èµ·å ããå¯èœæ§ããããŸãã æååã§ã¯ãªããæå³ã®ãããªããžã§ã¯ããValueã¹ã¿ãã¯ã«éä¿¡ããŸãã ããã«ãããããŒãµãŒãé«éã«ãªããã³ãŒããããæç¢ºã«ãªããŸãã
æªãïŒ
def logLevel = rule { capture("info" | "warning" | "error") ~ ':' }
è¯ãïŒ
def logLevel = rule { âinfo:â ~ push(LogLevel.Info) | âwarning" ~ push(LogLevel.Warning) | âerror" ~ push(LogLevel.Error) }
ç°¡çŽ åãããæ§æã䜿çšããŠãªããžã§ã¯ããçµã¿ç«ãŠãŸã
ãã®çŸããæ¹æ³ã¯ãParboiled1ã«ç»å ŽããŸããã éæ³ã§ã¯ãªããã±ãŒã¹ã¯ã©ã¹ã³ã³ã¹ãã©ã¯ã¿ãŒãæé»çã«åŒã³åºãããŸãã äž»ãªããšã¯ãå€ã¹ã¿ãã¯ã«é
眮ãããåŒæ°ã®æ°ãšã¿ã€ãããã±ãŒã¹ã¯ã©ã¹ã³ã³ã¹ãã©ã¯ã¿ãŒã®ã·ã°ããã£ãšäžèŽããããšã§ãã
æªãïŒ
def charsAST: Rule1[AST] = rule { capture(Characters) ~> ((s: String) => AText(s)) }
è¯ãïŒ
def charsAST = rule { capture(Characters) ~> AText }
ååä»ãã«ãŒã«
ååä»ãã«ãŒã«ã¯ãäžæçãªã«ãŒã«åã®ä»£ããã«ãšã€ãªã¢ã¹ã䜿çšã§ããããã«ããããããšã©ãŒã¬ããŒããåä¿¡ããéã®ç掻ã倧å¹
ã«ç°¡çŽ åããŸãã ãŸãã¯ãç¹å®ã®ã¿ã°ïŒããã®åŒããŸãã¯ãã¹ã¿ãã¯ã倿ŽãããïŒã§ã«ãŒã«ãããŒã¯ããŸãã ãããã«ããããã®æ©èœã«ã€ããŠç¥ã£ãŠãããšåœ¹ç«ã¡ãŸãã
å€ãã®Parboiled1ãŠãŒã¶ãŒã¯ãã§ã«ãã®æ©èœãæ°ã«å
¥ã£ãŠããŸãã ããšãã°ãPyboiledã䜿çšããŠCypherãè§£æããNeo4Jéçºè
ã
Parboiled1ã§ã®è¡šç€ºïŒ
def Header: Rule1[Header] = rule("I am header") { ... }
Parboiled2ã®å ŽåïŒ
def Header: Rule1[Header] = namedRule("header is here") { ... }
ãã¹ããããã«ãŒã«ã«ååãä»ããããšãã§ããŸãã
def UserName = rule { Prefix ~ oneOrMore(NameChar).named("username") ~ PostFix }
ç§»è¡
ã»ãšãã©ã®å Žåãç§»è¡ã¯åçŽãªããã»ã¹ã§ãããå€ãã®æéãããããŸãã ãããã£ãŠãå°ãªããšãããªãã®äººçã®è²Žéãªæéãç¯çŽããäž»ãªèœãšã穎ã説æããããšæããŸãã
ã¯ã©ã¹ãã¹
æåã®ããŒãžã§ã³ãšã®ç«¶åãé¿ããããã«ãParboiled2ã¯ã¯ã©ã¹ãã¹
org.parboiled2
䜿çšã
org.parboiled2
ïŒäžæ¹ã
org.parboiled2
ã®æåã®ããŒãžã§ã³ã®ã¯ã©ã¹ãã¹ïŒã ãã ãã
org.parboiled
ã¯å€ããŸãŸã§ãïŒ
org.parboiled
ã ãã®ããã1ã€ã®ãããžã§ã¯ãã«äž¡æ¹ã®äŸåé¢ä¿ãæãããæ°ããããŒãžã§ã³ãžã®æ®µéçãªç§»è¡ãå®è¡ã§ããŸãã ã¡ãªã¿ã«ãããã¯ããã€ãã®èªåŸåããŒãµãŒã§éåžžã«ããŸãæ©èœããŸãã ããŒãµãŒãããŸããŸãªå Žæã§åå©çšããã倿°ã®ã¢ãžã¥ãŒã«ã§æ§æãããŠããå ŽåïŒç§ã®å Žåã®ããã«ïŒ-ããã«ãã¹ãŠã®ã¢ãžã¥ãŒã«ã«å¯ŸããŠç§»è¡ãè¡ãå¿
èŠããããŸãã
ãã¹ãæ€èšŒ
åäœãã¹ãã®å¯çšæ§ãšããã©ãŒãã³ã¹ã確èªããŸãã ãããã¯ãããŸããïŒ ããïŒ ããããæžããŸãã ç§»è¡ããã»ã¹äžã«ãæ°ããDSLããã匷åã«ãªããäžæ³šæãªå€æŽãææ³ãå£ãããããããã€ãã®ææ³ãæ¹è¯ããå¿
èŠããããŸããã èœäžãã¹ãã¯å€ãã®æéãç¯çŽããŸããã ç§»è¡æã«ãææ³å
šäœãç Žããªã©ã®æ·±å»ãªåé¡ã¯çºçããŸããã§ããã ããã圌ã«èµ·ãã£ãå Žåã誰ãã圌ãã®çµéšãå
±æãããããããŸããã
ããŒãµãŒåšèŸºã®ã³ãŒã
ããã§ãããŒãµãŒã¯æ¯ååäœæãããŸãããããã¯å¿
ããã䟿å©ã§ã¯ãããŸããã PB1ã§ã¯ãããŒãµãŒãäžåºŠäœæããŠããç¹°ãè¿ã䜿çšããããšãæ¬åœã«å¥œãã§ããã ããã§ããã®çªå·ã¯æ©èœããªããªããŸãã ãããã£ãŠãããŒãµãŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã倿Žããããã䜿çšããŠã³ãŒããå°ãæžãæããå¿
èŠããããŸããããã«ããããã©ãŒãã³ã¹ãäœäžããããšãæããªãã§ãã ããã
èŠå Parboiled1ã䜿çšãããšãå®è¡æã«ã«ãŒã«ãçæã§ããŸãã ãããã£ãŠãåæ§ã®ããŒãµãŒã䜿çšããŠããå Žåã¯ãã»ãšãã©ã®å ŽåããããæžãçŽãå¿
èŠããããŸããParboiled2ã¯ããã€ããã¯ã¹ãéåžžã«é£ãããããã¯ãåŒã䜿çšãããããããã©ãŒãã³ã¹ãåäžããŸãã
æ§æ
ããŒãµãŒèŠçŽ ã®æ§æãžã®ã¢ãããŒãã¯å€æŽãããŠããŸãããããã¯ç§»æ°ã«ãšã£ãŠæå ±ã§ãã ãã ãã
Parser
ã¯ãã¯ãç¹æ§ã§ã¯ãªããæœè±¡ã¯ã©ã¹ã§ãã ãã¬ã€ãã¯ããœãããŠã§ã¢ã³ã³ããŒãã³ããæ§æããæã䟿å©ãªææ®µã§ãããPB1ã§ã¯ãããã«ãã
Parser
ãä»»æã®ã¢ãžã¥ãŒã«ã«æ··åããã¢ãžã¥ãŒã«ãäžç·ã«æ··åããããšãã§ããŸããã æœè±¡ã¯ã©ã¹ãæ¯æãã倿Žã¯ãã®æ©èœã«ã¯åœ±é¿ããŸããã§ãããã
èªå·±å
¥ååã®åç
§ã䜿çšããå¿
èŠããã
ãŸã ã
trait Numbers { this: Parser =>
èšèªã®ãã®æ©èœã䜿çšãããæ¯å
Parser
ç¹æ§ãæ··åãã人ã¯ã奜ã¿ã倿Žããå¿
èŠããããŸãã
å¥ã®æ¹æ³ãšããŠãç¹æ§ããå®å
šãªããŒãµãŒãäœæãããããããå¿
èŠãªã«ãŒã«ãïŒã¡ãœãããšããŠïŒã¡ã€ã³ããŒãµãŒã«ã€ã³ããŒãã§ããŸãã 確ãã«ãç§ã¯ããããããèŠèŠçã§ãããšæãã®ã§ãç§ã¯ãŸã ç¹æ§ã³ã³ããžã·ã§ã³ã䜿çšããããšã奜ã¿ãŸãã
ããªããã£ããåãé€ã
ç§»è¡ããã»ã¹äžã«ãããªããã£ãã«ãŒã«ã®å人ã©ã€ãã©ãªã®ç£æ»ãå¿
ãæé
ããŠãã ãã
CharPredicate
ãã®ããã¹ãŠåé€ããŠ
CharPredicate
ã ã©ã€ãã©ãªã®ééã¯æžããŸããããŸã£ããæ¶ããããšã¯ãããŸããã å€ãã®äººããããŸããŸãªæ¥ä»åœ¢åŒãé»åã¡ãŒã«ã説æããææ³ãããŒãã€ã«ãã®HTTPããããŒã®ãµããŒãã远å ããããšèããŠããŸãã Parboiledã¯ãåã«ããŒãµãŒã³ã³ãããŒã¿ãŒã§ãã ãã ããå€ãã³ãŒããæšãŠãããšã¯éåžžã«çŽ æŽãããããšã«åæããŸãã
ãããã«
ãã®äžé£ã®èšäºã§ã¯ãscalaèšèªã«ååšããæã鲿©çã§ææãªè§£æããŒã«ã«ã€ããŠèª¬æããããšããŸããã
çããã¥ãŒããªã¢ã«ãäœæããå®éã«çŽé¢ããªããã°ãªããªãåé¡ã«ã€ããŠè©±ããŸããããã®èšäºãææªã®å Žåã«åœ¹ç«ã€ããšãæã¿ãããããè¡åã®ã¬ã€ãã«ãªãããšãæã¿ãŸãã䜿çšããããœãŒã¹
è¬èŸ
ãã®èšäºã®çç±ãšäŸ¿å©ãªããŒã«ãæäŸããŠãããAlexanderãšMatthiasã«æè¬ããŸããã€ããç§ã®å€ãã®ééãã®æ ¡æ£ãšç·šéã«æè¬ããŸããç§ã¯ãã£ãšæèœã«æžãããšãçŽæããŸããfiregurafikuãšToo Tabooã«ãVertskã®æåã®èšäºãæ ¡æ£ã倿°ã®ä¿®æ£ãããã³åŸç¶ã®äŸã®ã¢ã€ãã¢ã®æ¯æŽã«æè¬ããŸããã·ãªãŒãºã®æåŸã®èšäºã®æ ¡æ£ãšèšæ£ãããŠãããVlad Ledovskyã«æè¬ããŸããããããšããããnehaevãäœåã«å·šå€§ãªåœ«åãïŒç§ã¯ãããè¡ãã«ã¯ããããªãã£ãïŒåå²ããã¢ã€ãã¢ã®ã³ãŒããšã©ãŒã§èŠã€ãã£ãèšäºã®ããã«ããšã€ãŽãŒã«KustovãçºèŠãããäžæ£ç¢ºããšã¢ãŒã»ããŒã»ã¢ã¬ãµã³ãããŽã£ããã®ãã©ã€ã ããŒã¯ã«æè¬ããŸãã圹ã«ç«ã€ææ¡ãèšäºã®ãµã€ã¯ã«ã«åŸã£ãŠæåŸã«å°éãããã¹ãŠã®äººã
ã«æè¬ããŸããä»äºãç¡é§ã«çµãã£ãŠããªãããšãé¡ã£ãŠããŸãã