2 min read

Python Pyparsing Module

The pyparsing module provides an alternative approach to creating and executing simple grammars, versus the traditional lex/yacc approach, or the use of regular expressions. It handles recursive grammars and complex parsing logic more elegantly than regex.

Installation

pip install pyparsing

Basic Usage

You define a grammar using Python objects, then use that grammar to parse strings.

from pyparsing import Word, alphas

# Define grammar: a word composed of alphabetical characters
greet = Word(alphas) + "," + Word(alphas) + "!"

# Parse a string
hello = "Hello, World!"
print(greet.parseString(hello))
# Output: ['Hello', ',', 'World', '!']

Common Elements

  • Word: Matches a word composed of specific characters.
  • Literal: Matches a specific string literal.
  • OneOrMore: Matches one or more occurrences.
  • ZeroOrMore: Matches zero or more occurrences.
  • Optional: Matches an optional element.
  • Suppress: Matches an element but suppresses it from the output.
from pyparsing import Word, nums, Suppress

# Parse an IP address (e.g., 192.168.0.1)
octet = Word(nums)
dot = Suppress('.')
ip_addr = octet + dot + octet + dot + octet + dot + octet

print(ip_addr.parseString("192.168.0.1"))
# Output: ['192', '168', '0', '1'] (dots are suppressed)

Parse Actions

You can attach functions to be called when a grammar element is matched. This is useful for type conversion.

from pyparsing import Word, nums

def convert_to_int(tokens):
    return int(tokens[0])

integer = Word(nums).setParseAction(convert_to_int)
result = integer.parseString("123")
print(result[0]) # Output: 123 (as integer)
print(type(result[0])) # <class 'int'>

Complex Grammars (Arithmetic)

Pyparsing handles operator precedence easily using infixNotation.

from pyparsing import Word, nums, infixNotation, opAssoc

integer = Word(nums).setParseAction(lambda t: int(t[0]))
operand = integer

expr = infixNotation(operand, [
    ('*', 2, opAssoc.LEFT),
    ('/', 2, opAssoc.LEFT),
    ('+', 2, opAssoc.LEFT),
    ('-', 2, opAssoc.LEFT),
])

print(expr.parseString("2 + 3 * 4"))
# Output: <a href='/2%2C%20%27%2B%27%2C%20%5B3%2C%20%27%2A%27%2C%204'>2, '+', [3, '*', 4</a>]

programming/python/python