Add functions
This commit is contained in:
		
							parent
							
								
									cf0f4fc0b9
								
							
						
					
					
						commit
						86c2b13d1a
					
				| @ -1,2 +1 @@ | |||||||
| let otus = "dotus"; | print(); | ||||||
| let botus = otus; |  | ||||||
| @ -62,6 +62,7 @@ impl Compiler { | |||||||
|                 self.list.push(Command::EndScope); |                 self.list.push(Command::EndScope); | ||||||
|                 Ok(None) |                 Ok(None) | ||||||
|             } |             } | ||||||
|  |             Expression::FunctionCall(..) => Err(CompilerError::Fatal), | ||||||
|             Expression::ValueRef(_, val) => match val { |             Expression::ValueRef(_, val) => match val { | ||||||
|                 Pattern::IdentPattern(pos, ident) => { |                 Pattern::IdentPattern(pos, ident) => { | ||||||
|                     if let Some(var) = self.root_scope.get(ident.clone()) { |                     if let Some(var) = self.root_scope.get(ident.clone()) { | ||||||
|  | |||||||
| @ -17,6 +17,7 @@ const ALLOWED_IDENT_BEGIN_CHARS: [char; 26] = [ | |||||||
| pub struct Parser { | pub struct Parser { | ||||||
|     text: Vec<char>, |     text: Vec<char>, | ||||||
|     cursor: usize, |     cursor: usize, | ||||||
|  |     inconfidence: usize, | ||||||
|     line_number: usize, |     line_number: usize, | ||||||
|     character_number: usize, |     character_number: usize, | ||||||
| } | } | ||||||
| @ -26,6 +27,7 @@ impl Parser { | |||||||
|         Parser { |         Parser { | ||||||
|             text: text.chars().collect(), |             text: text.chars().collect(), | ||||||
|             cursor: 0, |             cursor: 0, | ||||||
|  |             inconfidence: 0, | ||||||
|             line_number: 0, |             line_number: 0, | ||||||
|             character_number: 0, |             character_number: 0, | ||||||
|         } |         } | ||||||
| @ -37,7 +39,7 @@ impl Parser { | |||||||
|         let mut error = None; |         let mut error = None; | ||||||
| 
 | 
 | ||||||
|         while { |         while { | ||||||
|             self.skip_whitespace(); |             self.skip_whitespace_confident(true); | ||||||
|             if self.remaining() > 0 { |             if self.remaining() > 0 { | ||||||
|                 match Statement::parse(&mut self) { |                 match Statement::parse(&mut self) { | ||||||
|                     Ok(exp) => { |                     Ok(exp) => { | ||||||
| @ -76,12 +78,20 @@ impl Parser { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn expect<T: Into<String>>(&mut self, expected: T) -> Expect { |     pub fn expect<T: Into<String>>(&mut self, expectable: Expectable<T>) -> Expect { | ||||||
|  |         match expectable { | ||||||
|  |             Expectable::Static(val) => self.expect_static(val), | ||||||
|  |             Ident => self.expect_ident(), | ||||||
|  |             StringLit => self.expect_string_lit(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn expect_static<T: Into<String>>(&mut self, expected: T) -> Expect { | ||||||
|         let expected = expected.into(); |         let expected = expected.into(); | ||||||
|         self.skip_whitespace(); |         self.skip_whitespace(); | ||||||
|         let mut result = Some(expected.clone()); |         let mut result = Some(expected.clone()); | ||||||
|         for (idx, c) in expected.chars().enumerate() { |         for (idx, c) in expected.chars().enumerate() { | ||||||
|             if let Some(peek) = self.peek(idx) { |             if let Some(peek) = self.peek(idx + self.inconfidence) { | ||||||
|                 if peek != c { |                 if peek != c { | ||||||
|                     result = None; |                     result = None; | ||||||
|                 } |                 } | ||||||
| @ -90,9 +100,9 @@ impl Parser { | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         self.inconfidence += expected.len(); | ||||||
|         Expect { |         Expect { | ||||||
|             text: result, |             text: result, | ||||||
|             len: expected.len(), |  | ||||||
|             parser: self, |             parser: self, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -100,14 +110,13 @@ impl Parser { | |||||||
|     pub fn expect_ident(&mut self) -> Expect { |     pub fn expect_ident(&mut self) -> Expect { | ||||||
|         self.skip_whitespace(); |         self.skip_whitespace(); | ||||||
|         let mut ident: Option<String> = None; |         let mut ident: Option<String> = None; | ||||||
|         let mut len = 0; |  | ||||||
|         while { |         while { | ||||||
|             if let Some(peek) = self.peek(len) { |             if let Some(peek) = self.peek(self.inconfidence) { | ||||||
|                 let lowercase = &peek.to_ascii_lowercase(); |                 let lowercase = &peek.to_ascii_lowercase(); | ||||||
|                 if let Some(id) = &mut ident { |                 if let Some(id) = &mut ident { | ||||||
|                     if ALLOWED_IDENT_CHARS.contains(lowercase) { |                     if ALLOWED_IDENT_CHARS.contains(lowercase) { | ||||||
|                         id.push(peek); |                         id.push(peek); | ||||||
|                         len += 1; |                         self.inconfidence += 1; | ||||||
|                         true |                         true | ||||||
|                     } else { |                     } else { | ||||||
|                         false |                         false | ||||||
| @ -115,7 +124,7 @@ impl Parser { | |||||||
|                 } else { |                 } else { | ||||||
|                     if ALLOWED_IDENT_BEGIN_CHARS.contains(lowercase) { |                     if ALLOWED_IDENT_BEGIN_CHARS.contains(lowercase) { | ||||||
|                         ident = Some(peek.to_string()); |                         ident = Some(peek.to_string()); | ||||||
|                         len += 1; |                         self.inconfidence += 1; | ||||||
|                         true |                         true | ||||||
|                     } else { |                     } else { | ||||||
|                         false |                         false | ||||||
| @ -127,7 +136,6 @@ impl Parser { | |||||||
|         } {} |         } {} | ||||||
|         Expect { |         Expect { | ||||||
|             text: ident, |             text: ident, | ||||||
|             len: len, |  | ||||||
|             parser: self, |             parser: self, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -135,22 +143,21 @@ impl Parser { | |||||||
|     pub fn expect_string_lit(&mut self) -> Expect { |     pub fn expect_string_lit(&mut self) -> Expect { | ||||||
|         self.skip_whitespace(); |         self.skip_whitespace(); | ||||||
|         let mut content: Option<String> = None; |         let mut content: Option<String> = None; | ||||||
|         let mut len = 0; |  | ||||||
|         while { |         while { | ||||||
|             if let Some(peek) = self.peek(len) { |             if let Some(peek) = self.peek(self.inconfidence) { | ||||||
|                 if let Some(cont) = &mut content { |                 if let Some(cont) = &mut content { | ||||||
|                     if peek == '"' { |                     if peek == '"' { | ||||||
|                         len += 1; |                         self.inconfidence += 1; | ||||||
|                         false |                         false | ||||||
|                     } else { |                     } else { | ||||||
|                         cont.push(peek); |                         cont.push(peek); | ||||||
|                         len += 1; |                         self.inconfidence += 1; | ||||||
|                         true |                         true | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if peek == '"' { |                     if peek == '"' { | ||||||
|                         content = Some(String::new()); |                         content = Some(String::new()); | ||||||
|                         len += 1; |                         self.inconfidence += 1; | ||||||
|                         true |                         true | ||||||
|                     } else { |                     } else { | ||||||
|                         false |                         false | ||||||
| @ -162,12 +169,11 @@ impl Parser { | |||||||
|         } {} |         } {} | ||||||
|         Expect { |         Expect { | ||||||
|             text: content, |             text: content, | ||||||
|             len: len, |  | ||||||
|             parser: self, |             parser: self, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn move_cursor(&mut self) { |     pub fn advance_cursor(&mut self) { | ||||||
|         let curr = self.peek(0).unwrap(); |         let curr = self.peek(0).unwrap(); | ||||||
|         self.cursor += 1; |         self.cursor += 1; | ||||||
|         self.character_number += 1; |         self.character_number += 1; | ||||||
| @ -177,9 +183,9 @@ impl Parser { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn move_cursor_multiple(&mut self, amount: usize) { |     pub fn advance_cursor_multiple(&mut self, amount: usize) { | ||||||
|         for _ in 0..amount { |         for _ in 0..amount { | ||||||
|             self.move_cursor(); |             self.advance_cursor(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -187,36 +193,102 @@ impl Parser { | |||||||
|         Position(self.line_number, self.character_number) |         Position(self.line_number, self.character_number) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn skip_whitespace(&mut self) { |     fn skip_whitespace_confident(&mut self, confident: bool) { | ||||||
|         let mut next = ' '; |         let mut next = ' '; | ||||||
|         while self.remaining() > 0 && { |         while self.remaining() > 0 && { | ||||||
|             next = self.peek(0).unwrap(); |             next = self.peek(self.inconfidence).unwrap(); | ||||||
|             next == ' ' || next == '\n' || next == '\r' || next == '\t' |             next == ' ' || next == '\n' || next == '\r' || next == '\t' | ||||||
|         } { |         } { | ||||||
|             self.move_cursor(); |             if confident { | ||||||
|  |                 self.advance_cursor(); | ||||||
|  |             } else { | ||||||
|  |                 self.inconfidence += 1; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     fn skip_whitespace(&mut self) { | ||||||
|  |         self.skip_whitespace_confident(false); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub enum Expectable<T: Into<String>> { | ||||||
|  |     Static(T), | ||||||
|  |     Ident, | ||||||
|  |     StringLit, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct Expect<'a> { | pub struct Expect<'a> { | ||||||
|     text: Option<String>, |     text: Option<String>, | ||||||
|     len: usize, |  | ||||||
|     parser: &'a mut Parser, |     parser: &'a mut Parser, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Expect<'_> { | impl<'a> Expect<'a> { | ||||||
|     pub fn get(self) -> Option<String> { |     pub fn get_inconfident(self) -> Option<String> { | ||||||
|         if self.text.is_some() { |  | ||||||
|             self.parser.move_cursor_multiple(self.len); |  | ||||||
|         } |  | ||||||
|         self.text |         self.text | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get(self) -> Option<String> { | ||||||
|  |         if self.text.is_some() { | ||||||
|  |             self.parser | ||||||
|  |                 .advance_cursor_multiple(self.parser.inconfidence); | ||||||
|  |         } | ||||||
|  |         self.parser.inconfidence = 0; | ||||||
|  |         self.text | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn get_or(self, error: SyntaxError) -> Result<String, SyntaxError> { |     pub fn get_or(self, error: SyntaxError) -> Result<String, SyntaxError> { | ||||||
|         match self.get() { |         match self.get() { | ||||||
|             Some(text) => Ok(text), |             Some(text) => Ok(text), | ||||||
|             None => Err(error), |             None => Err(error), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn and<'b, T: Into<String>>(self, other: Expectable<T>) -> Expects<'a> { | ||||||
|  |         let texts = if let Some(text) = self.text { | ||||||
|  |             Some(vec![text]) | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         }; | ||||||
|  |         Expects::and( | ||||||
|  |             Expects { | ||||||
|  |                 texts: texts, | ||||||
|  |                 parser: self.parser, | ||||||
|  |             }, | ||||||
|  |             other, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_expect<T: Into<String>>(&mut self, expectable: Expectable<T>) -> Expect { | ||||||
|  |         self.parser.expect(expectable) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct Expects<'a> { | ||||||
|  |     texts: Option<Vec<String>>, | ||||||
|  |     parser: &'a mut Parser, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'a> Expects<'a> { | ||||||
|  |     pub fn and<'b, T: Into<String>>(mut self, expect: Expectable<T>) -> Expects<'a> { | ||||||
|  |         let other = self.parser.expect(expect); | ||||||
|  |         if let Some(texts) = &mut self.texts { | ||||||
|  |             if let Some(text) = other.get_inconfident() { | ||||||
|  |                 texts.push(text); | ||||||
|  |             } else { | ||||||
|  |                 self.texts = None; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         self | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get(self) -> Option<Vec<String>> { | ||||||
|  |         if self.texts.is_some() { | ||||||
|  |             self.parser | ||||||
|  |                 .advance_cursor_multiple(self.parser.inconfidence); | ||||||
|  |         } | ||||||
|  |         self.parser.inconfidence = 0; | ||||||
|  |         self.texts | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use super::{Parser, Position, SyntaxError}; | use super::{Expectable, Parser, Position, SyntaxError}; | ||||||
| 
 | 
 | ||||||
| type Ident = String; | type Ident = String; | ||||||
| 
 | 
 | ||||||
| @ -15,17 +15,17 @@ impl Statement { | |||||||
|     pub fn parse(parser: &mut Parser) -> Result<Statement, SyntaxError> { |     pub fn parse(parser: &mut Parser) -> Result<Statement, SyntaxError> { | ||||||
|         let pos = parser.pos(); |         let pos = parser.pos(); | ||||||
| 
 | 
 | ||||||
|         if let Some(_) = parser.expect("let").get() { |         if let Some(_) = parser.expect_static("let").get() { | ||||||
|             let ident = parser |             let ident = parser | ||||||
|                 .expect_ident() |                 .expect_ident() | ||||||
|                 .get_or(SyntaxError::ExpectedIdent(pos))?; |                 .get_or(SyntaxError::ExpectedIdent(pos))?; | ||||||
|             parser |             parser | ||||||
|                 .expect("=") |                 .expect_static("=") | ||||||
|                 .get_or(SyntaxError::ExpectedToken(pos, '='))?; |                 .get_or(SyntaxError::ExpectedToken(pos, '='))?; | ||||||
|             match Expression::parse(parser) { |             match Expression::parse(parser) { | ||||||
|                 Ok(expr) => { |                 Ok(expr) => { | ||||||
|                     parser |                     parser | ||||||
|                         .expect(";") |                         .expect_static(";") | ||||||
|                         .get_or(SyntaxError::ExpectedToken(pos, ';'))?; |                         .get_or(SyntaxError::ExpectedToken(pos, ';'))?; | ||||||
|                     Ok(Statement::LetStatement(pos, ident, Box::new(expr))) |                     Ok(Statement::LetStatement(pos, ident, Box::new(expr))) | ||||||
|                 } |                 } | ||||||
| @ -36,7 +36,7 @@ impl Statement { | |||||||
|                 Ok(expr) => { |                 Ok(expr) => { | ||||||
|                     let statement = Statement::ExprStatement(pos, expr); |                     let statement = Statement::ExprStatement(pos, expr); | ||||||
|                     parser |                     parser | ||||||
|                         .expect(";") |                         .expect_static(";") | ||||||
|                         .get_or(SyntaxError::ExpectedToken(pos, ';'))?; |                         .get_or(SyntaxError::ExpectedToken(pos, ';'))?; | ||||||
|                     Ok(statement) |                     Ok(statement) | ||||||
|                 } |                 } | ||||||
| @ -49,6 +49,7 @@ impl Statement { | |||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub enum Expression { | pub enum Expression { | ||||||
|     BlockExpr(Position, Vec<Statement>), |     BlockExpr(Position, Vec<Statement>), | ||||||
|  |     FunctionCall(Position, Ident, Vec<Expression>), | ||||||
|     ValueRef(Position, Pattern), |     ValueRef(Position, Pattern), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -56,8 +57,7 @@ impl Expression { | |||||||
|     pub fn parse(parser: &mut Parser) -> Result<Expression, SyntaxError> { |     pub fn parse(parser: &mut Parser) -> Result<Expression, SyntaxError> { | ||||||
|         let begin_pos = parser.pos(); |         let begin_pos = parser.pos(); | ||||||
| 
 | 
 | ||||||
|         let expect = parser.expect("{"); |         if let Some(_) = parser.expect_static("{").get() { | ||||||
|         if let Some(_) = expect.get() { |  | ||||||
|             let mut statement_list = Vec::new(); |             let mut statement_list = Vec::new(); | ||||||
|             while { |             while { | ||||||
|                 match Statement::parse(parser) { |                 match Statement::parse(parser) { | ||||||
| @ -68,11 +68,38 @@ impl Expression { | |||||||
|                     Err(_) => false, |                     Err(_) => false, | ||||||
|                 } |                 } | ||||||
|             } {} |             } {} | ||||||
|             if let Some(_) = parser.expect("}").get() { |             if let Some(_) = parser.expect_static("}").get() { | ||||||
|                 Ok(Expression::BlockExpr(begin_pos, statement_list)) |                 Ok(Expression::BlockExpr(begin_pos, statement_list)) | ||||||
|             } else { |             } else { | ||||||
|                 Err(SyntaxError::ExpectedToken(parser.pos(), '}')) |                 Err(SyntaxError::ExpectedToken(parser.pos(), '}')) | ||||||
|             } |             } | ||||||
|  |         } else if let Some(texts) = parser.expect_ident().and(Expectable::Static("(")).get() { | ||||||
|  |             let name = texts.get(0).unwrap(); | ||||||
|  |             let mut arg_list = Vec::new(); | ||||||
|  |             while { | ||||||
|  |                 match Expression::parse(parser) { | ||||||
|  |                     Ok(exp) => { | ||||||
|  |                         arg_list.push(exp); | ||||||
|  |                         if let Some(_) = parser.expect_static(",").get() { | ||||||
|  |                             true | ||||||
|  |                         } else { | ||||||
|  |                             false | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     Err(err) => { | ||||||
|  |                         if arg_list.is_empty() { | ||||||
|  |                             false | ||||||
|  |                         } else { | ||||||
|  |                             return Err(err); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } {} | ||||||
|  |             let pos = parser.pos(); | ||||||
|  |             parser | ||||||
|  |                 .expect_static(")") | ||||||
|  |                 .get_or(SyntaxError::ExpectedToken(pos, ')'))?; | ||||||
|  |             Ok(Expression::FunctionCall(pos, name.clone(), arg_list)) | ||||||
|         } else if let Ok(pattern) = Pattern::parse(parser) { |         } else if let Ok(pattern) = Pattern::parse(parser) { | ||||||
|             Ok(Expression::ValueRef(begin_pos, pattern)) |             Ok(Expression::ValueRef(begin_pos, pattern)) | ||||||
|         } else { |         } else { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user