diff options
Diffstat (limited to 'src/lang')
-rw-r--r-- | src/lang/parser.rs | 226 | ||||
-rw-r--r-- | src/lang/tokenizer.rs | 5 |
2 files changed, 184 insertions, 47 deletions
diff --git a/src/lang/parser.rs b/src/lang/parser.rs index c49cf65..35df372 100644 --- a/src/lang/parser.rs +++ b/src/lang/parser.rs @@ -7,6 +7,7 @@ use synth::*; #[derive(Debug)] pub enum ErrorKind { Unexpected(TokType, TokType), + Unparseable(TokType, String), ExpectedOp(char, TokType), UnknownGen(String), } @@ -26,6 +27,7 @@ impl ErrorType { ret.desc = match ret.kind { 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::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) { match self.pushback { None => { - self.pushback = Some(mem::replace(&mut self.token, tok)); + self.pushback = Some(tok); }, 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>> { - 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()) + } 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>> { - 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(()) }, - _ => 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; } - /* 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() { self.expect_op(']')?; @@ -138,17 +146,150 @@ impl<T: Iterator<Item=char>> Parser<T> { 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) } + 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>> { + eprintln!("consuming paren in factory_params"); self.expect_op('(')?; 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); 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(')')?; break; } @@ -177,14 +320,9 @@ impl<T: Iterator<Item=char>> Parser<T> { if self.expect_op('=').is_ok() { nm } 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(_) => { @@ -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()), + } } } diff --git a/src/lang/tokenizer.rs b/src/lang/tokenizer.rs index 1d62f3e..6de825b 100644 --- a/src/lang/tokenizer.rs +++ b/src/lang/tokenizer.rs @@ -425,9 +425,12 @@ impl<T: Iterator<Item=char>> Tokenizer<T> { floating = true; buffer.push(cc); buffer.push(ncc); - } else { + } else if ncc.is_digit(10) { buffer.push(cc); buffer.push(ncc); + } else { + self.push_back(ncc); + return Ok(Token::Integer(0)); } } else { buffer.push(cc); |