|
@@ -7,6 +7,7 @@ use synth::*;
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
|
pub enum ErrorKind {
|
|
pub enum ErrorKind {
|
|
|
Unexpected(TokType, TokType),
|
|
Unexpected(TokType, TokType),
|
|
|
|
|
+ Unparseable(TokType, String),
|
|
|
ExpectedOp(char, TokType),
|
|
ExpectedOp(char, TokType),
|
|
|
UnknownGen(String),
|
|
UnknownGen(String),
|
|
|
}
|
|
}
|
|
@@ -26,6 +27,7 @@ impl ErrorType {
|
|
|
|
|
|
|
|
ret.desc = match ret.kind {
|
|
ret.desc = match ret.kind {
|
|
|
ErrorKind::Unexpected(found, expected) => format!("Found {:?}, expected {:?}", found, expected),
|
|
ErrorKind::Unexpected(found, expected) => format!("Found {:?}, expected {:?}", found, expected),
|
|
|
|
|
+ ErrorKind::Unparseable(found, ref term) => format!("Cannot consume {:?} token in {}", found, term),
|
|
|
ErrorKind::ExpectedOp(c, found) => format!("Expected {:?}, found {:?}", c, found),
|
|
ErrorKind::ExpectedOp(c, found) => format!("Expected {:?}, found {:?}", c, found),
|
|
|
ErrorKind::UnknownGen(ref s) => format!("Unknown generator name {}", s),
|
|
ErrorKind::UnknownGen(ref s) => format!("Unknown generator name {}", s),
|
|
|
};
|
|
};
|
|
@@ -76,20 +78,27 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
pub fn push_back(&mut self, tok: Token) {
|
|
pub fn push_back(&mut self, tok: Token) {
|
|
|
match self.pushback {
|
|
match self.pushback {
|
|
|
None => {
|
|
None => {
|
|
|
- self.pushback = Some(mem::replace(&mut self.token, tok));
|
|
|
|
|
|
|
+ self.pushback = Some(tok);
|
|
|
},
|
|
},
|
|
|
Some(_) => panic!("too many pushbacks on Parser"),
|
|
Some(_) => panic!("too many pushbacks on Parser"),
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pub fn cur_token(&self) -> &Token {
|
|
|
|
|
+ match self.pushback {
|
|
|
|
|
+ Some(ref tok) => tok,
|
|
|
|
|
+ None => &self.token,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
pub fn expect(&mut self, ty: TokType) -> Result<Token, Box<Error>> {
|
|
pub fn expect(&mut self, ty: TokType) -> Result<Token, Box<Error>> {
|
|
|
- if ty == self.token.to_type() {
|
|
|
|
|
- Ok(mem::replace(&mut self.token, match self.pushback {
|
|
|
|
|
- Some(_) => mem::replace(&mut self.pushback, None).unwrap(),
|
|
|
|
|
- None => self.tzr.next_token()?,
|
|
|
|
|
- }))
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ if ty != self.cur_token().to_type() {
|
|
|
Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), ty)).into())
|
|
Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), ty)).into())
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Ok(match self.pushback {
|
|
|
|
|
+ Some(_) => mem::replace(&mut self.pushback, None).unwrap(),
|
|
|
|
|
+ None => mem::replace(&mut self.token, self.tzr.next_token()?),
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -101,9 +110,18 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn expect_op(&mut self, oper: char) -> Result<(), Box<Error>> {
|
|
pub fn expect_op(&mut self, oper: char) -> Result<(), Box<Error>> {
|
|
|
- match self.token {
|
|
|
|
|
|
|
+ eprintln!("expect_op: {:?} ({})", self.cur_token(), oper);
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
Token::Oper(c) if c == oper => { self.expect(TokType::Oper)?; Ok(()) },
|
|
Token::Oper(c) if c == oper => { self.expect(TokType::Oper)?; Ok(()) },
|
|
|
- _ => Err(ErrorType::new(ErrorKind::ExpectedOp(oper, self.token.to_type())).into()),
|
|
|
|
|
|
|
+ _ => Err(ErrorType::new(ErrorKind::ExpectedOp(oper, self.cur_token().to_type())).into()),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn peek_op(&self, oper: char) -> bool {
|
|
|
|
|
+ eprintln!("peek_op: {:?} ({})", self.cur_token(), oper);
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
|
|
+ Token::Oper(c) if c == oper => true,
|
|
|
|
|
+ _ => false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -117,17 +135,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* TODO: Can't yet clone a GenBox safely
|
|
|
|
|
- let repeat = match self.token {
|
|
|
|
|
- Token::Integer(v) => {
|
|
|
|
|
- self.expect_op('*')?;
|
|
|
|
|
- v
|
|
|
|
|
- },
|
|
|
|
|
- _ => 1,
|
|
|
|
|
- };
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
- ret.push(self.parse_gen()?);
|
|
|
|
|
|
|
+ ret.push(self.parse_gen_rel()?);
|
|
|
|
|
|
|
|
if self.expect_op(',').is_err() {
|
|
if self.expect_op(',').is_err() {
|
|
|
self.expect_op(']')?;
|
|
self.expect_op(']')?;
|
|
@@ -138,17 +146,150 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
Ok(ret)
|
|
Ok(ret)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn parse_gen(&mut self) -> Result<GenBox, Box<Error>> {
|
|
|
|
|
- let name = self.expect_ident()?;
|
|
|
|
|
- let mut params = self.parse_factory_params()?;
|
|
|
|
|
- let factory = match self.factories.get(&name) {
|
|
|
|
|
- Some(fac) => fac,
|
|
|
|
|
- None => return Err(ErrorType::new(ErrorKind::UnknownGen(name)).into()),
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ pub fn parse_gen_rel(&mut self) -> Result<GenBox, Box<Error>> {
|
|
|
|
|
+ let left = self.parse_gen_terms()?;
|
|
|
|
|
+
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
|
|
+ Token::Oper(c) => {
|
|
|
|
|
+ if c == '>' || c == '!' || c == '<' || c == '=' { // TODO: Conflict with param name
|
|
|
|
|
+ self.expect(TokType::Oper)?;
|
|
|
|
|
+ let relop = match (c, self.cur_token()) {
|
|
|
|
|
+ ('<', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::LessEqual },
|
|
|
|
|
+ ('=', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::Equal },
|
|
|
|
|
+ ('>', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::Greater },
|
|
|
|
|
+ ('!', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::NotEqual },
|
|
|
|
|
+ ('<', _) => RelOp::Less,
|
|
|
|
|
+ ('>', _) => RelOp::Greater,
|
|
|
|
|
+ _ => return Err(ErrorType::new(ErrorKind::Unparseable(TokType::Oper, "rel expr".to_string())).into()),
|
|
|
|
|
+ };
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::Generator(left));
|
|
|
|
|
+ params.vars.insert("1".to_string(), ParamValue::String(relop.to_param_string().to_string()));
|
|
|
|
|
+ params.vars.insert("2".to_string(), ParamValue::Generator(self.parse_gen_rel()?));
|
|
|
|
|
+ let factory = self.factories.get("rel").ok_or(ErrorType::new(ErrorKind::UnknownGen("rel".to_string())))?;
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Ok(left)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ _ => Ok(left),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn parse_gen_terms(&mut self) -> Result<GenBox, Box<Error>> {
|
|
|
|
|
+ let mut gens: Vec<GenBox> = Vec::new();
|
|
|
|
|
+ gens.push(self.parse_gen_factors()?);
|
|
|
|
|
+
|
|
|
|
|
+ loop {
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
|
|
+ Token::Oper('+') => {
|
|
|
|
|
+ self.expect_op('+')?;
|
|
|
|
|
+ gens.push(self.parse_gen_factors()?);
|
|
|
|
|
+ },
|
|
|
|
|
+ Token::Oper('-') => {
|
|
|
|
|
+ self.expect_op('-')?;
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::Generator(self.parse_gen_factors()?));
|
|
|
|
|
+ let factory = self.factories.get("negate").ok_or(ErrorType::new(ErrorKind::UnknownGen("negate".to_string())))?;
|
|
|
|
|
+ gens.push(factory.new(&mut params).map_err(GenFactoryErrorType::from)?);
|
|
|
|
|
+ },
|
|
|
|
|
+ _ => break,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if gens.len() == 1 {
|
|
|
|
|
+ return Ok(gens.pop().unwrap());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ for (idx, gen) in gens.into_iter().enumerate() {
|
|
|
|
|
+ params.vars.insert(idx.to_string(), ParamValue::Generator(gen));
|
|
|
|
|
+ }
|
|
|
|
|
+ let factory = self.factories.get("add").ok_or(ErrorType::new(ErrorKind::UnknownGen("add".to_string())))?;
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn parse_gen_factors(&mut self) -> Result<GenBox, Box<Error>> {
|
|
|
|
|
+ let mut gens: Vec<GenBox> = Vec::new();
|
|
|
|
|
+ gens.push(self.parse_gen()?);
|
|
|
|
|
+
|
|
|
|
|
+ loop {
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
|
|
+ Token::Oper('*') => {
|
|
|
|
|
+ self.expect_op('*')?;
|
|
|
|
|
+ gens.push(self.parse_gen()?);
|
|
|
|
|
+ },
|
|
|
|
|
+ Token::Oper('/') => {
|
|
|
|
|
+ self.expect_op('/')?;
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::Generator(self.parse_gen()?));
|
|
|
|
|
+ let factory = self.factories.get("reciprocate").ok_or(ErrorType::new(ErrorKind::UnknownGen("reciprocate".to_string())))?;
|
|
|
|
|
+ gens.push(factory.new(&mut params).map_err(GenFactoryErrorType::from)?);
|
|
|
|
|
+ },
|
|
|
|
|
+ _ => break,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if gens.len() == 1 {
|
|
|
|
|
+ return Ok(gens.pop().unwrap());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ for (idx, gen) in gens.into_iter().enumerate() {
|
|
|
|
|
+ params.vars.insert(idx.to_string(), ParamValue::Generator(gen));
|
|
|
|
|
+ }
|
|
|
|
|
+ let factory = self.factories.get("mul").ok_or(ErrorType::new(ErrorKind::UnknownGen("mul".to_string())))?;
|
|
|
factory.new(&mut params).map_err(Into::into)
|
|
factory.new(&mut params).map_err(Into::into)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pub fn parse_gen(&mut self) -> Result<GenBox, Box<Error>> {
|
|
|
|
|
+ match *self.cur_token() {
|
|
|
|
|
+ Token::Integer(v) => {
|
|
|
|
|
+ self.expect(TokType::Integer)?;
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::String("_".to_string()));
|
|
|
|
|
+ params.vars.insert("1".to_string(), ParamValue::Integer(v));
|
|
|
|
|
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ },
|
|
|
|
|
+ Token::Float(v) => {
|
|
|
|
|
+ self.expect(TokType::Float)?;
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::String("_".to_string()));
|
|
|
|
|
+ params.vars.insert("1".to_string(), ParamValue::Float(v));
|
|
|
|
|
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ },
|
|
|
|
|
+ Token::Ident(_) => {
|
|
|
|
|
+ let name = self.expect_ident()?;
|
|
|
|
|
+ if self.peek_op('(') {
|
|
|
|
|
+ let mut params = self.parse_factory_params()?;
|
|
|
|
|
+ let factory = match self.factories.get(&name) {
|
|
|
|
|
+ Some(fac) => fac,
|
|
|
|
|
+ None => return Err(ErrorType::new(ErrorKind::UnknownGen(name)).into()),
|
|
|
|
|
+ };
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
|
|
|
+ params.vars.insert("0".to_string(), ParamValue::String(name));
|
|
|
|
|
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
|
|
|
|
|
+ factory.new(&mut params).map_err(Into::into)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ Token::Oper('(') => {
|
|
|
|
|
+ eprintln!("consuming paren in parse_gen");
|
|
|
|
|
+ self.expect(TokType::Oper)?;
|
|
|
|
|
+ let ret = self.parse_gen_rel()?;
|
|
|
|
|
+ eprintln!("parenthesized generator is concluding");
|
|
|
|
|
+ self.expect_op(')')?;
|
|
|
|
|
+ Ok(ret)
|
|
|
|
|
+ },
|
|
|
|
|
+ _ => Err(ErrorType::new(ErrorKind::Unparseable(self.cur_token().to_type(), "gen".to_string())).into()),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
pub fn parse_factory_params(&mut self) -> Result<FactoryParameters, Box<Error>> {
|
|
pub fn parse_factory_params(&mut self) -> Result<FactoryParameters, Box<Error>> {
|
|
|
|
|
+ eprintln!("consuming paren in factory_params");
|
|
|
self.expect_op('(')?;
|
|
self.expect_op('(')?;
|
|
|
|
|
|
|
|
let mut params: FactoryParameters = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
let mut params: FactoryParameters = FactoryParameters { env: self.env.clone(), ..Default::default() };
|
|
@@ -161,7 +302,9 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
params.vars.insert(nm, vl);
|
|
params.vars.insert(nm, vl);
|
|
|
ctr = new_ctr;
|
|
ctr = new_ctr;
|
|
|
|
|
|
|
|
- if self.expect_op(',').is_err() {
|
|
|
|
|
|
|
+ eprintln!("before factory_params comma, tok is {:?}", self.cur_token());
|
|
|
|
|
+ if self.expect_op(',').map_err(|e| eprintln!("factory_params consume comma failed: {:?}", e)).is_err() {
|
|
|
|
|
+ eprintln!("factory_params is concluding");
|
|
|
self.expect_op(')')?;
|
|
self.expect_op(')')?;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -177,14 +320,9 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
if self.expect_op('=').is_ok() {
|
|
if self.expect_op('=').is_ok() {
|
|
|
nm
|
|
nm
|
|
|
} else {
|
|
} else {
|
|
|
- match self.token {
|
|
|
|
|
- Token::Oper(c) if c == '(' => {
|
|
|
|
|
- self.push_back(Token::Ident(nm));
|
|
|
|
|
- ctr += 1;
|
|
|
|
|
- (ctr - 1).to_string()
|
|
|
|
|
- },
|
|
|
|
|
- _ => return Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), TokType::Ident)).into()),
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ self.push_back(Token::Ident(nm));
|
|
|
|
|
+ ctr += 1;
|
|
|
|
|
+ (ctr - 1).to_string()
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
Err(_) => {
|
|
Err(_) => {
|
|
@@ -193,16 +331,12 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let ret = match self.token {
|
|
|
|
|
- Token::Integer(v) => Ok((name, ParamValue::Integer(v), ctr)),
|
|
|
|
|
- Token::Float(v) => Ok((name, ParamValue::Float(v), ctr)),
|
|
|
|
|
- Token::String(ref v) => Ok((name, ParamValue::String(v.clone()), ctr)),
|
|
|
|
|
- Token::Ident(_) => return Ok((name, ParamValue::Generator(self.parse_gen()?), ctr)),
|
|
|
|
|
- _ => return Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), TokType::Ident)).into()),
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ eprintln!("about to consume param value, token is {:?}", self.cur_token());
|
|
|
|
|
|
|
|
- let tp = self.token.to_type();
|
|
|
|
|
- self.expect(tp)?;
|
|
|
|
|
- ret
|
|
|
|
|
|
|
+ match self.cur_token().clone() { // FIXME: Does this really need to be cloned?
|
|
|
|
|
+ Token::String(ref v) => { self.expect(TokType::String)?; Ok((name, ParamValue::String(v.clone()), ctr)) },
|
|
|
|
|
+ Token::Integer(_) | Token::Float(_) | Token::Ident(_) | Token::Oper('(') => Ok((name, ParamValue::Generator(self.parse_gen_rel()?), ctr)),
|
|
|
|
|
+ _ => Err(ErrorType::new(ErrorKind::Unparseable(self.cur_token().to_type(), "param value".to_string())).into()),
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|