I am writing a recursive parser using a Vec as a stack to store the current state but I am running into major problems with the borrow checker. Any help will be appreciated. What I don't understand is since the lifetime of my Poly
exceeds the lifetime of the Parser
this should be totally safe but Rust does not think so.
extern crate std;
use std::fs::File;
use std::string::String;
use std::vec::Vec;
use std::result::Result;
use std::boxed::Box;
use std::str::{FromStr, Chars};
use std::io::{Read, Error, ErrorKind};
use std::io::Result as IoResult;
use std::num::ParseIntError;
struct Point
{
x : i32,
y : i32,
}
struct Path {
points : Vec<Point>
}
struct Poly {
paths : Vec<Path>
}
impl Poly {
fn new() -> Poly {
Poly { paths : Vec::new() }
}
}
impl Path {
fn new() -> Path {
Path { points : Vec::new() }
}
}
impl Point {
fn new() -> Point {
Point { x : 0, y : 0 }
}
}
trait ParserBase<'a> {
fn parseChar(&'a mut self, ch : char) -> ParseCharResult<'a>;
}
enum ParseCharResult<'a> {
Push(Box<ParserBase<'a> + 'a>, bool /*next char */),
Continue,
Pop(bool /*next char*/),
Error(&'static str /*message*/),
}
impl<'a> ParseCharResult<'a> {
fn new() -> ParseCharResult<'a> {
ParseCharResult::Error("unused")
}
}
struct ParsePoly<'a> {
poly : &'a mut Poly
}
struct ParsePath<'a> {
path : &'a mut Path
}
enum ParsePointState {
Start,
X,
Y
}
struct ParsePoint<'a> {
point : &'a mut Point,
state : ParsePointState
}
struct ParseInt<'a> {
value : &'a mut i32,
tmpStr : String
}
impl<'a> ParsePoly<'a> {
fn new(p : &'a mut Poly) -> ParsePoly<'a> {
ParsePoly{ poly : p }
}
}
impl<'a> ParsePath<'a> {
fn new(p : &'a mut Path) -> ParsePath<'a> {
ParsePath { path : p }
}
}
impl<'a> ParsePoint<'a> {
fn new(p : &'a mut Point) -> ParsePoint<'a> {
ParsePoint { point : p , state : ParsePointState::Start }
}
}
impl<'a> ParseInt<'a> {
fn new(v : &'a mut i32) -> ParseInt<'a> {
ParseInt {value : v, tmpStr : String::new() }
}
}
impl<'a> ParserBase<'a> for ParsePoly<'a>
{
fn parseChar(&'a mut self, ch : char) -> ParseCharResult<'a> {
if ch.is_whitespace() {
ParseCharResult::Continue
} else if ch == '{' {
self.poly.paths.push(Path::new());
let path : &'a mut Path = self.poly.paths.last_mut().unwrap();
let res : ParseCharResult<'a> = ParseCharResult::Push(Box::new(ParsePath::new(path)), true);
res
} else {
ParseCharResult::Error("unexpected character")
}
}
}
impl<'a> ParserBase<'a> for ParsePath<'a>
{
fn parseChar(&'a mut self, ch : char) -> ParseCharResult {
if ch.is_whitespace() {
ParseCharResult::Continue
} else if ch == '}' {
ParseCharResult::Pop(true)
} else {
self.path.points.push(Point::new());
let point = self.path.points.last_mut().unwrap();
ParseCharResult::Push(Box::new(ParsePoint::new(point)), false)
}
}
}
impl<'a> ParserBase<'a> for ParsePoint<'a>
{
fn parseChar(&'a mut self, ch : char) -> ParseCharResult {
match self.state {
ParsePointState::Start => {
if ch.is_whitespace() {
ParseCharResult::Continue
} else {
self.state = ParsePointState::X;
ParseCharResult::Push(Box::new(ParseInt::new(&mut self.point.x)), false)
}
}
ParsePointState::X => {
if ch == ' ' || ch == ',' {
ParseCharResult::Continue
} else {
self.state = ParsePointState::Y;
ParseCharResult::Push(Box::new(ParseInt::new(&mut self.point.y)), false)
}
}
ParsePointState::Y => {
if ch == '\n' {
ParseCharResult::Pop(true)
}
else if ch.is_whitespace() {
ParseCharResult::Continue
} else {
ParseCharResult::Error("ParsePoint unexpected character")
}
}
}
}
}
impl<'a> ParserBase<'a> for ParseInt<'a>
{
fn parseChar(&'a mut self, ch : char) -> ParseCharResult {
if ch.is_whitespace() || ch == ',' {
let res : Result<i32, ParseIntError> = self.tmpStr.parse();
match res {
Result::Err(_) => ParseCharResult::Error("An error occurred parsing the int"),
Result::Ok(val) => {
*self.value = val;
ParseCharResult::Pop(true)
}
}
}
else {
self.tmpStr.push(ch);
ParseCharResult::Continue
}
}
}
struct Parser<'a> {
stack : Vec<Box<ParserBase<'a> + 'a>>
}
impl<'a> Parser<'a> {
fn new(poly : &'a mut Poly) -> Parser<'a> {
let mut ret = Parser{ stack : Vec::new() };
ret.stack.push( Box::new(ParsePoly::new(poly)));
ret
}
fn parse(&'a mut self, data : &str) -> IoResult<()> {
let mut it : Chars = data.chars();
let mut val : Option<char> = it.next();
while let Option::Some(ch) = val {
let mut res = ParseCharResult::Error("unused");
{
if let Some(last) = self.stack.last_mut() {
res = (*last).parseChar(ch);
} else {
return Result::Ok(())
}
}
match res {
ParseCharResult::Push(item, inc) => {
self.stack.push(item);
if inc {
val = it.next();
}
}
ParseCharResult::Continue => {
val = it.next();
}
ParseCharResult::Pop(inc) => {
{
self.stack.pop();
}
if inc {
val = it.next();
}
}
ParseCharResult::Error(message) => return Err(std::io::Error::new(ErrorKind::Other, message))
}
}
Result::Err(std::io::Error::new(ErrorKind::UnexpectedEof, "Needs more data"))
}
}
impl Poly {
fn load(filename : &str) -> IoResult<Poly> {
let mut file = try!(File::open(filename));
let mut s = String::new();
try!(file.read_to_string(&mut s));
let mut poly= Poly::new();
{
let mut parser = Parser::new(&mut poly);
try!(parser.parse(s.as_str()));
}
Ok(poly)
}
}
This give the following errors.
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time --> src/poly.rs:235:25 | 217 | if let Some(last) = self.stack.last_mut() { | ---------- first mutable borrow occurs here ... 235 | self.stack.pop(); | ^^^^^^^^^^ second mutable borrow occurs here ... 245 | } | - first borrow ends here error: `parser` does not live long enough --> src/poly.rs:256:16 | 256 | try!(parser.parse(s.as_str())); | ^^^^^^ src/poly.rs:256:11: 256:42 note: in this expansion of try! (defined in ) | note: reference must be valid for the block at 254:8... --> src/poly.rs:254:9 | 254 | { | ^ note: ...but borrowed value is only valid for the block suffix following statement 0 at 255:50 --> src/poly.rs:255:51 | 255 | let mut parser = Parser::new(&mut poly); | ^ error: aborting due to 5 previous errors error: Could not compile `test`.