# Unreal Engine Log Parser
**Unreal Engine Log Parser** is a Rust-based command-line tool designed to parse and filter Unreal Engine log files. It leverages the `pest` parser for efficient log parsing and `clap` for a user-friendly CLI interface.
## Grammar Specification
The Unreal Engine Log Parser utilizes a [PEG (Parsing Expression Grammar)](https://en.wikipedia.org/wiki/Parsing_expression_grammar) defined using the [`pest`](https://pest.rs/) parser generator. Below is a detailed breakdown of the grammar rules used to parse Unreal Engine log files.
### Overview
A typical Unreal Engine log line follows this structure:
```
[2024.04.27-12.34.56:789][ 1]LogTemp: Warning: This is a warning message.
```
This line consists of:
1. **Timestamp:** `[2024.04.27-12.34.56:789]`
2. **Frame Number:** `[ 1]`
3. **Category:** `LogTemp:`
4. **Verbosity:** `Warning:`
5. **Message:** `This is a warning message.`
### Grammar Rules
1. Whitespace and Newline
WHITESPACE: Defines what constitutes whitespace in the log file. It includes spaces, tabs, and newlines.
```pest
WHITESPACE = _{ " " | "\t" | NEWLINE }
```
NEWLINE: Recognizes both Unix (\n) and Windows (\r\n) newline characters.
```pest
NEWLINE = _{ "\n" | "\r\n" }
```
2. File Structure
file: Represents the entire log file. It starts at the beginning of the input (SOI) and consists of zero or more line entries, ending at the end of the input (EOI).
```pest
file = { SOI ~ line* ~ EOI }
```
3. Log Line Structure
line: Defines a single log entry. Each line may optionally start with a timestamp and frame_num, followed by mandatory category, optional verbosity, and the message. An optional newline may follow.
```pest
line = { timestamp? ~ frame_num? ~ category ~ verbosity? ~ message ~ NEWLINE? }
```
4. Timestamp Parsing
timestamp: Enclosed in square brackets, it contains the datetime.
```pest
timestamp = { "[" ~ datetime ~ "]" }
```
datetime: Breaks down the timestamp into its constituent parts: year, month, day, hour, minute, second, and millisecond.
```pest
datetime = { year ~ "." ~ month ~ "." ~ day ~ "-" ~ hour ~ "." ~ minute ~ "." ~ second ~ ":" ~ millisecond }
```
**Individual Components:**
year: Exactly four digits.
```pest
year = @{ ASCII_DIGIT{4} }
```
month, day, hour, minute, second: Exactly two digits each.
```pest
month = @{ ASCII_DIGIT{2} }
day = @{ ASCII_DIGIT{2} }
hour = @{ ASCII_DIGIT{2} }
minute = @{ ASCII_DIGIT{2} }
second = @{ ASCII_DIGIT{2} }
```
millisecond: Exactly three digits.
```pest
millisecond = @{ ASCII_DIGIT{3} }
```
5. Frame Number Parsing
frame_num: Enclosed in square brackets, it contains the frame_number.
```pest
frame_num = { "[" ~ frame_number ~ "]" }
```
frame_number: Consists of one or more digits, potentially followed by spaces or tabs. Leading and trailing whitespace is allowed.
```pest
frame_number = @{ ws? ~ ws? ~ ASCII_DIGIT+ }
```
Example Matches:
```
[1] → 1
[ 123 ] → 123
[1 2 3] → 123
```
6. Category Parsing
category: An identifier followed by a colon and optional whitespace.
```pest
category = { identifier ~ ":" ~ ws }
```
identifier: Consists of one or more alphanumeric characters, underscores, or forward slashes.
```pest
verbosity_str = { "Verbose" | "VeryVerbose" | "Display" | "Log" | "Warning" | "Error" | "Fatal" }
```
Allowed Values:
- Verbose
- VeryVerbose
- Display
- Log
- Warning
- Error
- Fatal
8. Message Parsing
message: Captures the rest of the line as the log message. It includes any character except for a newline.