$TestsOnly$ define TestData { @value String name @value String description @value Bool boolean create (name,description,boolean) { return TestData{ name, description, boolean } } getName () { return name } getDescription () { return description } getBoolean () { return boolean } } define TestDataParser { // Mark @category members as read-only, to avoid accidental assignment. $ReadOnly[sentenceOrToken, acronymOrAardvark, fileStart, fileEnd, nameTag, descriptionTag, aWordTag]$ // Mark @category members as hidden, since they should not be used directly. $Hidden[whitespace, sentenceChars, sentence, quote, quotedSentence, token, acronym, aardvark]$ 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{ } } }