add objects and object types

This commit is contained in:
Mark
2023-11-30 15:44:51 +01:00
parent 9c0d55788f
commit 3d1ce384d0
11 changed files with 421 additions and 11 deletions

View File

@@ -180,15 +180,24 @@ impl Source {
self.i += ch.len_utf8();
Some(ch)
}
fn word_splitter(ch: char) -> bool {
fn word_splitter_no_colon(ch: char) -> bool {
ch.is_whitespace() || ".,;[](){}/<".contains(ch)
}
fn word_splitter(ch: char) -> bool {
Self::word_splitter_no_colon(ch) || ch == ':'
}
pub fn peek_word(&self) -> &str {
self.src[self.i..]
.split(Self::word_splitter)
.next()
.unwrap_or("")
}
pub fn peek_word_allow_colon(&self) -> &str {
self.src[self.i..]
.split(Self::word_splitter_no_colon)
.next()
.unwrap_or("")
}
pub fn next_word(&mut self) -> &str {
self.end_sections();
let word = self.src[self.i..]
@@ -198,6 +207,15 @@ impl Source {
self.i += word.len();
word
}
pub fn next_word_allow_colon(&mut self) -> &str {
self.end_sections();
let word = self.src[self.i..]
.split(Self::word_splitter_no_colon)
.next()
.unwrap_or("");
self.i += word.len();
word
}
pub fn peek_line(&self) -> &str {
self.src[self.i..].lines().next().unwrap_or("")
}

View File

@@ -35,15 +35,15 @@ pub fn parse(
);
}
src.skip_whitespace();
if src.peek_word() == ":=" {
src.next_word();
if src.peek_word_allow_colon() == ":=" {
src.next_word_allow_colon();
// [[name] := statement]
let statement = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `[...]` type annotation")))
.msg(format!("EOF after `[[...] := ...]` type definition")))
}
Err(e) => return Err(e),
};
@@ -113,10 +113,10 @@ pub fn parse(
};
let mut pos_after_first = src.get_pos();
src.skip_whitespace();
match src.peek_word() {
match src.peek_word_allow_colon() {
":=" => {
let pos_in_src = src.get_pos();
src.next_word();
src.next_word_allow_colon();
let source = parse(src, srca)?.ok_or_else(|| {
CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
@@ -130,7 +130,7 @@ pub fn parse(
}
"=" => {
let pos_in_src = src.get_pos();
src.next_word();
src.next_word_allow_colon();
let source = parse(src, srca)?.ok_or_else(|| {
CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
@@ -144,7 +144,7 @@ pub fn parse(
}
"->" => {
let pos_in_src = src.get_pos();
src.next_word();
src.next_word_allow_colon();
let run = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
@@ -303,8 +303,50 @@ pub fn parse_no_chain(
}
}
Some('{') => {
// try: is this an object?
let pos_in_src = src.get_pos();
src.next_char();
let pos_in_src_after_bracket = src.get_pos();
{
let mut elems = vec![];
loop {
src.skip_whitespace();
if src.peek_char() == Some('}') {
src.next_char();
return Ok(Some(Box::new(program::parsed::object::Object {
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
elems,
})));
}
let name = src.next_word().to_owned();
src.skip_whitespace();
match src.next_char() {
Some(':') => elems.push((
name,
match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `:` in object")))
}
Err(e) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("Error in statement after `:` in object"))
.err(e))
}
},
)),
_ => {
// not an object (or invalid syntax)
src.set_pos(pos_in_src_after_bracket);
break;
}
}
}
}
// if not an object
let statements = parse_multiple(src, srca, "}")?;
return Ok(Some(Box::new(program::parsed::block::Block {
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),

View File

@@ -12,6 +12,7 @@ use super::Source;
pub enum ParsedType {
Reference(Vec<Self>),
Tuple(Vec<Vec<Self>>),
Object(Vec<(String, Vec<Self>)>),
Type(String),
TypeWithInfo(String, String),
}
@@ -54,6 +55,7 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
} else {
loop {
inner.push(parse_type(src, srca)?);
src.skip_whitespace();
match src.peek_char() {
Some(')') => {
src.next_char();
@@ -82,6 +84,42 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
}
ParsedType::Tuple(inner)
}
// Object
Some('{') => {
let pos_in_src = src.get_pos();
src.next_char();
src.section_begin("parse tuple's inner types".to_string());
let mut inner = vec![];
src.skip_whitespace();
if let Some('}') = src.peek_char() {
// empty object, don't even start the loop
} else {
loop {
src.skip_whitespace();
let field = src.next_word().to_owned();
src.skip_whitespace();
if src.next_char() != Some(':') {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("Expected colon ':' in object type")));
}
src.skip_whitespace();
inner.push((field, parse_type(src, srca)?));
src.skip_whitespace();
match src.peek_char() {
Some('}') => {
src.next_char();
break;
}
Some(',') => {
src.next_char();
}
_ => (),
}
}
}
ParsedType::Object(inner)
}
Some(_) => {
let t = src.next_word().to_owned();
src.skip_whitespace();
@@ -131,6 +169,13 @@ pub fn type_from_parsed(
.map(|v| type_from_parsed(v, info))
.collect::<Result<_, _>>()?,
)),
ParsedType::Object(o) => Arc::new(data::object::ObjectT(
o.iter()
.map(|(s, v)| -> Result<_, CheckError> {
Ok((s.clone(), type_from_parsed(v, info)?))
})
.collect::<Result<_, _>>()?,
)),
ParsedType::Type(name) => match info
.scopes
.iter()