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>]