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