$TestsOnly$ define TestData { @value String name @value String description @value Bool boolean parseFrom (data) { return TestDataParser$create() `ParseState$$consumeAll` data } create (name,description,boolean) { return TestData{ name, description, boolean } } getName () { return name } getDescription () { return description } getBoolean () { return boolean } } concrete TestDataParser { @type create () -> (Parser) } define TestDataParser { refines Parser @category Parser whitespace <- SequenceOfParser$create(" \n\t",1,0) `Parse$or` Parse$error("Expected whitespace") @category String sentenceChars <- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "., !?-" @category Parser sentence <- SequenceOfParser$create(sentenceChars,0,0) @category Parser quote <- CharParser$create('"') @category Parser quotedSentence <- quote `Parse$right` sentence `Parse$left` quote @category Parser token <- SequenceOfParser$create("ABCDEFGHIJKLMNOPQRSTUVWXYZ_",1,0) @category Parser sentenceOrToken <- quotedSentence `Parse$or` token `Parse$left` whitespace @category Parser acronym <- StringParser$create("acronym") `Parse$right` Parse$const(true) @category Parser aardvark <- StringParser$create("aardvark") `Parse$right` Parse$const(false) @category Parser acronymOrAardvark <- Parse$try(acronym) `Parse$or` aardvark `Parse$left` whitespace @category Parser fileStart <- StringParser$create("file_start") `Parse$left` whitespace @category Parser fileEnd <- StringParser$create("file_end") `Parse$left` whitespace @category Parser nameTag <- StringParser$create("name:") `Parse$left` whitespace @category Parser descriptionTag <- StringParser$create("description:") `Parse$left` whitespace @category Parser aWordTag <- StringParser$create("a_word:") `Parse$left` whitespace run (contextOld) { ParseContext context <- contextOld context <- context.run(fileStart) context <- context.run(nameTag) context, ErrorOr name <- context.runAndGet(sentenceOrToken) context <- context.run(descriptionTag) context, ErrorOr description <- context.runAndGet(sentenceOrToken) context <- context.run(aWordTag) context, ErrorOr boolean <- context.runAndGet(acronymOrAardvark) context <- context.run(fileEnd) if (context.hasAnyError()) { return context.convertError() } else { return context.setValue( ErrorOr$$value(TestData$create(name.getValue(), description.getValue(), boolean.getValue()))) } } create () { return TestDataParser{ } } }