0

I am looking for an unambiguous grammar for arithmetic expressions with no redundant parentheses. For example, parentheses are redundant in id+(id*id), but not in (id+id)*id.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Moonwild
  • 171
  • 1
  • 2
  • 9
  • [Reverse Polish Notation](http://en.wikipedia.org/wiki/Reverse_Polish_Notation) -- No redundant parenthesis :-) –  Jan 08 '11 at 07:42
  • I don't believe there is a sane way to *reject* input which contains "redundant" parenthesis with infix notation in a CFG. –  Jan 08 '11 at 07:45
  • But this question appears in some books as well as candidacy examination of penn state university! so, there should be some solution to it! – Moonwild Jan 08 '11 at 20:14
  • Maybe the answer to the question is "no; you can't do it in a context-free grammar, but we asked you the question to make you think about the issue and realize the limits of a context-free grammar". – Jonathan Leffler Oct 17 '12 at 15:36

2 Answers2

4

You can easily do this. The only time when parentheses become necessary is a sum to the right of a subtraction, a sum to the right of a multiplication, or a sum or multiplication to the right of a division.

You want to parse the expression as such:

An expression is either a single value, or a sum or product.

A sum is the sum or difference of one or more multiplicative terms or individual values, which we add left to right, so we parse right to left; the right side of a subtraction can be a parenthetical sum (but not a parenthetical multiplication).

A product has either a value or a parenthetical sum to the right of it; parenthetical multiplications can be to the right of a division, too, but values cannot. Values can never be in parentheses.

expr      ::= sum
expr      ::= product
expr      ::= value


sum       ::= sum addsub prodvalue
sum       ::= prodvalue addsub prodvalue
sum       ::= sum '-' parensum
sum       ::= prodvalue '-' parensum

addsub    ::= '+' | '-'

parensum  ::= '(' sum ')'

prodvalue ::= value
prodvalue ::= product

product   ::= prodterm muldiv value
product   ::= prodterm muldiv parensum
product   ::= prodterm '/' parenprod

prodterm  ::= prodvalue
prodterm  ::= parensum

parenprod ::= '(' product ')'

value     ::= [0-9]+.?
value     ::= [0-9]*.[0-9]+

I'm pretty sure this I hope this helps!

Editing some time later: I had made some mistakes, namely that I didn't handle addition correctly. I realized that subtraction is a problem. I've simplified the system and fixed the problems.

The only time parentheses can show up is around a nontrivial product that is to the right of a division, or around a nontrivial sum that is to the right of a division, a multiplication, or a subtraction, or around a sum that is at the left of a product.

  • @moonwild I'm sorry for having given an incomplete solution before; I finally came back and fixed this. I think this is a complete solution, now. – therealmarauder Apr 12 '23 at 18:12
2

It depends on exactly what you mean by 'for arithmetic expressions with no redundant parentheses'. This will accept expressions with no redundant parentheses, but will also accept arbitrarily nested parentheses:

expr   ::= factor
expr   ::= factor mul_div factor

mul_div ::= '*' | '/'

factor ::= term
factor ::= term add_sub term

add_sub ::= '+' | '-'

term   ::= NUMBER
term   ::= '(' expr ')'

I'm assuming that NUMBER manages to recognize signed numbers, so there is no unary plus or minus in there. You can work out how to handle them if you need them. You can also add variables etc if you need them.

If you mean a grammar that rejects expressions that have unnecessary parentheses, then I think you are on a search for the something that is not a context-free grammar.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • The point is that as you said in the last paragraph, it rejects expressions that have unnecessary parentheses, like in id+(id*id). – Moonwild Jan 08 '11 at 05:37
  • 1
    @Mahshid: I'm pretty sure that cannot be done with a context-free grammar. Not certain, but almost certain. You might also clarify the question so that everyone knows exactly what you are after. You might simply rewrite the last sentence: _For example, parentheses are redundant in `id+(id*id)` so the grammar should reject it, but they are not redundant in `(id+id)*id` so the grammar should accept it._ – Jonathan Leffler Jan 08 '11 at 05:41
  • This is a question from chapter 4 of this book: – Moonwild Jan 08 '11 at 05:48
  • Sorry for the incomplete comment. My OS crashed. This is the book: Introduction to Automata Theory, Languages, and Computation (2nd Edition). This is question 4.5, part b. – Moonwild Jan 08 '11 at 06:16
  • This is not an unambiguous grammar, in particular it does not guarantee nice behavior for subtraction followed by addition or division followed by multiplication, without parentheses. – lukstafi Aug 21 '12 at 20:02
  • @lukstafi: are you sure? You can only write either '`number - number`' or '`( number - number ) + number`'; you can't write '`number - number + number`' as valid syntax. – Jonathan Leffler Aug 21 '12 at 20:07
  • @JonathanLeffler you are right! I'm sorry, I haven't read the grammar carefully. – lukstafi Aug 21 '12 at 23:44
  • Is it intentional this grammar parses "1+2*3" as expr[ factor[ 1 + 2 ] * factor[ 3 ] ]? I would have expected grammar to have been specified in such a way to match normal operator precedence rules. – Aaron May 09 '13 at 03:16
  • @Aaron: not intentional. Feel free to suggest the relevant rewrite. – Jonathan Leffler May 09 '13 at 16:29