use super::build::AstBuilder;
use super::helpers::*;
use crate::ast::*;
use crate::error::{ParseError, Result};
use crate::sexp::SExp;
crate::build_enum_parser!(
parse_binop,
BinOp,
[Add, Sub, Mul, Div, Rem, And, Or, BitAnd, BitOr, BitXor, Shl, Shr, Eq, Ne, Lt, Le, Gt, Ge]
);
crate::build_enum_parser!(parse_unop, UnOp, [Not, Neg, Deref]);
impl AstBuilder {
pub fn build_block(&mut self, sexp: &SExp) -> Result<Block> {
let list = expect_node_type(expect_list(sexp)?, "Block")?;
let kwargs = parse_kwargs(list)?;
let stmts = if let Some(stmts_sexp) = kwargs.get("stmts") {
let stmts_list = expect_list(stmts_sexp)?;
let mut statements = Vec::new();
for stmt_sexp in &stmts_list.elements {
statements.push(self.build_stmt(stmt_sexp)?);
}
statements
} else {
Vec::new()
};
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
Ok(Block::new(stmts, id, span))
}
pub fn build_expr(&mut self, sexp: &SExp) -> Result<Expr> {
let list = expect_node_type(expect_list(sexp)?, "Expr")?;
let kwargs = parse_kwargs(list)?;
let kind = self.build_expr_kind(require_field(&kwargs, "kind", list.pos)?)?;
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
Ok(Expr { id, kind, span, attrs: Vec::new(), tokens: None })
}
fn build_expr_kind(&mut self, sexp: &SExp) -> Result<ExprKind> {
let list = expect_list(sexp)?;
let node_type = expect_symbol(&list.elements[0])?;
match node_type.value.as_str() {
"If" | "Match" | "While" | "ForLoop" | "Loop" => {
self.build_control_flow_expr(&node_type.value, list)
}
"Binary" | "Unary" => self.build_operator_expr(&node_type.value, list),
"Call" | "MethodCall" => self.build_call_expr(&node_type.value, list),
"Array" | "Tuple" | "Struct" => self.build_collection_expr(&node_type.value, list),
"Field" | "Index" => self.build_access_expr(&node_type.value, list),
"Assign" | "Closure" | "Range" | "MacCall" | "Paren" | "Try" | "Cast" | "Break"
| "Continue" | "Return" => self.build_other_expr(&node_type.value, list),
"Path" | "Lit" => self.build_basic_expr(&node_type.value, list),
_ => Err(ParseError::Expected {
expected: "Supported ExprKind variant".to_string(),
found: node_type.value.clone(),
pos: node_type.pos,
}),
}
}
fn build_control_flow_expr(
&mut self,
node_type: &str,
list: &crate::sexp::List,
) -> Result<ExprKind> {
match node_type {
"If" => {
let kwargs = parse_kwargs(list)?;
let cond = Box::new(self.build_expr(require_field(&kwargs, "cond", list.pos)?)?);
let then_branch = self.build_block(require_field(&kwargs, "then", list.pos)?)?;
let else_branch = if let Some(else_sexp) = optional_field(&kwargs, "else") {
Some(Box::new(self.build_expr(else_sexp)?))
} else {
None
};
Ok(ExprKind::If { cond, then_branch, else_branch })
}
"Match" => {
let kwargs = parse_kwargs(list)?;
let expr = Box::new(self.build_expr(require_field(&kwargs, "expr", list.pos)?)?);
let arms_sexp = require_field(&kwargs, "arms", list.pos)?;
let arms_list = expect_list(arms_sexp)?;
let mut arms = Vec::new();
for arm_sexp in &arms_list.elements {
arms.push(self.build_arm(arm_sexp)?);
}
Ok(ExprKind::Match { expr, arms })
}
"While" => {
let kwargs = parse_kwargs(list)?;
let label = if let Some(label_sexp) = optional_field(&kwargs, "label") {
Some(self.build_label(label_sexp)?)
} else {
None
};
let cond = Box::new(self.build_expr(require_field(&kwargs, "cond", list.pos)?)?);
let body = self.build_block(require_field(&kwargs, "body", list.pos)?)?;
Ok(ExprKind::While { label, cond, body })
}
"ForLoop" => {
let kwargs = parse_kwargs(list)?;
let label = if let Some(label_sexp) = optional_field(&kwargs, "label") {
Some(self.build_label(label_sexp)?)
} else {
None
};
let pat = self.build_pat(require_field(&kwargs, "pat", list.pos)?)?;
let iter = Box::new(self.build_expr(require_field(&kwargs, "iter", list.pos)?)?);
let body = self.build_block(require_field(&kwargs, "body", list.pos)?)?;
Ok(ExprKind::ForLoop { label, pat, iter, body })
}
"Loop" => {
let kwargs = parse_kwargs(list)?;
let label = if let Some(label_sexp) = optional_field(&kwargs, "label") {
Some(self.build_label(label_sexp)?)
} else {
None
};
let body = self.build_block(require_field(&kwargs, "body", list.pos)?)?;
Ok(ExprKind::Loop { label, body })
}
_ => Err(ParseError::Expected {
expected: "If, Match, While, ForLoop, or Loop".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_operator_expr(
&mut self,
node_type: &str,
list: &crate::sexp::List,
) -> Result<ExprKind> {
match node_type {
"Binary" => {
let kwargs = parse_kwargs(list)?;
let left = Box::new(self.build_expr(require_field(&kwargs, "left", list.pos)?)?);
let op = self.build_binop(require_field(&kwargs, "op", list.pos)?)?;
let right = Box::new(self.build_expr(require_field(&kwargs, "right", list.pos)?)?);
Ok(ExprKind::Binary { left, op, right })
}
"Unary" => {
let kwargs = parse_kwargs(list)?;
let op = self.build_unop(require_field(&kwargs, "op", list.pos)?)?;
let expr = Box::new(self.build_expr(require_field(&kwargs, "expr", list.pos)?)?);
Ok(ExprKind::Unary { op, expr })
}
_ => Err(ParseError::Expected {
expected: "Binary or Unary".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_call_expr(&mut self, node_type: &str, list: &crate::sexp::List) -> Result<ExprKind> {
match node_type {
"Call" => {
let kwargs = parse_kwargs(list)?;
let func = Box::new(self.build_expr(require_field(&kwargs, "func", list.pos)?)?);
let args_sexp = require_field(&kwargs, "args", list.pos)?;
let args = self.build_expr_list(args_sexp)?;
Ok(ExprKind::Call { func, args })
}
"MethodCall" => {
let kwargs = parse_kwargs(list)?;
let receiver =
Box::new(self.build_expr(require_field(&kwargs, "receiver", list.pos)?)?);
let method = self.build_ident(require_field(&kwargs, "method", list.pos)?)?;
let args_sexp = require_field(&kwargs, "args", list.pos)?;
let args = self.build_expr_list(args_sexp)?;
Ok(ExprKind::MethodCall { receiver, method, args })
}
_ => Err(ParseError::Expected {
expected: "Call or MethodCall".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_collection_expr(
&mut self,
node_type: &str,
list: &crate::sexp::List,
) -> Result<ExprKind> {
match node_type {
"Array" => {
let elems = self.build_expr_list(&list.elements[1])?;
Ok(ExprKind::Array(elems))
}
"Tuple" => {
let elems = self.build_expr_list(&list.elements[1])?;
Ok(ExprKind::Tuple(elems))
}
"Struct" => {
let kwargs = parse_kwargs(list)?;
let path = self.build_path(require_field(&kwargs, "path", list.pos)?)?;
let fields = if let Some(fields_sexp) = kwargs.get("fields") {
self.build_expr_field_list(fields_sexp)?
} else {
Vec::new()
};
Ok(ExprKind::Struct { path, fields })
}
_ => Err(ParseError::Expected {
expected: "Array, Tuple, or Struct".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_access_expr(&mut self, node_type: &str, list: &crate::sexp::List) -> Result<ExprKind> {
match node_type {
"Field" => {
let kwargs = parse_kwargs(list)?;
let expr = Box::new(self.build_expr(require_field(&kwargs, "expr", list.pos)?)?);
let field = self.build_ident(require_field(&kwargs, "field", list.pos)?)?;
Ok(ExprKind::Field { expr, field })
}
"Index" => {
let kwargs = parse_kwargs(list)?;
let expr = Box::new(self.build_expr(require_field(&kwargs, "expr", list.pos)?)?);
let index = Box::new(self.build_expr(require_field(&kwargs, "index", list.pos)?)?);
Ok(ExprKind::Index { expr, index })
}
_ => Err(ParseError::Expected {
expected: "Field or Index".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_other_expr(&mut self, node_type: &str, list: &crate::sexp::List) -> Result<ExprKind> {
match node_type {
"MacCall" => {
let mac_call_sexp = &list.elements[1];
let mac_call_list = expect_list(mac_call_sexp)?;
let mac_call = self.build_mac_call_inner(mac_call_list)?;
Ok(ExprKind::MacCall(mac_call))
}
"Assign" => {
let kwargs = parse_kwargs(list)?;
let left = Box::new(self.build_expr(require_field(&kwargs, "left", list.pos)?)?);
let right = Box::new(self.build_expr(require_field(&kwargs, "right", list.pos)?)?);
Ok(ExprKind::Assign { left, right })
}
"Closure" => {
let kwargs = parse_kwargs(list)?;
let params = if let Some(params_sexp) = kwargs.get("params") {
self.build_param_list(params_sexp)?
} else {
Vec::new()
};
let body = Box::new(self.build_expr(require_field(&kwargs, "body", list.pos)?)?);
Ok(ExprKind::Closure { params, body })
}
"Range" => {
let kwargs = parse_kwargs(list)?;
let start = if let Some(start_sexp) = optional_field(&kwargs, "start") {
Some(Box::new(self.build_expr(start_sexp)?))
} else {
None
};
let end = if let Some(end_sexp) = optional_field(&kwargs, "end") {
Some(Box::new(self.build_expr(end_sexp)?))
} else {
None
};
let inclusive = matches!(
kwargs.get("inclusive"),
Some(SExp::Symbol(sym)) if sym.value == "true"
);
Ok(ExprKind::Range { start, end, inclusive })
}
"Paren" => {
let expr = Box::new(self.build_expr(&list.elements[1])?);
Ok(ExprKind::Paren(expr))
}
"Try" => {
let expr = Box::new(self.build_expr(&list.elements[1])?);
Ok(ExprKind::Try(expr))
}
"Cast" => {
let kwargs = parse_kwargs(list)?;
let expr = Box::new(self.build_expr(require_field(&kwargs, "expr", list.pos)?)?);
let ty = Box::new(self.build_ty(require_field(&kwargs, "ty", list.pos)?)?);
Ok(ExprKind::Cast { expr, ty })
}
"Break" => {
let kwargs = parse_kwargs(list)?;
let label = if let Some(label_sexp) = optional_field(&kwargs, "label") {
Some(self.build_label(label_sexp)?)
} else {
None
};
let value = if let Some(value_sexp) = optional_field(&kwargs, "value") {
Some(Box::new(self.build_expr(value_sexp)?))
} else {
None
};
Ok(ExprKind::Break { label, value })
}
"Continue" => {
let kwargs = parse_kwargs(list)?;
let label = if let Some(label_sexp) = optional_field(&kwargs, "label") {
Some(self.build_label(label_sexp)?)
} else {
None
};
Ok(ExprKind::Continue { label })
}
"Return" => {
let kwargs = parse_kwargs(list)?;
let value = if let Some(value_sexp) = optional_field(&kwargs, "value") {
Some(Box::new(self.build_expr(value_sexp)?))
} else {
None
};
Ok(ExprKind::Return { value })
}
_ => Err(ParseError::Expected {
expected:
"MacCall, Assign, Closure, Range, Paren, Try, Cast, Break, Continue, or Return"
.to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_basic_expr(&mut self, node_type: &str, list: &crate::sexp::List) -> Result<ExprKind> {
match node_type {
"Path" => {
let qself = if list.elements.len() > 1 {
let qself_sexp = &list.elements[1];
if matches!(qself_sexp, SExp::Symbol(sym) if sym.value == "nil") {
None
} else {
None
}
} else {
None
};
let path = self.build_path(&list.elements[2])?;
Ok(ExprKind::Path(qself, path))
}
"Lit" => {
let lit_sexp = &list.elements[1];
let lit = self.build_lit(lit_sexp)?;
Ok(ExprKind::Lit(lit))
}
_ => Err(ParseError::Expected {
expected: "Path or Lit".to_string(),
found: node_type.to_string(),
pos: list.pos,
}),
}
}
fn build_lit(&mut self, sexp: &SExp) -> Result<Lit> {
let list = expect_node_type(expect_list(sexp)?, "Lit")?;
let kwargs = parse_kwargs(list)?;
let kind = self.build_lit_kind(require_field(&kwargs, "kind", list.pos)?)?;
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
Ok(Lit { kind, span })
}
fn build_lit_kind(&mut self, sexp: &SExp) -> Result<LitKind> {
let list = expect_list(sexp)?;
let variant = expect_symbol(&list.elements[0])?;
match variant.value.as_str() {
"Int" => {
let value = expect_number(&list.elements[1])?;
Ok(LitKind::Int(value))
}
"Str" => {
let value = expect_string(&list.elements[1])?;
Ok(LitKind::Str(value.to_string()))
}
_ => Err(ParseError::Expected {
expected: "Int or Str".to_string(),
found: variant.value.clone(),
pos: variant.pos,
}),
}
}
pub(super) fn build_mac_call_inner(&mut self, list: &crate::sexp::List) -> Result<MacCall> {
let kwargs = parse_kwargs(list)?;
let path = self.build_path(require_field(&kwargs, "path", list.pos)?)?;
let args = if let Some(args_sexp) = kwargs.get("args") {
self.build_mac_args(args_sexp)?
} else {
MacArgs::Empty
};
Ok(MacCall::new(path, args))
}
pub fn build_path(&mut self, sexp: &SExp) -> Result<Path> {
let list = expect_node_type(expect_list(sexp)?, "Path")?;
let kwargs = parse_kwargs(list)?;
let segments = if let Some(segments_sexp) = kwargs.get("segments") {
let segments_list = expect_list(segments_sexp)?;
let mut segs = Vec::new();
for seg_sexp in &segments_list.elements {
segs.push(self.build_path_segment(seg_sexp)?);
}
segs
} else {
Vec::new()
};
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
Ok(Path { span, segments, tokens: None })
}
fn build_path_segment(&mut self, sexp: &SExp) -> Result<PathSegment> {
let list = expect_node_type(expect_list(sexp)?, "PathSegment")?;
let kwargs = parse_kwargs(list)?;
let ident = self.build_ident(require_field(&kwargs, "ident", list.pos)?)?;
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
Ok(PathSegment { ident, id, args: None })
}
fn build_mac_args(&mut self, sexp: &SExp) -> Result<MacArgs> {
if let Ok(sym) = expect_symbol(sexp) {
if sym.value == "Empty" {
return Ok(MacArgs::Empty);
}
}
let list = expect_list(sexp)?;
let node_type = expect_symbol(&list.elements[0])?;
match node_type.value.as_str() {
"Empty" => Ok(MacArgs::Empty),
"Delimited" => {
let kwargs = parse_kwargs(list)?;
let dspan = if let Some(dspan_sexp) = kwargs.get("dspan") {
self.build_del_span(dspan_sexp)?
} else {
DelSpan::new(Span::DUMMY, Span::DUMMY)
};
let delim = if let Some(delim_sexp) = kwargs.get("delim") {
self.build_delimiter(delim_sexp)?
} else {
Delimiter::Paren
};
let tokens = if let Some(tokens_sexp) = kwargs.get("tokens") {
self.build_token_stream(tokens_sexp)?
} else {
TokenStream::Empty
};
Ok(MacArgs::Delimited { dspan, delim, tokens })
}
_ => Err(ParseError::Expected {
expected: "Empty or Delimited".to_string(),
found: node_type.value.clone(),
pos: node_type.pos,
}),
}
}
fn build_del_span(&mut self, sexp: &SExp) -> Result<DelSpan> {
let list = expect_list(sexp)?;
let kwargs = parse_kwargs(list)?;
let open = if let Some(open_sexp) = kwargs.get("open") {
self.build_span(open_sexp)?
} else {
Span::DUMMY
};
let close = if let Some(close_sexp) = kwargs.get("close") {
self.build_span(close_sexp)?
} else {
Span::DUMMY
};
Ok(DelSpan::new(open, close))
}
fn build_delimiter(&mut self, sexp: &SExp) -> Result<Delimiter> {
let sym = expect_symbol(sexp)?;
match sym.value.as_str() {
"Paren" => Ok(Delimiter::Paren),
"Brace" => Ok(Delimiter::Brace),
"Bracket" => Ok(Delimiter::Bracket),
"Invisible" => Ok(Delimiter::Invisible),
_ => Err(ParseError::Expected {
expected: "Paren, Brace, Bracket, or Invisible".to_string(),
found: sym.value.clone(),
pos: sym.pos,
}),
}
}
fn build_token_stream(&mut self, sexp: &SExp) -> Result<TokenStream> {
if let Ok(sym) = expect_symbol(sexp) {
if sym.value == "Empty" {
return Ok(TokenStream::Empty);
}
}
let list = expect_list(sexp)?;
let node_type = expect_symbol(&list.elements[0])?;
match node_type.value.as_str() {
"Empty" => Ok(TokenStream::Empty),
"TokenStream" => {
let kwargs = parse_kwargs(list)?;
if let Some(source_sexp) = kwargs.get("source") {
let source = expect_string(source_sexp)?;
Ok(TokenStream::Source(source))
} else {
Ok(TokenStream::Empty)
}
}
_ => Err(ParseError::Expected {
expected: "TokenStream".to_string(),
found: node_type.value.clone(),
pos: node_type.pos,
}),
}
}
pub fn build_pat(&mut self, sexp: &SExp) -> Result<Pat> {
let list = expect_node_type(expect_list(sexp)?, "Pat")?;
let kwargs = parse_kwargs(list)?;
let kind = if let Some(kind_sexp) = kwargs.get("kind") {
self.build_pat_kind(kind_sexp)?
} else {
return Err(ParseError::Expected {
expected: ":kind field".to_string(),
found: "missing".to_string(),
pos: list.pos,
});
};
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
Ok(Pat { id, kind, span, tokens: None })
}
fn build_pat_kind(&mut self, sexp: &SExp) -> Result<PatKind> {
if let SExp::Symbol(sym) = sexp {
return match sym.value.as_str() {
"Wild" => Ok(PatKind::Wild),
_ => Err(ParseError::Expected {
expected: "Wild or pattern list".to_string(),
found: sym.value.clone(),
pos: sym.pos,
}),
};
}
let list = expect_list(sexp)?;
let node_type = expect_symbol(&list.elements[0])?;
match node_type.value.as_str() {
"Ident" => {
let kwargs = parse_kwargs(list)?;
let ident = self.build_ident(require_field(&kwargs, "ident", list.pos)?)?;
let binding_mode = if let Some(bm_sexp) = kwargs.get("binding-mode") {
self.build_binding_mode(bm_sexp)?
} else {
BindingMode::ByValue(Mutability::Not)
};
let sub = if let Some(sub_sexp) = optional_field(&kwargs, "sub") {
Some(Box::new(self.build_pat(sub_sexp)?))
} else {
None
};
Ok(PatKind::Ident { binding_mode, ident, sub })
}
"Struct" => {
let kwargs = parse_kwargs(list)?;
let path = self.build_path(require_field(&kwargs, "path", list.pos)?)?;
let fields = if let Some(fields_sexp) = kwargs.get("fields") {
self.build_pat_field_list(fields_sexp)?
} else {
Vec::new()
};
Ok(PatKind::Struct { path, fields })
}
"TupleStruct" => {
let kwargs = parse_kwargs(list)?;
let path = self.build_path(require_field(&kwargs, "path", list.pos)?)?;
let elems = if let Some(elems_sexp) = kwargs.get("elems") {
self.build_pat_list(elems_sexp)?
} else {
Vec::new()
};
Ok(PatKind::TupleStruct { path, elems })
}
"Tuple" => {
let pats = self.build_pat_list(&list.elements[1])?;
Ok(PatKind::Tuple(pats))
}
"Slice" => {
let pats = self.build_pat_list(&list.elements[1])?;
Ok(PatKind::Slice(pats))
}
"Or" => {
let pats = self.build_pat_list(&list.elements[1])?;
Ok(PatKind::Or(pats))
}
"Ref" => {
let kwargs = parse_kwargs(list)?;
let pat = Box::new(self.build_pat(require_field(&kwargs, "pat", list.pos)?)?);
let mutability = if let Some(mut_sexp) = kwargs.get("mutability") {
let sym = expect_symbol(mut_sexp)?;
match sym.value.as_str() {
"Mut" => Mutability::Mut,
"Not" => Mutability::Not,
_ => Mutability::Not,
}
} else {
Mutability::Not
};
Ok(PatKind::Ref { pat, mutability })
}
"Lit" => {
let expr = Box::new(self.build_expr(&list.elements[1])?);
Ok(PatKind::Lit(expr))
}
"Box" => {
let pat = Box::new(self.build_pat(&list.elements[1])?);
Ok(PatKind::Box(pat))
}
"Path" => {
let kwargs = parse_kwargs(list)?;
let qself = if let Some(qself_sexp) = optional_field(&kwargs, "qself") {
Some(self.build_qself(qself_sexp)?)
} else {
None
};
let path = self.build_path(require_field(&kwargs, "path", list.pos)?)?;
Ok(PatKind::Path { qself, path })
}
"Range" => {
let kwargs = parse_kwargs(list)?;
let start = if let Some(start_sexp) = optional_field(&kwargs, "start") {
Some(Box::new(self.build_expr(start_sexp)?))
} else {
None
};
let end = if let Some(end_sexp) = optional_field(&kwargs, "end") {
Some(Box::new(self.build_expr(end_sexp)?))
} else {
None
};
let limits = if let Some(limits_sexp) = kwargs.get("limits") {
self.build_range_end(limits_sexp)?
} else {
RangeEnd::Excluded
};
Ok(PatKind::Range { start, end, limits })
}
"Rest" => Ok(PatKind::Rest),
"Paren" => {
let pat = Box::new(self.build_pat(&list.elements[1])?);
Ok(PatKind::Paren(pat))
}
"Type" => {
let kwargs = parse_kwargs(list)?;
let pat = Box::new(self.build_pat(require_field(&kwargs, "pat", list.pos)?)?);
let ty = Box::new(self.build_ty(require_field(&kwargs, "ty", list.pos)?)?);
Ok(PatKind::Type { pat, ty })
}
"Const" => {
let kwargs = parse_kwargs(list)?;
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
let value = Box::new(self.build_expr(require_field(&kwargs, "value", list.pos)?)?);
Ok(PatKind::Const(ConstBlock { id, value }))
}
"MacCall" => {
let kwargs = parse_kwargs(list)?;
let mac_sexp = require_field(&kwargs, "mac", list.pos)?;
let mac_list = expect_list(mac_sexp)?;
let mac = self.build_mac_call_inner(mac_list)?;
Ok(PatKind::MacCall(mac))
}
"Err" => Ok(PatKind::Err),
_ => Err(ParseError::Expected {
expected: "Supported PatKind variant".to_string(),
found: node_type.value.clone(),
pos: node_type.pos,
}),
}
}
fn build_arm(&mut self, sexp: &SExp) -> Result<Arm> {
let list = expect_node_type(expect_list(sexp)?, "Arm")?;
let kwargs = parse_kwargs(list)?;
let pat = self.build_pat(require_field(&kwargs, "pat", list.pos)?)?;
let body = Box::new(self.build_expr(require_field(&kwargs, "body", list.pos)?)?);
let guard = if let Some(guard_sexp) = optional_field(&kwargs, "guard") {
Some(Box::new(self.build_expr(guard_sexp)?))
} else {
None
};
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
let id = if let Some(id_sexp) = kwargs.get("id") {
NodeId(expect_number(id_sexp)? as u32)
} else {
self.next_id()
};
Ok(Arm { attrs: Vec::new(), pat, guard, body, span, id })
}
fn build_label(&mut self, sexp: &SExp) -> Result<Label> {
let list = expect_node_type(expect_list(sexp)?, "Label")?;
let kwargs = parse_kwargs(list)?;
let ident = self.build_ident(require_field(&kwargs, "ident", list.pos)?)?;
Ok(Label { ident })
}
fn build_binop(&mut self, sexp: &SExp) -> Result<BinOp> {
parse_binop(sexp)
}
fn build_unop(&mut self, sexp: &SExp) -> Result<UnOp> {
parse_unop(sexp)
}
fn build_expr_list(&mut self, sexp: &SExp) -> Result<Vec<Expr>> {
let list = expect_list(sexp)?;
list.elements.iter().map(|elem| self.build_expr(elem)).collect()
}
fn build_pat_list(&mut self, sexp: &SExp) -> Result<Vec<Pat>> {
let list = expect_list(sexp)?;
list.elements.iter().map(|elem| self.build_pat(elem)).collect()
}
fn build_pat_field_list(&mut self, sexp: &SExp) -> Result<Vec<PatField>> {
let list = expect_list(sexp)?;
list.elements.iter().map(|elem| self.build_pat_field(elem)).collect()
}
fn build_pat_field(&mut self, sexp: &SExp) -> Result<PatField> {
let list = expect_node_type(expect_list(sexp)?, "PatField")?;
let kwargs = parse_kwargs(list)?;
let attrs = Vec::new();
let ident = self.build_ident(require_field(&kwargs, "ident", list.pos)?)?;
let pat = self.build_pat(require_field(&kwargs, "pat", list.pos)?)?;
let is_shorthand = matches!(
kwargs.get("is-shorthand"),
Some(SExp::Symbol(sym)) if sym.value == "true"
);
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
Ok(PatField { attrs, ident, pat, is_shorthand, span })
}
fn build_binding_mode(&mut self, sexp: &SExp) -> Result<BindingMode> {
let list = expect_list(sexp)?;
let node_type = expect_symbol(&list.elements[0])?;
match node_type.value.as_str() {
"ByRef" => {
let mutability = if list.elements.len() > 1 {
let sym = expect_symbol(&list.elements[1])?;
match sym.value.as_str() {
"Mut" => Mutability::Mut,
"Not" => Mutability::Not,
_ => Mutability::Not,
}
} else {
Mutability::Not
};
Ok(BindingMode::ByRef(mutability))
}
"ByValue" => {
let mutability = if list.elements.len() > 1 {
let sym = expect_symbol(&list.elements[1])?;
match sym.value.as_str() {
"Mut" => Mutability::Mut,
"Not" => Mutability::Not,
_ => Mutability::Not,
}
} else {
Mutability::Not
};
Ok(BindingMode::ByValue(mutability))
}
_ => Err(ParseError::Expected {
expected: "ByRef or ByValue".to_string(),
found: node_type.value.clone(),
pos: node_type.pos,
}),
}
}
fn build_expr_field_list(&mut self, sexp: &SExp) -> Result<Vec<ExprField>> {
let list = expect_list(sexp)?;
list.elements.iter().map(|elem| self.build_expr_field(elem)).collect()
}
fn build_expr_field(&mut self, sexp: &SExp) -> Result<ExprField> {
let list = expect_node_type(expect_list(sexp)?, "ExprField")?;
let kwargs = parse_kwargs(list)?;
let attrs = Vec::new();
let ident = self.build_ident(require_field(&kwargs, "ident", list.pos)?)?;
let expr = self.build_expr(require_field(&kwargs, "expr", list.pos)?)?;
let is_shorthand = matches!(
kwargs.get("is-shorthand"),
Some(SExp::Symbol(sym)) if sym.value == "true"
);
let span = if let Some(span_sexp) = kwargs.get("span") {
self.build_span(span_sexp)?
} else {
Span::DUMMY
};
Ok(ExprField { attrs, ident, expr, is_shorthand, span })
}
fn build_param_list(&mut self, sexp: &SExp) -> Result<Vec<Param>> {
let list = expect_list(sexp)?;
list.elements.iter().map(|elem| self.build_param(elem)).collect()
}
fn build_qself(&mut self, _sexp: &SExp) -> Result<QSelf> {
Ok(QSelf {})
}
fn build_range_end(&mut self, sexp: &SExp) -> Result<RangeEnd> {
let sym = expect_symbol(sexp)?;
match sym.value.as_str() {
"Included" => Ok(RangeEnd::Included),
"Excluded" => Ok(RangeEnd::Excluded),
_ => Err(ParseError::Expected {
expected: "Included or Excluded".to_string(),
found: sym.value.clone(),
pos: sym.pos,
}),
}
}
}