def number(): whitespace() lead = u''.join(many1(digit)) commit() if optional(p(one_of, '.')): trail = u''.join(many1(digit)) return ('float', float(lead + '.' + trail)) else: return ('int', int(lead))
def identifier(first=partial(one_of, ascii_letters), consecutive=partial(one_of, ascii_letters + digit_chars + '_'), must_contain=set(digit_chars)): """Expects a letter followed by one or more alphanumerical characters. If ``must_contain`` is given, the following letters must include one from this set. The default option is to expect a letter followed by a number of letters and digits, but with a requirement of at least one digit (this allows an easy distinction between names and identifiers). >>> parse(identifier, 'abc123') 'abc123' >>> parse(identifier, 'abc') # doctest: +ELLIPSIS Traceback (most recent call last): ... NoMatch: ... >>> parse(partial(identifier, must_contain=None), 'abc') 'abc' """ result = [] if first is not None: result.append(first()) if must_contain is None: chars = many(consecutive) else: chars = many1(partial(choice, consecutive, partial(one_of, must_contain))) if not set(chars) & must_contain: fail() result.extend(chars) return result
def string_literal(): whitespace() quote = one_of('\'"') commit() st = u''.join(many1(p(string_char, quote))) one_of(quote) return ('str', st)
def tag(): """Parse a single tag, optionally prefixed by a hash mark (``'#'``). """ optional(hash, None) return many1(partial(one_of, ascii_letters))
def parse(cls): result = {} try: result['name'] = pico.name() except: raise FormatError( "Expected name (got: %s)." % "".join(remaining())) try: many1(partial(one_of, ' ,;')) result['sex'] = pico.one_of_strings( 'male', 'female', 'm', 'f')[0].upper() except: raise FormatError( "Expected the infant's gender " "(\"male\", \"female\", or simply \"m\" or \"f\"), " "but received instead: %s." % "".join(remaining())) try: many1(partial(one_of, ' ,;')) words = pico.name().lower() except: raise FormatError( "Expected a location; " "either \"home\", \"clinic\" or \"facility\" " "(got: %s)." % "".join(remaining())) for word in words.split(): matches = difflib.get_close_matches( word, ('home', 'clinic', 'facility')) if matches: result['place'] = matches[0].upper() break else: raise FormatError( "Did not understand the location: %s." % words) return result
def parse(cls): result = {} try: identifiers = optional(tri(pico.ids), None) if identifiers: result['ids'] = [id.upper() for id in identifiers] else: result['name'] = pico.name() except: raise FormatError( "Expected a name, or a patient's health or tracking ID " "(got: %s)." % "".join(remaining())) if 'name' in result: try: many1(partial(one_of, ' ,;')) result['sex'] = pico.one_of_strings( 'male', 'female', 'm', 'f')[0].upper() except: raise FormatError( "Expected the infant's gender " "(\"male\", \"female\", or simply \"m\" or \"f\"), " "but received instead: %s." % "".join(remaining())) try: pico.separator() except: raise FormatError("Expected age or birthdate of patient.") try: result['age'] = choice(*map(tri, (pico.date, pico.timedelta))) except: raise FormatError("Expected age or birthdate of patient, but " "received %s." % "".join(remaining())) return result
def dec_entity(): return unichr(int(build_string(many1(decimal_digit)), 10))
def operator(): whitespace() not_followed_by(p(choice, *[p(reserved_op, op) for op in reserved_operators])) name = u''.join(many1(operator_char)) return ('op', name)
def ident(): whitespace1() pico.hash() commit() return many1(any_token)
def number(): whitespace1() return many1(partial(one_of, string.digits + ' -+()'))
def fn_expression(): reserved('fn') params = many1(identifier) reserved_op('->') expr = expression() return ('fn', params, expr)
def name(): whitespace1() result['name'] = "".join(many1(partial(not_one_of, ',')))
def named_entity(): name = build_string(many1(partial(not_one_of,';#'))) if name not in named_entities: fail() return named_entities[name]
def ident(): pico.hash() commit() return many1(any_token)
def named_entity(): name = build_string(many1(partial(not_one_of, ";#"))) if name not in named_entities: fail() return named_entities[name]
def text_node(): return "TEXT", build_string(many1(xml_char))
def version_num(): string('1.') return "1." + build_string(many1(decimal_digit))
def parse(cls, keyword=None, keywords=None): if keywords is None: keywords = cls.KEYWORDS slug = keywords[keyword.lower()] kind = ReportKind.objects.get(slug=slug) observations = {} result = { 'observations': observations, 'kind': kind, } total = "".join(optional(pico.digits, ())) if total: result['total'] = int(total) many1(partial(one_of, ' ,;')) kinds = ObservationKind.objects.filter(slug__startswith="%s_" % slug).all() observation_kinds = dict((kind.slug, kind) for kind in kinds) codes = [kind.abbr for kind in kinds if kind.abbr] # we allow both the observation kinds and any aliases allowed_codes = tuple(codes) + tuple(cls.ALIASES) while peek(): # look up observation kinds that double as user input # for the aggregate codes try: code = "".join(pico.one_of_strings(*allowed_codes)).lower() except: raise FormatError( "Expected an indicator code " "such as %s (got: %s)." % ( " or ".join(map(unicode.upper, codes[:2])), "".join(remaining()).strip() or u"nothing")) # rewrite alias if required, then look up kind munged= "%s_%s" % (slug, code) munged = cls.ALIASES.get(munged, munged) kind = observation_kinds[munged] # guard against duplicate entries if kind.slug in observations: raise FormatError("Duplicate value for %s." % code) whitespace() try: minus = optional(partial(one_of, '-'), '') value = int("".join([minus]+pico.digits())) except: raise FormatError("Expected a value for %s." % code) if value < 0: raise FormatError("Got %d for %s. You must " "report a positive value." % ( value, kind.name)) observations[kind.slug] = value many(partial(one_of, ' ,;.')) return result
def version_num(): string("1.") return "1." + build_string(many1(decimal_digit))
def number(): return many1(partial(one_of, string.digits + ' -+()'))
def eval_expression(): parts = many1(expression_part) if len(parts) == 1: return parts[0] else: return ('eval', parts)
def ident(): whitespace1() one_of('#') commit() result['ident'] = "".join(many1(partial(not_one_of, ',')))