3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-07-20 11:22:05 +00:00

libparse: support space ANDs

This commit is contained in:
Emil J. Tywoniak 2025-07-11 23:09:30 +02:00
parent 4b1a8a3b66
commit c6e1d461fa
3 changed files with 32 additions and 19 deletions

View file

@ -163,6 +163,12 @@ void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string i
}
#ifndef FILTERLIB
// binary operators excluding ' '
bool LibertyExpression::is_nice_binop(char c) {
return c == '*' || c == '&' || c == '^' || c == '+' || c == '|';
}
// https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
if (s.empty())
@ -201,15 +207,8 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
while (true) {
if (s.empty())
break;
c = s.peek();
while (isspace(c)) {
if (s.empty())
return lhs;
s.next();
c = s.peek();
}
c = s.peek();
if (c == '\'') { // postfix NOT
if (min_prio > 7)
@ -235,11 +234,27 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
lhs = std::move(n);
continue;
} else if (c == '&' || c == '*') { // infix AND
// technically space should be considered infix AND. it seems rare in practice.
} else if (c == '&' || c == '*' || isspace(c)) { // infix AND
if (min_prio > 3)
break;
s.next();
if (isspace(c)) {
// Rewind past this space and any further spaces
while (isspace(c) && !s.empty()) {
if (s.empty())
return lhs;
s.next();
c = s.peek();
}
if (is_nice_binop(c)) {
// We found a real binop, so this space wasn't an AND
// and we just discard it as meaningless whitespace
continue;
}
} else {
// Rewind past this op
s.next();
}
auto rhs = parse(s, 4);
auto n = LibertyExpression{};
@ -310,7 +325,6 @@ bool LibertyExpression::eval(dict<std::string, bool>& values) {
std::string LibertyExpression::str(int indent)
{
std::string prefix;
prefix = std::string(indent, ' ');
switch (kind) {
case AND:
prefix += "(and ";
@ -337,10 +351,9 @@ std::string LibertyExpression::str(int indent)
bool first = true;
for (auto child : children) {
if (!first) {
prefix += "\n" + child.str(indent + add_indent);
} else {
prefix += child.str(0);
prefix += "\n" + std::string(indent + add_indent, ' ');
}
prefix += child.str(indent + add_indent);
first = false;
}
prefix += ")";