Skip to content

Commit

Permalink
Merge branch 'kast-lang:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
bhavyakukkar authored Oct 3, 2024
2 parents cb3956f + d1362bb commit b84b483
Show file tree
Hide file tree
Showing 13 changed files with 512 additions and 423 deletions.
4 changes: 2 additions & 2 deletions .justfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ test:
nix flake check

repl:
just run --repl
cargo run -- repl

run *ARGS:
cargo run -- {{ARGS}}
cargo run -- run {{ARGS}}

serve:
cd website && zola serve
Expand Down
57 changes: 34 additions & 23 deletions crates/ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::HashSet;
use std::sync::Arc;
use std::{borrow::Cow, collections::HashSet};

use kast_util::*;

Expand All @@ -13,7 +13,6 @@ pub use syntax::{Associativity, Priority, Syntax, SyntaxDefinition, SyntaxDefini
use lexer::*;
use syntax::{BindingPower, Edge};

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum Ast<Data = Span> {
Simple {
Expand Down Expand Up @@ -141,28 +140,32 @@ pub fn parse(syntax: &Syntax, source: SourceFile) -> Result<Option<Ast>, Error>
}

pub fn read_syntax(source: SourceFile) -> Result<Syntax, Error> {
let mut reader = lex(source)?;
let result = (|| {
let mut syntax = Syntax::empty();
loop {
let should_skip = |token: &Token| match token {
Token::Punctuation { raw } if raw == ";" => true,
Token::Comment { .. } => true,
_ => false,
};
while should_skip(&reader.peek().unwrap().token) {
reader.next().unwrap();
let ast = parse(&Syntax::empty(), source)?;
let mut syntax = Syntax::empty();
fn collect_syntax_definitions(syntax: &mut Syntax, ast: Ast) -> Result<(), Error> {
match ast {
Ast::Simple { .. } => {}
Ast::Complex {
definition: _,
values,
data: _,
} => {
for (_name, value) in values {
collect_syntax_definitions(syntax, value)?;
}
}

if reader.peek().unwrap().is_eof() {
break;
Ast::SyntaxDefinition { def, data: span } => {
syntax
.insert(def)
.map_err(|ErrorMessage(message)| Error { message, span })?;
}
let def = read_syntax_def(&mut reader)?.0;
syntax.insert(Arc::new(def)).unwrap();
}
Ok(syntax)
})();
result.map_err(|msg: ErrorMessage| msg.at(reader.peek().unwrap().span.clone()))
Ok(())
}
if let Some(ast) = ast {
collect_syntax_definitions(&mut syntax, ast)?;
}
Ok(syntax)
}

pub struct Parser {
Expand Down Expand Up @@ -479,14 +482,22 @@ impl Parser {
return Ok(None);
}
tracing::trace!("starting to read expr with outer_bp={outer_bp:?}");
let mut syntax = Cow::Borrowed(syntax);
let mut already_parsed = None;
loop {
tracing::trace!(
"trying to read one more node with already_parsed={}",
display_option(&already_parsed),
);
match self.read_one(syntax, continuation_keywords, already_parsed, outer_bp)? {
ReadOneResult::Progress(value) => already_parsed = Some(value),
match self.read_one(&syntax, continuation_keywords, already_parsed, outer_bp)? {
ReadOneResult::Progress(value) => {
if let Ast::SyntaxDefinition { def, data: _ } = &value {
let mut new_syntax = syntax.into_owned();
new_syntax.insert(def.clone())?;
syntax = Cow::Owned(new_syntax);
}
already_parsed = Some(value);
}
ReadOneResult::NoProgress(value) => {
match &value {
Some(value) => tracing::trace!("read expr - done! parsed {value}"),
Expand Down
4 changes: 4 additions & 0 deletions crates/ast/tests/syntax.ks
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
syntax then -> 0 = _ ";" _;
syntax then -> 0 = _ ";";

syntax add <- 20 = lhs "+" rhs;
syntax sub <- 20 = lhs "-" rhs;
syntax mul <- 30 = lhs "*" rhs;
syntax call <- 50 = f args;

syntax scoped <- 1000 = "(" e ")";
14 changes: 13 additions & 1 deletion crates/util/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,25 @@ impl<T> Tuple<T> {
named_order: vec![],
}
}
pub fn single_named(name: impl Into<String>, value: T) -> Self {
let mut result = Self::empty();
result.add_named(name, value);
result
}
pub fn is_empty(&self) -> bool {
self.unnamed.is_empty() && self.named.is_empty()
}
pub fn get_unnamed(&self) -> &[T] {
&self.unnamed
}
pub fn get_named(&self, name: &str) -> Option<&T> {
self.named.get(name)
}
pub fn add_unnamed(&mut self, value: T) {
self.unnamed.push(value);
}
pub fn add_named(&mut self, name: String, value: T) {
pub fn add_named(&mut self, name: impl Into<String>, value: T) {
let name: String = name.into();
self.named_order.push(name.clone());
self.named.insert(name, value);
}
Expand Down
3 changes: 3 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::path::PathBuf;

#[derive(clap::Subcommand)]
pub enum Command {
ParseAst,
Repl,
Run { path: PathBuf },
}

#[derive(clap::Parser)]
Expand Down
Loading

0 comments on commit b84b483

Please sign in to comment.