or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

common-expressions.mdcore-elements.mdenhancement.mdexceptions.mdhelpers.mdindex.mdtesting-debugging.md

exceptions.mddocs/

0

# Exception Handling

1

2

Exception classes for parsing errors with detailed location information and error recovery mechanisms. PyParsing provides a comprehensive exception hierarchy that helps developers identify and handle parsing failures with precise error reporting.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Foundation exception classes that provide common functionality for all parsing errors.

9

10

```python { .api }

11

class ParseBaseException(Exception):

12

"""Base class for all pyparsing exceptions."""

13

14

def __init__(self,

15

pstr: str,

16

loc: int = 0,

17

msg: str = None,

18

elem: ParserElement = None): ...

19

20

@property

21

def line(self) -> str:

22

"""Get the line of text where the exception occurred."""

23

24

@property

25

def lineno(self) -> int:

26

"""Get the line number where the exception occurred."""

27

28

@property

29

def col(self) -> int:

30

"""Get the column number where the exception occurred."""

31

32

def mark_input_line(self, markerString: str = ">!<") -> str:

33

"""Return the input line with error position marked."""

34

35

def explain(self, depth: int = 16) -> str:

36

"""Return detailed explanation of parsing failure."""

37

```

38

39

### Specific Exception Types

40

41

Specialized exception classes for different types of parsing failures.

42

43

```python { .api }

44

class ParseException(ParseBaseException):

45

"""Exception raised for general parsing failures."""

46

47

def __init__(self,

48

pstr: str,

49

loc: int = 0,

50

msg: str = None,

51

elem: ParserElement = None): ...

52

53

class ParseFatalException(ParseException):

54

"""Exception that stops backtracking and parser recovery."""

55

56

def __init__(self,

57

pstr: str,

58

loc: int = 0,

59

msg: str = None,

60

elem: ParserElement = None): ...

61

62

class ParseSyntaxException(ParseFatalException):

63

"""Exception for syntax errors in parsing."""

64

65

def __init__(self,

66

pstr: str,

67

loc: int = 0,

68

msg: str = None,

69

elem: ParserElement = None): ...

70

```

71

72

### Grammar Definition Exceptions

73

74

Exceptions related to grammar definition and structure.

75

76

```python { .api }

77

class RecursiveGrammarException(Exception):

78

"""Exception for improperly defined recursive grammars."""

79

80

def __init__(self, parseElementList: list): ...

81

```

82

83

### Exception Usage Patterns

84

85

**Basic exception handling:**

86

```python

87

from pyparsing import Word, alphas, ParseException

88

89

parser = Word(alphas)

90

91

try:

92

result = parser.parse_string("123") # Will fail

93

except ParseException as pe:

94

print(f"Parse failed at line {pe.lineno}, column {pe.col}")

95

print(f"Error: {pe}")

96

print(pe.mark_input_line())

97

```

98

99

**Detailed error reporting:**

100

```python

101

def parse_with_detailed_errors(parser, text):

102

try:

103

return parser.parse_string(text, parse_all=True)

104

except ParseBaseException as pe:

105

print(f"Parsing failed:")

106

print(f" Location: Line {pe.lineno}, Column {pe.col}")

107

print(f" Message: {pe}")

108

print(f" Context: {pe.line}")

109

print(f" Marked: {pe.mark_input_line()}")

110

print(f" Explanation: {pe.explain()}")

111

return None

112

```

113

114

**Custom error messages:**

115

```python

116

# Add custom error messages to parser elements

117

number = Word(nums).set_name("number")

118

operator = oneOf("+ - * /").set_name("arithmetic operator")

119

expr = number + operator + number

120

121

try:

122

result = expr.parse_string("5 % 3") # Invalid operator

123

except ParseException as pe:

124

print(f"Expected {number.name} or {operator.name}")

125

```

126

127

**Fatal exceptions to prevent backtracking:**

128

```python

129

# Use ParseFatalException to stop parser recovery

130

def validate_positive(tokens):

131

if int(tokens[0]) <= 0:

132

raise ParseFatalException("Number must be positive")

133

134

positive_int = Word(nums).set_parse_action(validate_positive)

135

```

136

137

**Exception propagation in complex grammars:**

138

```python

139

# Control exception behavior in nested expressions

140

expr = Forward()

141

term = Word(nums) | "(" + expr + ")"

142

expr <<= term + ZeroOrMore(("+" | "-") + term)

143

144

# ParseFatalException will bubble up through the Forward reference

145

def check_balanced_parens(s, loc, tokens):

146

if tokens.count("(") != tokens.count(")"):

147

raise ParseFatalException("Unbalanced parentheses")

148

149

expr.set_parse_action(check_balanced_parens)

150

```

151

152

**Error recovery strategies:**

153

```python

154

def parse_with_recovery(parser, text):

155

"""Parse with multiple recovery strategies."""

156

try:

157

# Try strict parsing first

158

return parser.parse_string(text, parse_all=True)

159

except ParseFatalException:

160

# Fatal error - don't attempt recovery

161

raise

162

except ParseException as first_error:

163

try:

164

# Try partial parsing

165

return parser.parse_string(text, parse_all=False)

166

except ParseException:

167

# Return original error with more context

168

raise first_error

169

```

170

171

**Custom exception classes:**

172

```python

173

class ConfigurationError(ParseException):

174

"""Custom exception for configuration parsing errors."""

175

176

def __init__(self, pstr, loc, msg, elem=None):

177

super().__init__(pstr, loc, f"Configuration error: {msg}", elem)

178

179

def validate_config_value(tokens):

180

value = tokens[0]

181

if not value:

182

raise ConfigurationError("", 0, "Empty configuration value not allowed")

183

return value

184

185

config_parser = Word(alphanums).set_parse_action(validate_config_value)

186

```

187

188

### Exception Properties and Methods

189

190

**Accessing exception information:**

191

```python

192

try:

193

parser.parse_string(invalid_input)

194

except ParseException as pe:

195

# Location information

196

line_num = pe.lineno # 1-based line number

197

col_num = pe.col # 1-based column number

198

line_text = pe.line # Text of the line containing error

199

200

# Error context

201

marked_line = pe.mark_input_line("<<<ERROR>>>")

202

explanation = pe.explain(depth=10)

203

204

# Exception details

205

error_msg = str(pe) # Human-readable error message

206

location = pe.loc # 0-based character position

207

```

208

209

**Exception chaining for complex parsers:**

210

```python

211

def create_detailed_parser():

212

"""Create parser with comprehensive error reporting."""

213

214

# Add meaningful names to all elements for better error messages

215

identifier = Word(alphas + "_", alphanums + "_").set_name("identifier")

216

number = Word(nums).set_name("number")

217

string_literal = QuotedString('"').set_name("string literal")

218

219

value = (string_literal | number | identifier).set_name("value")

220

assignment = (identifier + "=" + value).set_name("assignment")

221

222

return OneOrMore(assignment).set_name("configuration")

223

224

# Usage with detailed error reporting

225

parser = create_detailed_parser()

226

try:

227

result = parser.parse_string(config_text)

228

except ParseException as pe:

229

print(f"Configuration parsing failed:")

230

print(f"Expected: {pe.expected}") # Available in some contexts

231

print(f"Found: '{pe.line[pe.col-1:pe.col+10]}'")

232

print(pe.explain())

233

```