work around operator left recursion
This commit is contained in:
parent
edab641506
commit
b4e31d2bc8
|
@ -178,6 +178,7 @@ fn lower_expression(
|
|||
module.add_cell(cell);
|
||||
Ok(output_gen_wire)
|
||||
}
|
||||
// operations should really just desugar to callables
|
||||
parser::Expression::Operation(_op) => todo!("operators not yet implemented"),
|
||||
parser::Expression::Literal(lit) => {
|
||||
Ok(rtlil::SigSpec::Const(*lit as i64, TODO_WIDTH))
|
||||
|
|
|
@ -61,8 +61,8 @@ pub struct Assign<'a> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum Operation<'a> {
|
||||
And { a: String, b: Expression<'a> },
|
||||
Or { a: String, b: Expression<'a> },
|
||||
And { a: Expression<'a>, b: Expression<'a> },
|
||||
Or { a: Expression<'a>, b: Expression<'a> },
|
||||
Not(Expression<'a>),
|
||||
}
|
||||
|
||||
|
@ -100,16 +100,16 @@ fn operation(input: Span) -> IResult<Span, Operation> {
|
|||
// temporarily given up on before I learn the shunting yard algorithm
|
||||
alt((
|
||||
map(
|
||||
separated_pair(ws0(identifier), char('&'), ws0(expression)),
|
||||
separated_pair(ws0(expression_nonrecurse), char('&'), ws0(expression)),
|
||||
|(a, b)| Operation::And {
|
||||
a: (*a.fragment()).into(),
|
||||
a,
|
||||
b,
|
||||
},
|
||||
),
|
||||
map(
|
||||
separated_pair(ws0(identifier), char('|'), ws0(expression)),
|
||||
separated_pair(ws0(expression_nonrecurse), char('|'), ws0(expression)),
|
||||
|(a, b)| Operation::Or {
|
||||
a: (*a.fragment()).into(),
|
||||
a,
|
||||
b,
|
||||
},
|
||||
),
|
||||
|
@ -134,14 +134,25 @@ fn call_item(input: Span) -> IResult<Span, Call> {
|
|||
)(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
|
||||
fn expression(input: Span) -> IResult<Span, Expression> {
|
||||
alt((
|
||||
map(ws0(decimal), |lit| Expression::Literal(lit)),
|
||||
map(ws0(operation), |op| Expression::Operation(Box::new(op))),
|
||||
expression_nonrecurse
|
||||
))(input)
|
||||
}
|
||||
|
||||
/// the portion of the expression grammar that can be parsed without left recursion
|
||||
fn expression_nonrecurse(input: Span) -> IResult<Span, Expression> {
|
||||
alt((
|
||||
map(ws0(decimal), |lit| Expression::Literal(lit)),
|
||||
map(ws0(call_item), |call| Expression::Call(Box::new(call))),
|
||||
map(ws0(identifier), |ident| {
|
||||
Expression::Ident(*ident.fragment())
|
||||
}),
|
||||
delimited(char('('), expression, char(')')),
|
||||
))(input)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue