Skip to content

Commit 8274d9b

Browse files
committed
Removed PyO3 integration and turned this into a strict parsing library
1 parent 1213039 commit 8274d9b

File tree

6 files changed

+92
-272
lines changed

6 files changed

+92
-272
lines changed

Cargo.toml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[package]
2-
name = "unrealscriptplus"
2+
name = "unrealscript_parser"
33
version = "0.2.1"
44
edition = "2024"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88

99
[lib]
10-
name = "unrealscriptplus"
11-
crate-type = ["lib", "cdylib"]
10+
name = "unrealscript_parser"
11+
crate-type = ["lib"]
1212

1313
[dependencies]
1414
pest = "2.7"
@@ -20,8 +20,4 @@ strum_macros = "0.26"
2020
pest_consume = "1.1"
2121
pest_consume_macros = "1.1"
2222
convert_case = "0.6"
23-
if_chain = "1.0"
24-
25-
[dependencies.pyo3]
26-
version = "0.27"
27-
features = ["extension-module"]
23+
if_chain = "1.0"

src/lib.rs

Lines changed: 2 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,6 @@
11
pub mod ast;
22
pub mod parser;
33
pub mod visitor;
4-
pub mod transform;
54

6-
use pest::error::{ErrorVariant, LineColLocation, InputLocation};
7-
use crate::parser::{ParsingError, ParserRule, ProgramResult};
8-
9-
// PYTHON STUFF
10-
use pyo3::prelude::*;
11-
use pyo3::{create_exception, PyErr};
12-
use pyo3::types::PyDict;
13-
use pyo3::exceptions;
14-
15-
create_exception!(unrealscriptplus, ScriptParseError, pyo3::exceptions::PyException);
16-
17-
fn parsing_error_to_py_err(py: Python, error: ParsingError) -> PyErr {
18-
match error {
19-
ParsingError::PestError(e) => ScriptParseError::new_err(pest_error_to_py_object(py, e)),
20-
ParsingError::EncodingError(e) => exceptions::PyUnicodeEncodeError::new_err(e.to_string()),
21-
ParsingError::IoError(e) => exceptions::PyIOError::new_err(e.to_string())
22-
}
23-
}
24-
25-
fn program_result_to_py_object(py: Python, result: &ProgramResult) -> Py<PyAny> {
26-
let errors: Vec<Py<PyAny>> = result.errors.iter().map(|e| {
27-
let dict = PyDict::new(py);
28-
dict.set_item("line", e.span.line).unwrap();
29-
dict.set_item("message", &e.message).unwrap();
30-
dict.set_item("severity", format!("{:?}", e.severity)).unwrap();
31-
dict.into()
32-
}).collect();
33-
34-
let dict = PyDict::new(py);
35-
dict.set_item("errors", errors).unwrap();
36-
dict.into()
37-
}
38-
39-
fn pest_error_to_py_object(py: Python, e: pest_consume::Error<ParserRule>) -> Py<PyAny> {
40-
let dict = PyDict::new(py);
41-
42-
match e.line_col {
43-
LineColLocation::Pos(pos) => {
44-
dict.set_item("line_col", pos).unwrap();
45-
},
46-
LineColLocation::Span(span1, span2) => {
47-
dict.set_item("line_col", (span1, span2)).unwrap();
48-
}
49-
};
50-
51-
match e.location {
52-
InputLocation::Pos(pos) => {
53-
dict.set_item("location", pos).unwrap();
54-
},
55-
InputLocation::Span(span) => {
56-
dict.set_item("location", span).unwrap();
57-
}
58-
};
59-
60-
let variant: Py<PyAny> = match e.variant {
61-
ErrorVariant::ParsingError { positives, negatives } => {
62-
let positives: Vec<String> = positives.into_iter().map(|r| format!("{:?}", r)).collect();
63-
let negatives: Vec<String> = negatives.into_iter().map(|r| format!("{:?}", r)).collect();
64-
let variant_dict = PyDict::new(py);
65-
variant_dict.set_item("type", "parsing").unwrap();
66-
variant_dict.set_item("positives", positives).unwrap();
67-
variant_dict.set_item("negatives", negatives).unwrap();
68-
variant_dict.into()
69-
},
70-
ErrorVariant::CustomError { message } => {
71-
let variant_dict = PyDict::new(py);
72-
variant_dict.set_item("type", "custom").unwrap();
73-
variant_dict.set_item("message", message).unwrap();
74-
variant_dict.into()
75-
},
76-
};
77-
dict.set_item("variant", variant).unwrap();
78-
79-
dict.into()
80-
}
81-
82-
#[pyfunction]
83-
fn parse_expression(py: Python, path: &str) -> PyResult<String> {
84-
match crate::parser::parse_expression(path) {
85-
Ok(p) => { Ok(format!("{:?}", p)) }
86-
Err(e) => { Err(parsing_error_to_py_err(py, e.into())) }
87-
}
88-
}
89-
90-
#[pyfunction]
91-
fn parse_file(py: Python, path: &str) -> PyResult<Py<PyAny>> {
92-
match crate::parser::parse_file(path) {
93-
Ok(result) => {
94-
Ok(program_result_to_py_object(py, &result))
95-
}
96-
Err(e) => Err(parsing_error_to_py_err(py, e))
97-
}
98-
}
99-
100-
#[pymodule]
101-
fn unrealscriptplus(m: &Bound<'_, PyModule>) -> PyResult<()> {
102-
m.add_function(wrap_pyfunction!(parse_expression, m)?)?;
103-
m.add_function(wrap_pyfunction!(parse_file, m)?)?;
104-
m.add("ScriptParseError", m.py().get_type::<ScriptParseError>())?;
105-
Ok(())
106-
}
5+
// Re-export main parsing functions and types for library consumers
6+
pub use parser::{parse_expression, parse_with_rule, parse_program, ParsingError, ProgramResult, Rule};

src/parser.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ use std::str::FromStr;
99
use std::collections::HashMap;
1010
use lazy_static::lazy_static;
1111

12-
use encoding::{DecoderTrap, Encoding};
13-
use std::fs::File;
14-
use std::io::Read;
15-
1612
use std::rc::Rc;
1713

1814
use crate::ast::*;
@@ -1236,6 +1232,7 @@ impl UnrealScriptParser {
12361232
}
12371233
}
12381234

1235+
#[derive(Debug)]
12391236
pub enum ParsingError {
12401237
IoError(std::io::Error),
12411238
EncodingError(String),
@@ -1254,15 +1251,6 @@ impl From<Error<Rule>> for ParsingError {
12541251
}
12551252
}
12561253

1257-
fn read_file_to_string(path: &str) -> std::result::Result<String, ParsingError> {
1258-
let mut file = File::open(path)?;
1259-
let mut buffer: Vec<u8> = Vec::new();
1260-
file.read_to_end(&mut buffer)?;
1261-
encoding::all::WINDOWS_1252
1262-
.decode(&mut buffer, DecoderTrap::Strict)
1263-
.map_err(|e| ParsingError::EncodingError(e.to_string()))
1264-
}
1265-
12661254
#[derive(Debug, PartialEq, Clone)]
12671255
pub enum ProgramErrorSeverity {
12681256
Warning,
@@ -1330,6 +1318,22 @@ pub fn parse_expression(contents: &str) -> std::result::Result<Box<AstNode<Expre
13301318
}
13311319
}
13321320

1333-
pub fn parse_file(path: &str) -> std::result::Result<ProgramResult, ParsingError> {
1334-
parse_program(read_file_to_string(path)?.as_str())
1321+
/// Parse text starting at a specific grammar rule.
1322+
/// Useful for incremental parsing where you want to parse a slice of code.
1323+
///
1324+
/// # Arguments
1325+
/// * `rule` - The grammar rule to start parsing from
1326+
/// * `contents` - The text to parse
1327+
///
1328+
/// # Returns
1329+
/// The raw pest_consume Nodes iterator on success, or a ParsingError on failure.
1330+
///
1331+
/// # Example
1332+
/// ```ignore
1333+
/// use unrealscript_parser::{parse_with_rule, Rule};
1334+
/// let result = parse_with_rule(Rule::expression, "1 + 2");
1335+
/// ```
1336+
pub fn parse_with_rule(rule: Rule, contents: &str) -> std::result::Result<pest_consume::Nodes<'_, Rule, ()>, ParsingError> {
1337+
UnrealScriptParser::parse(rule, contents)
1338+
.map_err(|e| ParsingError::from(e))
13351339
}

src/transform.rs

Lines changed: 0 additions & 146 deletions
This file was deleted.

0 commit comments

Comments
 (0)