~/problems / Iterators & parsers / Parsers and interpreters

Parse a label printer's key=value line

easy ~15 min

A plant nursery prints pot labels from one-line specs like

name="Boston fern" water=weekly light="bright, indirect"

Write parse_tags(line: str) -> dict[str, str] that turns such a line into a dict, or raises ValueError if the line is malformed.

Grammar (the only whitespace is the plain space " "):

  • A line is zero or more pairs, separated by one or more spaces. Spaces before the first pair and after the last one are allowed.
  • A pair is a key, then =, then a value, with no spaces around =.
  • A key is one or more characters from A-Z, a-z, 0-9 and _.
  • A value is either
    • bare: one or more characters, none of which is a space, " or = (a backslash is an ordinary character here), or
    • quoted: ", then any characters, then a closing ". Inside the quotes, \" stands for " and \\ stands for \; a backslash followed by anything else is an error. Spaces and = are ordinary characters inside quotes, and "" is an empty value.
  • Right after a value comes a space or the end of the line (so a="x"b=1 is malformed).
  • A key may appear only once per line.

Everything else (a missing =, an empty bare value, an unterminated quote, a bad escape, a bad key character, a duplicate key...) raises ValueError.

parse_tags('name="Boston fern" water=weekly')
# {"name": "Boston fern", "water": "weekly"}

parse_tags(r'note="say \"hi\"" path=C:\pots')
# {"note": 'say "hi"', "path": "C:\\pots"}

parse_tags("   ")          # {}
parse_tags("a=1 a=2")      # ValueError: duplicate key 'a'
parse_tags('a="open')      # ValueError: unterminated quote
parse_tags("a= 1")         # ValueError: empty value
Show hint

walk an index i through the string. Skip spaces; read a key while the character is a key character; expect =; if the next character is ", loop until the closing quote handling \ escapes, otherwise read a bare value until a space. Raise as soon as something doesn't match what you expect.

Topic: Parsers and interpreters. Tokenize, recursive descent, S-expressions, evaluation and type inference.

0:00
Ctrl ' run · Ctrl ↵ submit
esc