I'm looking to learn and practice parsing, and so I have started with writing an EBNF for a number (using the python interpreter as an example of possible inputs).
Here is what I have so far (also viewable in
this playground, for which I've included a working screenshot below with a sample input):
/* +1.24E9 or +(1.24E9) or (+1.24E9) or --(-1.24E9) */ <number> ::= <signM> <float> <S> | <LParen> <float> <S> ")" <float> ::= "."? <digit>+ <exponent>? | <digit> "."? <digit>* <exponent>? <exponent> ::= ("e" | "E") <sign>? <digit>+ <LParen> ::= <signM> "(" <signM> <signM> ::= (<S> <sign> <S>)* <sign> ::= "+" | "-" <digit> ::= [0-9]+ /* optional whitespace */ <S> ::= " "*
Other than the obvious question of how can this be improved or simplified, here are a few questions:
- I feel like the code is littered with the optional whitespace, which I have defined as
<S>. How is this usually handled with in parsers? For example, here are a few valid inputsfor a number:
( 1.2 )and here are a few invalid inputs:
12 34. So sometimes the whitespace matters, but usually it does not.
- How to make sure that the parens are 'balanced'? Or is this not covered in
BNFand it's the responsibility of the parser to handle that? It's not covered in my grammar above, but being able to have something like:
((((((((((1))))))))))+((2+((2+2)))). (Again my point here is more for learning and not to actually build a useful numerical validator, which is why I've tried to accommodate a loose definition for a number.)
- Finally, what tools do you usually use to validate that your expressions are 'correct'? The only one I'm familiar with is https://bnfplayground.pauliankline.com/, and I don't know enough about BNF to know whether this is 'good' or not, though one thing that is a bit tedious is not allowing multiple inputs at the same time (for example most regex validators allow this -- one string per line or so).
Thank you for your help and time!