#![allow(missing_docs)]
use super::Parser;
use crate::ast::{Binding, CaseClause, CaseLambdaClause, CondClause, Expr, Formals, GuardClause, KeywordParam, ParameterBinding};
use crate::diagnostics::{Error, Result, Span, Spanned};
use crate::lexer::TokenKind;
use std::collections::HashMap;
impl Parser {
pub fn parse_quote_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let expr = self.parse_expression()?;
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after quote")?;
let end_span = self.current_span();
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Quote(Box::new(expr)), span))
}
pub fn parse_lambda_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let formals = self.parse_formals()?;
let metadata = self.parse_metadata_exprs()?;
let mut body = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
body.push(self.parse_expression()?);
}
if body.is_empty() {
return Err(Box::new(Error::parse_error(
"Lambda body cannot be empty",
self.current_span(),
)))
}
let end_span = self.current_span();
self.advance(); let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::Lambda { formals, metadata, body },
span,
))
}
pub fn parse_if_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let test = Box::new(self.parse_expression()?);
let consequent = Box::new(self.parse_expression()?);
let alternative = if !self.check(&TokenKind::RightParen) {
Some(Box::new(self.parse_expression()?))
} else {
None
};
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after if")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::If { test, consequent, alternative },
span,
))
}
pub fn parse_define_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("define form", |parser| {
let first = parser.parse_expression()?;
match first.inner {
Expr::Identifier(name) => {
let metadata = parser.parse_metadata_exprs()?;
let value = Box::new(parser.parse_expression()?);
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after define")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::Define { name, value, metadata },
span,
))
}
Expr::Application { operator, operands } => {
if let Expr::Identifier(name) = &operator.inner {
let formals = parser.operands_to_formals(operands)?;
let metadata = parser.parse_metadata_exprs()?;
let body = parser.parse_body()?;
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after define")?;
let span = start_span.combine(end_span);
let lambda_span = operator.span.combine(end_span);
let lambda_expr = Spanned::new(
Expr::Lambda { formals, metadata: HashMap::new(), body },
lambda_span,
);
Ok(Spanned::new(
Expr::Define {
name: name.clone(),
value: Box::new(lambda_expr),
metadata
},
span,
))
} else {
Err(Box::new(Error::parse_error(
"Expected identifier as function name in define",
operator.span,
)))
}
}
_ => {
Err(Box::new(Error::parse_error(
"Expected identifier or function signature in define",
first.span,
)))
}
}
})
}
pub fn parse_set_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("set! form", |parser| {
let name_expr = parser.parse_expression()?;
let name = match name_expr.inner {
Expr::Identifier(name) => name,
_ => return Err(Box::new(Error::parse_error(
"Expected identifier in set!",
name_expr.span,
))),
};
let value = Box::new(parser.parse_expression()?);
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after set!")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Set { name, value }, span))
})
}
pub fn parse_define_syntax_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("define-syntax form", |parser| {
let name_expr = parser.parse_expression()?;
let name = match name_expr.inner {
Expr::Identifier(name) => name,
_ => return Err(Box::new(Error::parse_error(
"Expected identifier in define-syntax",
name_expr.span,
))),
};
let transformer = Box::new(parser.parse_expression()?);
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after define-syntax")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::DefineSyntax { name, transformer },
span,
))
})
}
pub fn parse_syntax_rules_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("syntax-rules form", |parser| {
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for literals list")?;
parser.skip_whitespace();
let mut literals = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
if !parser.check(&TokenKind::Identifier) {
return Err(Box::new(Error::parse_error(
"Expected identifier in literals list",
parser.current_span(),
)))
}
literals.push(parser.current_token().text.clone());
parser.advance();
parser.skip_whitespace();
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for literals list")?;
parser.skip_whitespace();
let mut rules = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for syntax rule")?;
parser.skip_whitespace();
let pattern = parser.parse_expression()?;
parser.skip_whitespace();
let template = parser.parse_expression()?;
parser.skip_whitespace();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for syntax rule")?;
parser.skip_whitespace();
rules.push((pattern, template))
}
if rules.is_empty() {
return Err(Box::new(Error::parse_error(
"syntax-rules must have at least one rule",
parser.current_span(),
)))
}
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after syntax-rules")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::SyntaxRules { literals, rules },
span,
))
})
}
pub fn parse_call_cc_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let expr = Box::new(self.parse_expression()?);
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after call/cc")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::CallCC(expr), span))
}
pub fn parse_primitive_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let name_expr = self.parse_expression()?;
let name = match name_expr.inner {
Expr::Identifier(name) => name,
Expr::Literal(crate::ast::Literal::String(name)) => name,
_ => return Err(crate::diagnostics::Error::parse_error(
"Expected symbol or string in primitive",
name_expr.span,
).boxed()),
};
let mut args = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
args.push(self.parse_expression()?);
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after primitive")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Primitive { name, args }, span))
}
pub fn parse_type_annotation_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let expr = Box::new(self.parse_expression()?);
let type_expr = Box::new(self.parse_expression()?);
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after type annotation")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::TypeAnnotation { expr, type_expr },
span,
))
}
pub fn parse_begin_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let mut exprs = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
exprs.push(self.parse_expression()?);
}
if exprs.is_empty() {
return Err(crate::diagnostics::Error::parse_error(
"Begin form cannot be empty",
self.current_span(),
).into())
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after begin")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Begin(exprs), span))
}
pub fn parse_let_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let bindings = self.parse_bindings()?;
let body = self.parse_body()?;
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after let")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Let { bindings, body }, span))
}
pub fn parse_let_star_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let bindings = self.parse_bindings()?;
let body = self.parse_body()?;
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after let*")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::LetStar { bindings, body }, span))
}
pub fn parse_letrec_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let bindings = self.parse_bindings()?;
let body = self.parse_body()?;
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after letrec")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::LetRec { bindings, body }, span))
}
pub fn parse_cond_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let mut clauses = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for cond clause")?;
self.skip_whitespace();
let test = self.parse_expression()?;
self.skip_whitespace();
let mut body = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
body.push(self.parse_expression()?);
self.skip_whitespace();
}
if body.is_empty() {
return Err(Box::new(Error::parse_error(
"Cond clause must have at least one body expression",
self.current_span(),
)))
}
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for cond clause")?;
self.skip_whitespace();
clauses.push(CondClause { test, body });
}
if clauses.is_empty() {
return Err(Box::new(Error::parse_error(
"Cond form must have at least one clause",
self.current_span(),
)))
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after cond")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Cond(clauses), span))
}
pub fn parse_case_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let expr = Box::new(self.parse_expression()?);
self.skip_whitespace();
let mut clauses = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for case clause")?;
self.skip_whitespace();
let values = if self.check(&TokenKind::Identifier)
&& self.current_token().text == "else" {
self.advance(); Vec::new()
} else {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for case values")?;
self.skip_whitespace();
let mut values = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
values.push(self.parse_expression()?);
self.skip_whitespace();
}
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for case values")?;
values
};
self.skip_whitespace();
let mut body = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
body.push(self.parse_expression()?);
self.skip_whitespace();
}
if body.is_empty() {
return Err(Box::new(Error::parse_error(
"Case clause must have at least one body expression",
self.current_span(),
)))
}
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for case clause")?;
self.skip_whitespace();
clauses.push(CaseClause { values, body });
}
if clauses.is_empty() {
return Err(Box::new(Error::parse_error(
"Case form must have at least one clause",
self.current_span(),
)))
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after case")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Case { expr, clauses }, span))
}
pub fn parse_and_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let mut exprs = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
exprs.push(self.parse_expression()?);
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after and")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::And(exprs), span))
}
pub fn parse_or_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let mut exprs = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
exprs.push(self.parse_expression()?);
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after or")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Or(exprs), span))
}
pub fn parse_when_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let test = Box::new(self.parse_expression()?);
let body = self.parse_body()?;
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after when")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::When { test, body }, span))
}
pub fn parse_unless_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let test = Box::new(self.parse_expression()?);
let body = self.parse_body()?;
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after unless")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Unless { test, body }, span))
}
pub fn parse_parameterize_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("parameterize form", |parser| {
let bindings = parser.parse_parameter_bindings()?;
let body = parser.parse_body()?;
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after parameterize")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Parameterize { bindings, body }, span))
})
}
pub fn parse_guard_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("guard form", |parser| {
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for guard variable and clauses")?;
parser.skip_whitespace();
if !parser.check(&TokenKind::Identifier) {
return Err(Box::new(Error::parse_error(
"Expected identifier for guard variable",
parser.current_span(),
)))
}
let variable = parser.current_token().text.clone();
parser.advance();
parser.skip_whitespace();
let mut clauses = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for guard clause")?;
parser.skip_whitespace();
let test = parser.parse_expression()?;
parser.skip_whitespace();
let mut arrow = None;
let mut body = Vec::new();
if parser.check(&TokenKind::Identifier) && parser.current_token().text == "=>" {
parser.advance(); parser.skip_whitespace();
arrow = Some(parser.parse_expression()?);
} else {
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
body.push(parser.parse_expression()?);
parser.skip_whitespace();
}
if body.is_empty() && arrow.is_none() {
return Err(Box::new(Error::parse_error(
"Guard clause must have at least one body expression or => clause",
parser.current_span(),
)))
}
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for guard clause")?;
parser.skip_whitespace();
clauses.push(GuardClause { test, body, arrow });
}
if clauses.is_empty() {
return Err(Box::new(Error::parse_error(
"Guard form must have at least one clause",
parser.current_span(),
)))
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for guard clauses")?;
parser.skip_whitespace();
let body = parser.parse_body()?;
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after guard")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Guard { variable, clauses, body }, span))
})
}
pub fn parse_case_lambda_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("case-lambda form", |parser| {
let metadata = HashMap::new(); let mut clauses = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
parser.skip_whitespace();
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for case-lambda clause")?;
parser.skip_whitespace();
let formals = parser.parse_formals()?;
parser.skip_whitespace();
let mut body = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
body.push(parser.parse_expression()?);
parser.skip_whitespace();
}
if body.is_empty() {
return Err(Box::new(Error::parse_error(
"Case-lambda clause must have at least one body expression",
parser.current_span(),
)))
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for case-lambda clause")?;
parser.skip_whitespace();
clauses.push(CaseLambdaClause { formals, body });
}
if clauses.is_empty() {
return Err(Box::new(Error::parse_error(
"Case-lambda form must have at least one clause",
parser.current_span(),
)))
}
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after case-lambda")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::CaseLambda { clauses, metadata }, span))
})
}
pub fn parse_formals(&mut self) -> Result<Formals> {
if self.check(&TokenKind::LeftParen) {
self.advance(); self.skip_whitespace();
let mut fixed = Vec::new();
let mut rest = None;
let mut keywords = Vec::new();
let mut seen_keyword = false;
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
if self.check(&TokenKind::Dot) {
self.advance(); self.skip_whitespace();
if !self.check(&TokenKind::Identifier) {
return Err(Box::new(Error::parse_error(
"Expected identifier after dot in formals",
self.current_span(),
)))
}
let rest_name = self.current_token().text.clone();
self.advance();
rest = Some(rest_name);
break;
} else if self.check(&TokenKind::Keyword) {
seen_keyword = true;
let keyword_token = self.current_token();
let keyword_name = keyword_token.text
.strip_prefix("#:")
.unwrap_or(&keyword_token.text)
.to_string();
self.advance();
self.skip_whitespace();
let default = if !self.check(&TokenKind::RightParen)
&& !self.check(&TokenKind::Keyword) {
Some(self.parse_expression()?)
} else {
None
};
keywords.push(KeywordParam {
name: keyword_name,
default,
});
} else if self.check(&TokenKind::Identifier) {
if seen_keyword {
return Err(Box::new(Error::parse_error(
"Cannot mix positional and keyword parameters",
self.current_span(),
)))
}
let param_name = self.current_token().text.clone();
self.advance();
fixed.push(param_name);
} else {
return Err(Box::new(Error::parse_error(
"Expected identifier or keyword in formals",
self.current_span(),
)))
}
self.skip_whitespace();
}
if !self.check(&TokenKind::RightParen) {
return Err(Box::new(Error::parse_error(
"Expected closing parenthesis in formals",
self.current_span(),
)))
}
self.advance();
let formals = if !keywords.is_empty() {
Formals::Keyword { fixed, rest, keywords }
} else if let Some(rest_param) = rest {
if fixed.is_empty() {
Formals::Variable(rest_param)
} else {
Formals::Mixed { fixed, rest: rest_param }
}
} else {
Formals::Fixed(fixed)
};
Parser::validate_formals(&formals, self.current_span())?;
Ok(formals)
} else if self.check(&TokenKind::Identifier) {
let name = self.current_token().text.clone();
Parser::validate_identifier(&name, self.current_span())?;
self.advance();
Ok(Formals::Variable(name))
} else {
Err(Box::new(Error::parse_error(
format!("Expected formals list or identifier, found {}",
self.current_token_text()),
self.current_span(),
)))
}
}
fn parse_parameter_bindings(&mut self) -> Result<Vec<ParameterBinding>> {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for parameter bindings")?;
self.skip_whitespace();
let mut bindings = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for parameter binding")?;
self.skip_whitespace();
let parameter = self.parse_expression()?;
self.skip_whitespace();
let value = self.parse_expression()?;
self.skip_whitespace();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for parameter binding")?;
self.skip_whitespace();
bindings.push(ParameterBinding { parameter, value });
}
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for parameter bindings")?;
Ok(bindings)
}
fn parse_bindings(&mut self) -> Result<Vec<Binding>> {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for bindings")?;
self.skip_whitespace();
let mut bindings = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
self.consume(&TokenKind::LeftParen, "Expected opening parenthesis for binding")?;
self.skip_whitespace();
if !self.check(&TokenKind::Identifier) {
return Err(Box::new(Error::parse_error(
"Expected identifier in binding",
self.current_span(),
)))
}
let name = self.current_token().text.clone();
self.advance();
self.skip_whitespace();
let value = self.parse_expression()?;
self.skip_whitespace();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for binding")?;
self.skip_whitespace();
bindings.push(Binding { name, value });
}
self.consume(&TokenKind::RightParen, "Expected closing parenthesis for bindings")?;
Ok(bindings)
}
pub fn parse_body(&mut self) -> Result<Vec<Spanned<Expr>>> {
let mut body = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
body.push(self.parse_expression()?);
}
if body.is_empty() {
return Err(Box::new(Error::parse_error(
"Body cannot be empty",
self.current_span(),
)))
}
Ok(body)
}
pub fn operands_to_formals(&self, operands: Vec<Spanned<Expr>>) -> Result<Formals> {
let mut fixed_params = Vec::new();
let mut rest_param = None;
let mut _found_dot = false;
for (i, operand) in operands.iter().enumerate() {
match &operand.inner {
Expr::Identifier(name) => {
if name == "." {
if _found_dot {
return Err(Box::new(Error::parse_error(
"Multiple dots in formal parameter list",
operand.span,
)))
}
if i == operands.len() - 1 {
return Err(Box::new(Error::parse_error(
"Expected rest parameter after dot",
operand.span,
)))
}
if i == operands.len() - 2 {
if let Expr::Identifier(rest_name) = &operands[i + 1].inner {
rest_param = Some(rest_name.clone());
_found_dot = true;
break;
} else {
return Err(Box::new(Error::parse_error(
"Expected identifier as rest parameter",
operands[i + 1].span,
)))
}
} else {
return Err(Box::new(Error::parse_error(
"Dot must be followed by exactly one rest parameter",
operand.span,
)))
}
} else if !_found_dot {
fixed_params.push(name.clone());
}
}
_ => {
return Err(Box::new(Error::parse_error(
"Expected identifier in formal parameter list",
operand.span,
)))
}
}
}
let formals = if let Some(rest) = rest_param {
Formals::Mixed { fixed: fixed_params, rest }
} else {
Formals::Fixed(fixed_params)
};
Parser::validate_formals(&formals, operands.first().map(|e| e.span).unwrap_or(Span::new(0, 0)))?;
Ok(formals)
}
pub fn parse_import_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
let mut import_specs = Vec::new();
while !self.check(&TokenKind::RightParen) && !self.is_at_end() {
import_specs.push(self.parse_expression()?);
self.skip_whitespace();
}
if import_specs.is_empty() {
return Err(Box::new(Error::parse_error(
"Import form requires at least one import specification",
self.current_span(),
)))
}
let end_span = self.current_span();
self.consume(&TokenKind::RightParen, "Expected closing parenthesis after import")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(Expr::Import { import_specs }, span))
}
pub fn parse_define_library_form(&mut self, start_span: Span) -> Result<Spanned<Expr>> {
self.with_context("define-library form", |parser| {
parser.consume(&TokenKind::LeftParen, "Expected opening parenthesis for library name")?;
parser.skip_whitespace();
let mut name_parts = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
if parser.check(&TokenKind::Identifier) || parser.check(&TokenKind::IntegerNumber) {
let name = parser.current_token().text.clone();
name_parts.push(name);
parser.advance();
} else {
return Err(Box::new(Error::parse_error(
"Library name parts must be identifiers or numbers",
parser.current_span(),
)))
}
parser.skip_whitespace();
}
if name_parts.is_empty() {
return Err(Box::new(Error::parse_error(
"Library name cannot be empty",
parser.current_span(),
)))
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for library name")?;
parser.skip_whitespace();
let mut imports = Vec::new();
let mut exports = Vec::new();
let mut body = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
if parser.check(&TokenKind::LeftParen) {
let declaration_start_span = parser.current_span();
parser.advance(); parser.skip_whitespace();
if parser.check(&TokenKind::Identifier) {
let keyword = parser.current_token().text.clone();
parser.advance();
parser.skip_whitespace();
match keyword.as_str() {
"import" => {
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
imports.push(parser.parse_expression()?);
parser.skip_whitespace();
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for import declaration")?;
}
"export" => {
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
exports.push(parser.parse_expression()?);
parser.skip_whitespace();
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for export declaration")?;
}
_ => {
let mut content = Vec::new();
while !parser.check(&TokenKind::RightParen) && !parser.is_at_end() {
content.push(parser.parse_expression()?);
parser.skip_whitespace();
}
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis for library declaration")?;
let declaration_expr = Expr::List({
let mut decl = vec![Spanned::new(Expr::Identifier(keyword), declaration_start_span)];
decl.extend(content);
decl
});
body.push(Spanned::new(declaration_expr, declaration_start_span))
}
}
} else {
return Err(Box::new(Error::parse_error(
"Expected identifier in library declaration",
parser.current_span(),
)))
}
} else {
return Err(Box::new(Error::parse_error(
"Expected library declaration (list starting with identifier)",
parser.current_span(),
)))
}
parser.skip_whitespace();
}
let end_span = parser.current_span();
parser.consume(&TokenKind::RightParen, "Expected closing parenthesis after define-library")?;
let span = start_span.combine(end_span);
Ok(Spanned::new(
Expr::DefineLibrary { name: name_parts, imports, exports, body },
span,
))
})
}
}