-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmini_parser.py
More file actions
137 lines (109 loc) · 3.37 KB
/
mini_parser.py
File metadata and controls
137 lines (109 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python3
"""
Mini Parser - Main Interface
=============================
Improved version with specific error handling.
"""
import sys
from tokenizer import Tokenizer
from parser import Parser, Interpreter
# Define custom exceptions
class TokenizationError(Exception):
pass
class ParsingError(Exception):
pass
class EvaluationError(Exception):
pass
def parse_and_evaluate(expression: str, verbose: bool = False) -> float:
"""
Parse and evaluate a mathematical expression.
Raises specific errors for each stage.
"""
# Step 1: Tokenize
try:
tokenizer = Tokenizer(expression)
tokens = tokenizer.tokenize()
except Exception as e:
raise TokenizationError(f"Tokenization failed: {e}")
if verbose:
print("\n=== TOKENIZATION ===")
print(f"Input: {expression}")
print("Tokens:", tokens)
# Step 2: Parse
try:
parser = Parser(tokens)
ast = parser.parse()
except Exception as e:
raise ParsingError(f"Parsing failed: {e}")
if verbose:
print("\n=== PARSING ===")
print("AST:", ast)
# Step 3: Evaluate
try:
interpreter = Interpreter()
result = interpreter.evaluate(ast)
except Exception as e:
raise EvaluationError(f"Evaluation failed: {e}")
if verbose:
print("\n=== EVALUATION ===")
print("Result:", result)
return result
def interactive_mode():
"""
Run parser in interactive mode with improved error reporting.
"""
print("Mini Parser - Interactive Mode")
print("=" * 50)
verbose = False
while True:
try:
expression = input(">>> ").strip()
if expression.lower() in ('quit', 'exit'):
print("Goodbye!")
break
if expression.lower() == 'verbose':
verbose = not verbose
print(f"Verbose mode: {'ON' if verbose else 'OFF'}")
continue
if not expression:
continue
result = parse_and_evaluate(expression, verbose=verbose)
if not verbose:
print(result)
except (TokenizationError, ParsingError, EvaluationError) as e:
print(f"Error: {e}")
except KeyboardInterrupt:
print("\nGoodbye!")
break
except Exception as e:
# Catch any unexpected errors
print(f"Unexpected Error: {e}")
def main():
if len(sys.argv) == 1:
print("Usage: python mini_parser.py <expression> or --interactive/-i")
sys.exit(0)
# Interactive mode
if sys.argv[1] in ('--interactive', '-i'):
interactive_mode()
return
# Verbose mode
verbose = False
expression_index = 1
if sys.argv[1] in ('--verbose', '-v'):
verbose = True
expression_index = 2
if len(sys.argv) < 3:
print("Error: --verbose requires an expression argument")
sys.exit(1)
expression = sys.argv[expression_index]
try:
result = parse_and_evaluate(expression, verbose=verbose)
print(result)
except (TokenizationError, ParsingError, EvaluationError) as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Unexpected Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()