add match blocks and constant literals

This commit is contained in:
NotAFile 2022-04-04 21:40:08 +02:00
parent 68be74d032
commit da5258a11a
10 changed files with 240 additions and 116 deletions

View File

@ -3,6 +3,7 @@ use std::collections::BTreeMap;
use std::fmt::Write; use std::fmt::Write;
use super::parser; use super::parser;
use super::parser::block_expression::BlockExpr;
use crate::rtlil; use crate::rtlil;
pub use callable::{Callable, CallableContext, CallableId}; pub use callable::{Callable, CallableContext, CallableId};
pub use types::{Type, TypeStruct, TypingContext}; pub use types::{Type, TypeStruct, TypingContext};
@ -119,11 +120,8 @@ impl Context {
match &expr.kind { match &expr.kind {
typed_ir::ExprKind::Literal(lit) => Ok(lit.clone()), typed_ir::ExprKind::Literal(lit) => Ok(lit.clone()),
typed_ir::ExprKind::Path(_) => todo!("evaluate path"), typed_ir::ExprKind::Path(_) => todo!("evaluate path"),
typed_ir::ExprKind::Call { typed_ir::ExprKind::Call(_call) => todo!("evaluate call"),
called, typed_ir::ExprKind::Match(_) => todo!(),
args,
genargs,
} => todo!("evaluate call"),
} }
} }
@ -144,10 +142,10 @@ impl Context {
} }
Expression::Literal(lit) => { Expression::Literal(lit) => {
// TODO: make this a proper enum instead of having to match on everything // TODO: make this a proper enum instead of having to match on everything
let data = match lit.kind() { let data = match lit.kind {
parser::tokens::TokenKind::Number => { parser::expression::LiteralKind::Num(num) => self.types.make_elabnum_u32(num),
let num = lit.span().fragment().parse().unwrap(); parser::expression::LiteralKind::Const(width, val) => {
self.types.make_elabnum_u32(num) self.types.make_const_u32(width, val as u32)
} }
_ => unreachable!("non-literal token in literal?"), _ => unreachable!("non-literal token in literal?"),
}; };
@ -161,11 +159,11 @@ impl Context {
let a = self.type_expression(&op.a)?; let a = self.type_expression(&op.a)?;
typed_ir::Expr { typed_ir::Expr {
id, id,
kind: typed_ir::ExprKind::Call { kind: typed_ir::ExprKind::Call(typed_ir::Call {
called: self.callables.builtins.bitnot, called: self.callables.builtins.bitnot,
args: vec![a], args: vec![a],
genargs: vec![], genargs: vec![],
}, }),
typ: self.types.primitives.infer, typ: self.types.primitives.infer,
} }
} }
@ -173,11 +171,11 @@ impl Context {
let (a, b) = (self.type_expression(&op.a)?, self.type_expression(&op.b)?); let (a, b) = (self.type_expression(&op.a)?, self.type_expression(&op.b)?);
typed_ir::Expr { typed_ir::Expr {
id, id,
kind: typed_ir::ExprKind::Call { kind: typed_ir::ExprKind::Call(typed_ir::Call {
called: self.callables.builtins.xor, called: self.callables.builtins.xor,
args: vec![a, b], args: vec![a, b],
genargs: vec![], genargs: vec![],
}, }),
typ: self.types.primitives.infer, typ: self.types.primitives.infer,
} }
} }
@ -202,14 +200,34 @@ impl Context {
.collect(); .collect();
typed_ir::Expr { typed_ir::Expr {
id, id,
kind: typed_ir::ExprKind::Call { kind: typed_ir::ExprKind::Call(typed_ir::Call {
called, called,
args: args_resolved, args: args_resolved,
genargs: genargs_resolved, genargs: genargs_resolved,
}, }),
typ: self.types.primitives.infer, typ: self.types.primitives.infer,
} }
} }
Expression::BlockExpr(block) => match &**block {
BlockExpr::IfElse(_) => todo!(),
BlockExpr::Match(match_) => {
let expr = self.type_expression(&match_.expr)?;
let arms = match_
.arms
.iter()
.map(|(cond, val)| {
Ok((self.type_expression(cond)?, self.type_expression(val)?))
})
.collect::<Result<_, _>>()?;
let typed = typed_ir::Match { expr, arms };
typed_ir::Expr {
id,
kind: typed_ir::ExprKind::Match(Box::new(typed)),
typ: self.types.primitives.infer,
}
}
BlockExpr::Block(_) => todo!(),
},
}; };
Ok(t_expr) Ok(t_expr)
} }
@ -317,13 +335,13 @@ impl Context {
typed_ir::ExprKind::Literal(lit) => expr.clone().with_type(lit.typ), typed_ir::ExprKind::Literal(lit) => expr.clone().with_type(lit.typ),
// we can not see beyond this expression right now // we can not see beyond this expression right now
typed_ir::ExprKind::Path(_) => expr.clone(), typed_ir::ExprKind::Path(_) => expr.clone(),
typed_ir::ExprKind::Call { typed_ir::ExprKind::Call(call) => {
called, let args_typed: Vec<_> = call
args, .args
genargs, .iter()
} => { .map(|ex| self.infer_expr_types(ex))
let args_typed: Vec<_> = args.iter().map(|ex| self.infer_expr_types(ex)).collect(); .collect();
let callee_def = self.callables.get(*called); let callee_def = self.callables.get(call.called);
let param_types: Vec<_> = callee_def.args.iter().map(|param| param.1).collect(); let param_types: Vec<_> = callee_def.args.iter().map(|param| param.1).collect();
let inferred_args: Vec<_> = param_types let inferred_args: Vec<_> = param_types
@ -358,11 +376,27 @@ impl Context {
let mut new_expr = expr.clone(); let mut new_expr = expr.clone();
new_expr.typ = new_type; new_expr.typ = new_type;
new_expr.kind = typed_ir::ExprKind::Call { new_expr.kind = typed_ir::ExprKind::Call(typed_ir::Call {
called: called.clone(), called: call.called.clone(),
args: args_typed, args: args_typed,
genargs, genargs,
});
new_expr
}
typed_ir::ExprKind::Match(match_) => {
let new_arms: Vec<_> = match_
.arms
.iter()
.map(|(pat, val)| (self.infer_expr_types(pat), self.infer_expr_types(val)))
.collect();
// TODO: hacky hacky hacky
let res_type = new_arms.first().unwrap().1.typ;
let new_match = typed_ir::Match {
expr: self.infer_expr_types(&match_.expr),
arms: new_arms,
}; };
let mut new_expr = expr.clone().with_type(res_type);
new_expr.kind = typed_ir::ExprKind::Match(Box::new(new_match));
new_expr new_expr
} }
} }
@ -429,20 +463,18 @@ impl Context {
lit_str lit_str
} }
typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0), typed_ir::ExprKind::Path(path) => format!("sig_{}", path.0),
typed_ir::ExprKind::Call { typed_ir::ExprKind::Call(call) => {
called, let args = call
args, .args
genargs,
} => {
let args = args
.iter() .iter()
.map(|arg| { .map(|arg| {
self.pretty_typed_expr(w, arg)?; self.pretty_typed_expr(w, arg)?;
Ok(format!("_{}", arg.id.0)) Ok(format!("_{}", arg.id.0))
}) })
.collect::<Result<Vec<_>, std::fmt::Error>>()?; .collect::<Result<Vec<_>, std::fmt::Error>>()?;
let callable = self.callables.get(*called); let callable = self.callables.get(call.called);
let genargs = genargs let genargs = call
.genargs
.iter() .iter()
.map(|param| { .map(|param| {
let mut type_str = String::new(); let mut type_str = String::new();
@ -457,6 +489,23 @@ impl Context {
args.join(", ") args.join(", ")
) )
} }
typed_ir::ExprKind::Match(match_) => {
self.pretty_typed_expr(w, &match_.expr)?;
let arms = match_
.arms
.iter()
.map(|(pat, val)| {
self.pretty_typed_expr(w, pat)?;
self.pretty_typed_expr(w, val)?;
Ok(format!(" _{} => _{}", pat.id.0, val.id.0))
})
.collect::<Result<Vec<_>, _>>()?;
format!(
"match (_{}) {{\n{}\n}}",
&match_.expr.id.0,
arms.join(",\n")
)
}
}; };
let mut type_pretty = String::new(); let mut type_pretty = String::new();
self.types.pretty_type(&mut type_pretty, expr.typ)?; self.types.pretty_type(&mut type_pretty, expr.typ)?;

View File

@ -17,22 +17,19 @@ fn lower_expression(
module.add_wire(expr_wire); module.add_wire(expr_wire);
match &expr.kind { match &expr.kind {
ExprKind::Path(def) => Ok(rtlil::SigSpec::Wire(format!("\\$sig_{}", def.0))), ExprKind::Path(def) => Ok(rtlil::SigSpec::Wire(format!("\\$sig_{}", def.0))),
ExprKind::Call { ExprKind::Call(call) => {
called, let args_resolved = call
args, .args
genargs,
} => {
let args_resolved = args
.iter() .iter()
.map(|expr| lower_expression(ctx, module, expr)) .map(|expr| lower_expression(ctx, module, expr))
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let callable = ctx.callables.get(*called); let callable = ctx.callables.get(call.called);
let cell_id = module.make_genid(callable.name()); let cell_id = module.make_genid(callable.name());
if *called == ctx.callables.builtins.xor { if call.called == ctx.callables.builtins.xor {
let a_width = ctx.types.get_width(args[0].typ).unwrap(); let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
let b_width = ctx.types.get_width(args[1].typ).unwrap(); let b_width = ctx.types.get_width(call.args[1].typ).unwrap();
let y_width = ctx.types.get_width(expr.typ).unwrap(); let y_width = ctx.types.get_width(expr.typ).unwrap();
let mut cell = rtlil::Cell::new(&cell_id, "$xor"); let mut cell = rtlil::Cell::new(&cell_id, "$xor");
cell.add_param("\\A_SIGNED", "0"); cell.add_param("\\A_SIGNED", "0");
@ -44,8 +41,8 @@ fn lower_expression(
cell.add_connection("\\B", &args_resolved[1]); cell.add_connection("\\B", &args_resolved[1]);
cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone())); cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone()));
module.add_cell(cell); module.add_cell(cell);
} else if *called == ctx.callables.builtins.reduce_or { } else if call.called == ctx.callables.builtins.reduce_or {
let a_width = ctx.types.get_width(args[0].typ).unwrap(); let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
let y_width = ctx.types.get_width(expr.typ).unwrap(); let y_width = ctx.types.get_width(expr.typ).unwrap();
let mut cell = rtlil::Cell::new(&cell_id, "$reduce_or"); let mut cell = rtlil::Cell::new(&cell_id, "$reduce_or");
cell.add_param("\\A_SIGNED", "0"); cell.add_param("\\A_SIGNED", "0");
@ -54,8 +51,8 @@ fn lower_expression(
cell.add_connection("\\A", &args_resolved[0]); cell.add_connection("\\A", &args_resolved[0]);
cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone())); cell.add_connection("\\Y", &rtlil::SigSpec::Wire(expr_wire_name.clone()));
module.add_cell(cell); module.add_cell(cell);
} else if *called == ctx.callables.builtins.bitnot { } else if call.called == ctx.callables.builtins.bitnot {
let a_width = ctx.types.get_width(args[0].typ).unwrap(); let a_width = ctx.types.get_width(call.args[0].typ).unwrap();
let y_width = ctx.types.get_width(expr.typ).unwrap(); let y_width = ctx.types.get_width(expr.typ).unwrap();
let mut cell = rtlil::Cell::new(&cell_id, "$not"); let mut cell = rtlil::Cell::new(&cell_id, "$not");
cell.add_param("\\A_SIGNED", "0"); cell.add_param("\\A_SIGNED", "0");
@ -72,6 +69,7 @@ fn lower_expression(
todo!(), todo!(),
ctx.types.get_width(expr.typ).expect("signal has no size"), ctx.types.get_width(expr.typ).expect("signal has no size"),
)), )),
ExprKind::Match(_) => todo!(),
} }
} }

View File

@ -28,15 +28,25 @@ pub struct Expr {
pub typ: Type, pub typ: Type,
} }
#[derive(Debug, Clone)]
pub struct Call {
pub called: CallableId,
pub args: Vec<Expr>,
pub genargs: Vec<Type>,
}
#[derive(Debug, Clone)]
pub struct Match {
pub expr: Expr,
pub arms: Vec<(Expr, Expr)>,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ExprKind { pub enum ExprKind {
Literal(ElabData), Literal(ElabData),
Path(DefId), Path(DefId),
Call { Call(Call),
called: CallableId, Match(Box<Match>),
args: Vec<Expr>,
genargs: Vec<Type>,
},
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -1,3 +1,4 @@
use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
/// Alias for &TypeStruct to reduce repetition /// Alias for &TypeStruct to reduce repetition
/// and make futura migration to interning /// and make futura migration to interning
@ -13,12 +14,12 @@ impl Debug for InternedType {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct TypeStruct { pub struct TypeStruct {
kind: TypeKind, kind: TypeKind,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
enum TypeKind { enum TypeKind {
/// Elaboration-time types /// Elaboration-time types
ElabType(ElabKind), ElabType(ElabKind),
@ -62,7 +63,7 @@ enum ElabValueData {
} }
/// Types that are only valid during Elaboration /// Types that are only valid during Elaboration
#[derive(Debug)] #[derive(Debug, Clone)]
enum ElabKind { enum ElabKind {
/// general, unsized number type /// general, unsized number type
Num, Num,
@ -95,7 +96,7 @@ pub struct PrimitiveTypes {
} }
pub struct TypingContext { pub struct TypingContext {
types: Vec<TypeStruct>, types: RefCell<Vec<TypeStruct>>,
pub primitives: PrimitiveTypes, pub primitives: PrimitiveTypes,
} }
@ -107,7 +108,7 @@ impl TypingContext {
infer: InternedType(2), infer: InternedType(2),
}; };
Self { Self {
types: vec![ types: RefCell::new(vec![
TypeStruct { TypeStruct {
kind: TypeKind::ElabType(ElabKind::Num), kind: TypeKind::ElabType(ElabKind::Num),
}, },
@ -120,19 +121,19 @@ impl TypingContext {
TypeStruct { TypeStruct {
kind: TypeKind::Infer, kind: TypeKind::Infer,
}, },
], ]),
primitives, primitives,
} }
} }
pub fn add(&mut self, typ: TypeStruct) -> Type { pub fn add(&self, typ: TypeStruct) -> Type {
let id = self.types.len(); let id = self.types.borrow().len();
self.types.push(typ); self.types.borrow_mut().push(typ);
InternedType(id) InternedType(id)
} }
pub fn get(&self, typ: Type) -> &TypeStruct { pub fn get(&self, typ: Type) -> TypeStruct {
&self.types[typ.0] self.types.borrow()[typ.0].clone()
} }
pub fn make_elabnum_u32(&self, num: u32) -> ElabData { pub fn make_elabnum_u32(&self, num: u32) -> ElabData {
@ -142,7 +143,14 @@ impl TypingContext {
} }
} }
pub fn make_logic_size(&mut self, width: u32) -> Type { pub fn make_const_u32(&self, width: u32, num: u32) -> ElabData {
ElabData {
typ: self.make_logic_size(width),
value: ElabValue::Concrete(ElabValueData::U32(num)),
}
}
pub fn make_logic_size(&self, width: u32) -> Type {
let widthnum = self.make_elabnum_u32(width); let widthnum = self.make_elabnum_u32(width);
self.parameterize(self.primitives.logic, &[GenericArg::Elab(widthnum)]) self.parameterize(self.primitives.logic, &[GenericArg::Elab(widthnum)])
.unwrap() .unwrap()
@ -171,7 +179,7 @@ impl TypingContext {
} }
} }
pub fn parameterize(&mut self, typ: Type, params: &[GenericArg]) -> Option<Type> { pub fn parameterize(&self, typ: Type, params: &[GenericArg]) -> Option<Type> {
// TODO: return proper error type here // TODO: return proper error type here
match &self.get(typ).kind { match &self.get(typ).kind {
// Elab types have no params yet // Elab types have no params yet

View File

@ -0,0 +1,57 @@
use nom::{
branch::alt,
combinator::map,
error::context,
multi::{many1, separated_list1},
sequence::{delimited, separated_pair, tuple},
};
use crate::parser::{
assign_statement, expression,
expression::{expression, Expression},
tokens::{token, TokenKind as tk, TokenSpan},
Assign, IResult, Span,
};
#[derive(Debug, Clone)]
pub enum BlockExpr<'a> {
IfElse(IfElseBlock),
Match(MatchBlock<'a>),
Block(Vec<BlockExpr<'a>>),
}
// TODO: postponed because annoying to implement
#[derive(Debug, Clone)]
pub struct IfElseBlock {}
#[derive(Debug, Clone)]
pub struct MatchBlock<'a> {
pub expr: Expression<'a>,
pub arms: Vec<(Expression<'a>, Expression<'a>)>,
}
fn match_arm(input: TokenSpan) -> IResult<TokenSpan, (Expression, Expression)> {
separated_pair(expression, token(tk::FatArrow), expression)(input)
}
fn match_block(input: TokenSpan) -> IResult<TokenSpan, MatchBlock> {
context(
"match block",
map(
tuple((
token(tk::Match),
delimited(token(tk::LParen), expression, token(tk::RParen)),
delimited(
token(tk::LBrace),
separated_list1(token(tk::Comma), match_arm),
token(tk::RBrace),
),
)),
|(_, expr, arms)| MatchBlock { expr, arms },
),
)(input)
}
pub fn block_expr(input: TokenSpan) -> IResult<TokenSpan, BlockExpr> {
alt((map(match_block, BlockExpr::Match),))(input)
}

View File

@ -1,3 +1,5 @@
use super::block_expression::{block_expr, BlockExpr};
use super::literals;
use super::tokens::{token, Token, TokenKind as tk, TokenSpan}; use super::tokens::{token, Token, TokenKind as tk, TokenSpan};
use super::{IResult, Span}; use super::{IResult, Span};
use nom::{ use nom::{
@ -7,6 +9,18 @@ use nom::{
sequence::{delimited, preceded, separated_pair, tuple}, sequence::{delimited, preceded, separated_pair, tuple},
}; };
#[derive(Debug, Clone)]
pub struct Literal<'a> {
pub tok: Token<'a>,
pub kind: LiteralKind,
}
#[derive(Debug, Clone)]
pub enum LiteralKind {
Num(u32),
Const(u32, u64),
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Call<'a> { pub struct Call<'a> {
pub name: Span<'a>, pub name: Span<'a>,
@ -42,10 +56,11 @@ pub struct UnOp<'a> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Expression<'a> { pub enum Expression<'a> {
Path(&'a str), Path(&'a str),
Literal(Token<'a>), Literal(Literal<'a>),
UnOp(Box<UnOp<'a>>), UnOp(Box<UnOp<'a>>),
BinOp(Box<BinOp<'a>>), BinOp(Box<BinOp<'a>>),
Call(Box<Call<'a>>), Call(Box<Call<'a>>),
BlockExpr(Box<BlockExpr<'a>>),
} }
/// expressions that can't be subdivided further /// expressions that can't be subdivided further
@ -55,7 +70,19 @@ fn atom(input: TokenSpan) -> IResult<TokenSpan, Expression> {
map(token(tk::Ident), |it| { map(token(tk::Ident), |it| {
Expression::Path(it.span().fragment()) Expression::Path(it.span().fragment())
}), }),
map(token(tk::Number), Expression::Literal), map(token(tk::Number), |tok| {
Expression::Literal(Literal {
tok,
kind: LiteralKind::Num(tok.span().parse().expect("invalid literal")),
})
}),
map(token(tk::Constant), |tok| {
let (_, (width, val)) = literals::const_bits(tok.span()).expect("invalid literal");
Expression::Literal(Literal {
tok,
kind: LiteralKind::Const(width, val),
})
}),
delimited(token(tk::LParen), expression, token(tk::RParen)), delimited(token(tk::LParen), expression, token(tk::RParen)),
))(input) ))(input)
} }
@ -119,11 +146,11 @@ pub fn call_item(input: TokenSpan) -> IResult<TokenSpan, Call> {
)(input) )(input)
} }
/// parser combinators can not parse left-recursive grammars. To work around this, we split
/// expressions into a recursive and non-recursive portion.
/// Parsers reachable from this point must call expression_nonrecurse instead
pub fn expression(input: TokenSpan) -> IResult<TokenSpan, Expression> { pub fn expression(input: TokenSpan) -> IResult<TokenSpan, Expression> {
bitop(input) alt((
bitop,
map(block_expr, |blk| Expression::BlockExpr(Box::new(blk))),
))(input)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,15 +1,27 @@
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of}, character::complete::{alpha1, alphanumeric1, char, digit1, multispace0, one_of},
combinator::{map, recognize}, combinator::{map, recognize},
error::ParseError, error::ParseError,
multi::{many0, many1}, multi::{many0, many1},
sequence::{delimited, pair, preceded, terminated}, sequence::{delimited, pair, preceded, separated_pair, terminated},
}; };
use crate::parser::{IResult, Span}; use crate::parser::{IResult, Span};
pub fn const_bits(input: Span) -> IResult<Span, (u32, u64)> {
map(
separated_pair(digit1, char('\''), digit1),
|(width, value): (Span, Span)| {
(
width.fragment().parse().expect("error parsing literal"),
value.fragment().parse().expect("error parsing literal"),
)
},
)(input)
}
pub fn hexadecimal(input: Span) -> IResult<Span, u64> { pub fn hexadecimal(input: Span) -> IResult<Span, u64> {
map( map(
preceded( preceded(

View File

@ -1,4 +1,5 @@
pub mod adt; pub mod adt;
pub mod block_expression;
pub mod comb; pub mod comb;
pub mod declaration; pub mod declaration;
pub mod error; pub mod error;

View File

@ -3,12 +3,11 @@ use nom::{
combinator::map, combinator::map,
error::context, error::context,
multi::{many1, separated_list1}, multi::{many1, separated_list1},
sequence::{delimited, separated_pair, tuple}, sequence::{delimited, tuple},
}; };
use crate::parser::{ use crate::parser::{
assign_statement, expression, assign_statement,
expression::{expression, Expression},
tokens::{token, TokenKind as tk, TokenSpan}, tokens::{token, TokenKind as tk, TokenSpan},
Assign, IResult, Span, Assign, IResult, Span,
}; };
@ -21,42 +20,7 @@ pub struct ProcBlock<'a> {
#[derive(Debug)] #[derive(Debug)]
pub enum ProcStatement<'a> { pub enum ProcStatement<'a> {
IfElse(IfElseBlock),
Assign(Assign<'a>), Assign(Assign<'a>),
Match(MatchBlock<'a>),
Block(Vec<ProcStatement<'a>>),
}
// TODO: postponed because annoying to implement
#[derive(Debug)]
pub struct IfElseBlock {}
#[derive(Debug)]
pub struct MatchBlock<'a> {
pub expr: Expression<'a>,
pub arms: Vec<(Expression<'a>, ProcStatement<'a>)>,
}
fn match_arm(input: TokenSpan) -> IResult<TokenSpan, (Expression, ProcStatement)> {
separated_pair(expression, token(tk::FatArrow), proc_statement)(input)
}
fn match_block(input: TokenSpan) -> IResult<TokenSpan, MatchBlock> {
context(
"match block",
map(
tuple((
token(tk::Match),
delimited(token(tk::LParen), expression, token(tk::RParen)),
delimited(
token(tk::LBrace),
separated_list1(token(tk::Comma), match_arm),
token(tk::RBrace),
),
)),
|(_, expr, arms)| MatchBlock { expr, arms },
),
)(input)
} }
fn statement_block(input: TokenSpan) -> IResult<TokenSpan, Vec<ProcStatement>> { fn statement_block(input: TokenSpan) -> IResult<TokenSpan, Vec<ProcStatement>> {
@ -69,11 +33,7 @@ fn statement_block(input: TokenSpan) -> IResult<TokenSpan, Vec<ProcStatement>> {
/// parse a statement that is valid inside a proc block /// parse a statement that is valid inside a proc block
fn proc_statement(input: TokenSpan) -> IResult<TokenSpan, ProcStatement> { fn proc_statement(input: TokenSpan) -> IResult<TokenSpan, ProcStatement> {
alt(( alt((map(assign_statement, ProcStatement::Assign),))(input)
map(match_block, ProcStatement::Match),
map(statement_block, ProcStatement::Block),
map(assign_statement, ProcStatement::Assign),
))(input)
} }
pub fn proc_block(input: TokenSpan) -> IResult<TokenSpan, ProcBlock> { pub fn proc_block(input: TokenSpan) -> IResult<TokenSpan, ProcBlock> {

View File

@ -2,7 +2,7 @@
use super::{ use super::{
error::{Error, InputPos}, error::{Error, InputPos},
literals::{identifier, ws0}, literals::{const_bits, identifier, ws0},
IResult, Span, IResult, Span,
}; };
use nom::{ use nom::{
@ -77,6 +77,7 @@ pub enum TokenKind {
// Literals // Literals
Ident, Ident,
Number, Number,
Constant,
// Keywords // Keywords
Module, Module,
Assign, Assign,
@ -186,6 +187,7 @@ fn lex_braces(input: Span) -> IResult<Span, Token> {
fn lex_literals(input: Span) -> IResult<Span, Token> { fn lex_literals(input: Span) -> IResult<Span, Token> {
map( map(
consumed(alt(( consumed(alt((
map(const_bits, |_| TokenKind::Constant),
map(identifier, |_| TokenKind::Ident), map(identifier, |_| TokenKind::Ident),
map(digit1, |_| TokenKind::Number), map(digit1, |_| TokenKind::Number),
))), ))),