Add functions

This commit is contained in:
Sofia 2020-06-24 19:29:16 +03:00
parent cf0f4fc0b9
commit 86c2b13d1a
4 changed files with 136 additions and 37 deletions

View File

@ -1,2 +1 @@
let otus = "dotus"; print();
let botus = otus;

View File

@ -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()) {

View File

@ -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)]

View File

@ -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 {