How can I define an INI file grammar using the BNFC?

bnf, context-free-grammar, ebnf, haskell, parsing

Solution

I asked one of the BNFC devs and quote his reply here:

Space characters such as newlines are not well supported in tokens, because BNFC has a hard-wired lexer type "space". The idea is that spaces can't carry meaning in "well-behaved" languages. One of those restrictions that has made BNFC so simple... but you should be able solve this by using a preprocessor, e.g. parse input line by line.

Like for example:

entrypoints File ;

comment "#" ;

token ID ( letter | digit | ["-_'"] )+ ;

Ini. File ::= [Section] ;
Sect. Section ::= "[" ID "]" [Statement] ;
Bind. Statement ::= ID "=" ID ;

separator Statement "//" ;
terminator Section "//" ;

Read:

[name]
x = 10
y = 20

Preprocess:

[name]//
x = 10//
y = 20//

Parse:

Ini [Sect (ID "name") [Bind (ID "x") (ID "10"), Bind (ID "y") (ID "20")]]

Transform:

                                          ↓                       ↓
Ini [Sect (ID "name") [Bind (ID "x") (ID "0"), Bind (ID "y") (ID "0")]]

Write:

[name]//
x = 0//
y = 0//

Postprocess:

[name]
x = 0
y = 0

(not checked, don't know if it works, just to give an idea!!)

Problem

http://www.cs.chalmers.se/Cs/Research/Language-technology/BNFC/ how should I write my labeled BNF to get BNFC to generate a INI parser for me? I have only gotten so far o__O! ``` entrypoints File ; comment "#" ; token ID ( letter | digit | ["-_'"] )+ ; Ini. File ::= [Section] ; Sect. Section ::= "[" ID "]" [Statement] ; Bind. Statement ::= ID "=" ID ; separator Statement "\n" ; terminator Section "" ; ``` ``` [name] #x = 10 y = 20 ``` ``` Parse Successful! [Abstract Syntax] Ini [Sect (ID "name") [Bind (ID "y") (ID "20")]] [Linearized tree] [name]y = 20 ``` ``` [name] x = 10 #y = 20 ``` ``` Parse Successful! [Abstract Syntax] Ini [Sect (ID "name") [Bind (ID "x") (ID "10")]] [Linearized tree] [name]x = 10 ``` o__O I'm stuck ...

Original source