From 22cb7d7cbcacbfe3a7d3a2d454e6b8cf49ae989c Mon Sep 17 00:00:00 2001
From: Graham Northup <grissess@nexusg.org>
Date: Fri, 13 Oct 2017 12:54:04 -0400
Subject: Added LUTs and ControlRate; improved parser

---
 src/lang/parser.rs | 226 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 180 insertions(+), 46 deletions(-)

(limited to 'src/lang/parser.rs')

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()),
+        }
     }
 }
-- 
cgit v1.2.3-70-g09d2