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