diff options
Diffstat (limited to 'quizdata/_format_gift.py')
-rw-r--r-- | quizdata/_format_gift.py | 92 |
1 files changed, 65 insertions, 27 deletions
diff --git a/quizdata/_format_gift.py b/quizdata/_format_gift.py index b88e51c..437bf16 100644 --- a/quizdata/_format_gift.py +++ b/quizdata/_format_gift.py @@ -2,42 +2,80 @@ Parsing and support functions for the Moodle GIFT format. ''' from pyparsing import (Word, Literal, Optional, Group, OneOrMore, - ParseException, Combine, restOfLine, printables, - nums) + ParseException, Combine, restOfLine, + nums, StringEnd, ZeroOrMore, oneOf, + originalTextFor, CharsNotIn, NotAny, + ParserElement, printables, White, + FollowedBy) -_special_chars = set(":/=~#{}->") -_filt_printables = ''.join([ p for p in printables if p not in _special_chars ]) +__all__ = [ 'parse', 'question', 'questions' ] -_text = OneOrMore(Word(_filt_printables)) -_number = Combine(Word(nums) + Optional("." + Optional(Word(nums)))) +ParserElement.enablePackrat() +#ParserElement.setDefaultWhitespaceChars(" \t") -_comment = Literal("//") + restOfLine -_dcolon = Literal("::") -_qtitle = _dcolon + _text + _dcolon +comment = Literal("//") + restOfLine +NL = Literal("\n").suppress() -_correct_ans = Literal("=") + _text -_wrong_ans = Literal("~") + _text -_ans_explain = Literal("#") + _text -_ans_tf = Literal("TRUE") | Literal("FALSE") | Literal("T") | Literal("F") -_ans_match = Literal("=") + _text + Literal("->") + _text +def kill_whitespace(s, l, t): + #print t.asList()[1:-1] + return [ ' '.join(t.asList()[1:-1]).strip() ] -_ans_numeric = (Optional(Literal("=")) - + (_number + Optional( Literal(":") + _number) - |_number + Literal("..") + _number) - + Optional( _ans_explain )) +def printables_except(chars): + l = list(printables) + for c in chars: + l.remove(c) + return ''.join(l) -_answer = ( (( _correct_ans | _wrong_ans ) + Optional(_ans_explain)) - | _ans_tf | _ans_match ) +def restricted_text(allowed_chars): + return originalTextFor( + Optional(NL) + + OneOrMore((Word(allowed_chars) + + Optional(NL))) + ).setParseAction( kill_whitespace ) -question = (Optional(_qtitle) + _text - + ("{" + OneOrMore(_answer) + "}" | - "{#" + OneOrMore(_ans_numeric) + "}")) -question.ignore(_comment) +text = restricted_text(printables) +qtext = restricted_text(printables_except("{")) +ans_text = restricted_text(printables_except("=~#}->")) +after_text = text + FollowedBy(NL+NL) +title_text = restricted_text(printables_except(":")) -questions = OneOrMore(question + Literal("\n\n")) -questions.ignore(_comment) +number = Combine(Word(nums) + Optional("." + Optional(Word(nums)))) +dcolon = Literal("::") +qtitle = dcolon.suppress() + title_text + dcolon.suppress() -def _parse_only(text): +correct_ans = (Literal("=") + ans_text) +wrong_ans = Literal("~") + ans_text +ans_explain = Literal("#") + ans_text +ans_tf = oneOf("T F TRUE FALSE") +ans_match = Literal("=") + ans_text + Literal("->") + ans_text + +ans_numeric = Group(Optional(Literal("=")) + + (number + Optional( Literal(":") + number) + ^number + Literal("..") + number) + + Optional( ans_explain )) + +answer = Group(( ( correct_ans ^ wrong_ans ^ ans_tf) + Optional(ans_explain)) + ^ ans_match ) + +answer_list = ((Literal("{").suppress() + + OneOrMore(answer) + + Literal("}").suppress()) + ^ + (Literal("{#").suppress() + + OneOrMore(ans_numeric) + + Literal("}").suppress())) + +question = ZeroOrMore(NL) + Group( Optional(qtitle)("title") + + qtext("text") + + answer_list("answers") + + Optional(after_text)("text_additional") ) + +question.ignore(comment) + +questions = (question + ZeroOrMore(NL + NL + question))("questions") + StringEnd() +questions.ignore(comment) + +def parse_only(text): return questions.parseText(text) def parse(text): |