Skip to content

Exceptions and Error Taxonomy ​

This document provides a specification of TeXpr's error model, including error classification, typed exceptions, and recovery strategies.

Error Classification ​

TeXpr errors are classified into three distinct categories based on the processing stage where they occur:

┌─────────────────────────────────────────────────────────────────┐
│                        Input String                              │
└─────────────────────────┬───────────────────────────────────────┘
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│  TOKENIZER              │  TokenizerException                   │
│  (Lexical Analysis)     │  - Invalid characters                 │
│                         │  - Malformed numbers                  │
│                         │  - Unknown LaTeX commands             │
└─────────────────────────┬───────────────────────────────────────┘
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│  PARSER                 │  ParserException                      │
│  (Syntactic Analysis)   │  - Unbalanced delimiters              │
│                         │  - Missing arguments                  │
│                         │  - Unexpected tokens                  │
│                         │  - Recursion depth exceeded           │
└─────────────────────────┬───────────────────────────────────────┘
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│  EVALUATOR              │  EvaluatorException                   │
│  (Semantic Analysis)    │  - Undefined variables                │
│                         │  - Division by zero                   │
│                         │  - Domain errors                      │
│                         │  - Type mismatches                    │
│                         │  - Resource limits                    │
└─────────────────────────┴───────────────────────────────────────┘

Exception Hierarchy ​

dart
sealed class TexprException implements Exception {
  String get message;
  int? get position;
  String? get expression;
  String? get suggestion;
}

class TokenizerException extends TexprException { ... }
class ParserException extends TexprException { ... }
class EvaluatorException extends TexprException { ... }

All exceptions are subclasses of the sealed TexprException base class, enabling exhaustive pattern matching in Dart 3.0+.


Exception Properties ​

PropertyTypeDescription
messageStringHuman-readable error description
positionint?Character index in source (0-based)
expressionString?Original expression string
suggestionString?Actionable fix recommendation

Lexical Errors (TokenizerException) ​

Lexical errors occur during tokenization when the input contains invalid character sequences.

Error Codes ​

ErrorCauseExampleSuggestion
Unknown commandUnrecognized \command\unknownfunc{x}"Did you mean '\sin'?"
Invalid characterNon-mathematical character@#$"Remove invalid character"
Malformed numberMultiple decimal points1.2.3"Invalid number format"
Unterminated textMissing closing brace in \text{}\text{hello"Add closing brace"

Example ​

dart
try {
  texpr.parse(r'\sinn{x}');
} on TokenizerException catch (e) {
  print(e.message);     // "Unknown command: sinn"
  print(e.position);    // 0
  print(e.suggestion);  // "Did you mean 'sin'?"
}

Syntactic Errors (ParserException) ​

Syntactic errors occur when the token sequence doesn't match the grammar rules.

Error Codes ​

ErrorCauseExampleSuggestion
Unbalanced delimitersMissing opening/closing(x + 1"Expected ')'"
Missing argumentIncomplete construct\frac{1}"Expected second argument"
Unexpected tokenGrammar violation+ + 1"Unexpected operator"
Recursion overflowToo deeply nested((((...))))"Expression too deeply nested"
Empty expressionNo content``"Expected expression"

Example ​

dart
try {
  texpr.parse(r'\frac{1}');
} on ParserException catch (e) {
  print(e.message);     // "Expected second argument for \\frac"
  print(e.position);    // 8
  print(e.suggestion);  // "Usage: \\frac{numerator}{denominator}"
}

Semantic Errors (EvaluatorException) ​

Semantic errors occur during evaluation when the expression is syntactically valid but mathematically problematic.

Error Categories ​

Variable Errors ​

ErrorCauseExampleSuggestion
Undefined variableMissing bindingx + 1 (no x)"Provide a value for 'x'"
Wrong variable typeNon-numeric variable{'x': 'text'}"Variable must be numeric"

Domain Errors ​

ErrorCauseExampleSuggestion
Division by zeroZero denominator1/0"Denominator cannot be zero"
Log of zeroln(0)\ln{0}"Logarithm undefined for zero"
Log of negativeln(-x) real mode\ln{-1}"Logarithm undefined for negative (use complex)"
Sqrt of negativeReal mode only\sqrt{-1}"Use complex number support"
Factorial domainNegative or non-integer(-5)!"Factorial requires non-negative integer"
Asin/acos domainOutside [-1, 1]\arcsin{2}"Argument must be in [-1, 1]"

Type Errors ​

ErrorCauseExampleSuggestion
Matrix-scalar mismatchIncompatible typesA + 5 (A is matrix)"Cannot add matrix and scalar"
Matrix dimension mismatchWrong dimensionsA * B (incompatible)"Matrix dimensions must match"
Non-numeric in calculusVariable in bounds\sum_{i=x}^{y}"Bounds must be numeric"

Resource Limit Errors ​

ErrorCauseLimitSuggestion
Recursion overflowDeep nesting500 (default)"Increase maxRecursionDepth"
Iteration overflowHuge sum/product100,000"Reduce iteration bounds"
Factorial overflowToo largen > 170"Factorial(n) exceeds double range"
Fibonacci overflowToo largen > 1476"Fibonacci(n) exceeds double range"

Example ​

dart
try {
  texpr.evaluate(r'\sum_{i=1}^{999999999} i');
} on EvaluatorException catch (e) {
  print(e.message);     // "Iteration limit exceeded"
  print(e.suggestion);  // "Maximum 100,000 iterations allowed"
}

Handling Exceptions ​

Basic Pattern ​

dart
try {
  final result = texpr.evaluate(expression, variables);
  // Use result...
} on TokenizerException catch (e) {
  // Invalid input: unknown commands, bad characters
  logError('Lexical error: ${e.message}');
} on ParserException catch (e) {
  // Syntax error: unbalanced braces, missing args
  logError('Syntax error at position ${e.position}: ${e.message}');
} on EvaluatorException catch (e) {
  // Runtime error: undefined vars, domain errors
  logError('Evaluation error: ${e.message}');
} on TexprException catch (e) {
  // Catch-all for any TeXpr error
  logError('Math error: ${e.message}');
}

Exhaustive Matching (Dart 3.0+) ​

dart
switch (error) {
  case TokenizerException(message: var msg, position: var pos):
    handleLexicalError(msg, pos);
  case ParserException(message: var msg, suggestion: var sug):
    handleSyntaxError(msg, sug);
  case EvaluatorException(message: var msg):
    handleRuntimeError(msg);
}

ValidationResult ​

For validation without throwing exceptions, use texpr.validate():

dart
final result = texpr.validate(r'\frac{1}{');

if (!result.isValid) {
  print(result.errorMessage);   // "Expected closing brace"
  print(result.position);       // 9
  print(result.suggestion);     // "Add '}' to close \\frac"
  print(result.exceptionType);  // ParserException
}

Properties ​

PropertyTypeDescription
isValidbooltrue if expression is valid
errorMessageString?Primary error description
positionint?Error position in source
suggestionString?Recommended fix
exceptionTypeType?Exception class that would be thrown
subErrorsList<ValidationError>Additional errors found

Multiple Error Detection ​

The validator attempts recovery to find multiple issues:

dart
final result = texpr.validate(r'2 + ) + \unknownfunc{x}');

print(result.errorMessage);  // Primary error
for (final sub in result.subErrors) {
  print('${sub.position}: ${sub.errorMessage}');
}
// Output:
// 4: Unexpected ')'
// 8: Unknown command 'unknownfunc'

Error Recovery Strategies ​

User Input Handling ​

dart
String sanitizeAndEvaluate(String input) {
  // 1. Validate first
  final validation = texpr.validate(input);
  if (!validation.isValid) {
    return 'Error: ${validation.suggestion ?? validation.errorMessage}';
  }

  // 2. Evaluate with timeout protection
  try {
    final result = texpr.evaluate(input, context);
    
    // 3. Check for special values
    if (result.isNumeric) {
      final value = result.asNumeric();
      if (value.isNaN) return 'Error: Result is undefined';
      if (value.isInfinite) return 'Error: Result is infinite';
      return value.toString();
    }
    
    return result.toString();
  } on TexprException catch (e) {
    return 'Error: ${e.suggestion ?? e.message}';
  }
}

Graceful Degradation ​

dart
double evaluateOrDefault(String expr, double defaultValue) {
  try {
    return texpr.evaluate(expr).asNumeric();
  } on TexprException {
    return defaultValue;
  }
}

Error Message Quality ​

TeXpr provides actionable suggestions for common errors:

Error PatternMessageSuggestion
\sin{x"Expected closing brace""Add '}' after the argument"
\sni{x}"Unknown command: sni""Did you mean 'sin'?"
x + "Unexpected end of expression""Add right-hand operand"
\log{0}"Logarithm of zero is undefined""Ensure argument is positive"
A + B (matrices)"Matrix dimensions must match""A is 2×2, B is 3×3"

API Stability ​

AspectStability Guarantee
Exception typesStable within major versions
message textMay change (not API)
position accuracyBest effort, may be approximate
suggestion presenceNot guaranteed
New exception typesMay be added in minor versions

Summary ​

StageExceptionExamples
TokenizationTokenizerExceptionUnknown commands, invalid chars
ParsingParserExceptionSyntax errors, unbalanced delimiters
EvaluationEvaluatorExceptionDomain errors, undefined variables

Always wrap evaluate() calls in try-catch and handle all three exception types appropriately for robust applications.

Made with ❤️ by TeXpr, Docs Inspired by ElysiaJS