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";
let botus = otus;
print();

View File

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

View File

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

View File

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