Posted to tcl by evilotto at Mon Jul 15 21:58:00 GMT 2013view pretty

driver:
package require pt::peg::from::peg
package require pt::peg::container
package require pt::peg::interp
package require pt::ast

set f [open [lindex $argv 0]]
set ldef [read $f]
close $f

set stream [open [lindex $argv 1]]

pt::peg::container lang
pt::peg::interp L
lang deserialize = [pt::peg::from::peg convert $ldef]
L use lang

set ast [L parse $stream]

seek $stream 0
set data [read $stream]

proc exp_ast_nt {a} {
    if {[llength $a] == 3} {
        return [list [string range $::data [lindex $a 1] [lindex $a 2]]]
    } else {
        return [list  {*}[lmap st [lrange $a 3 end] {exp_ast_nt $st}]]
    }
}

proc exp_ast {a} {
    if {[llength $a] == 3} {
        return [list [lindex $a 0] [string range $::data [lindex $a 1] [lindex $a 2]]]
    } else {
        return [list [lindex $a 0]  {*}[lmap st [lrange $a 3 end] {exp_ast $st}]]
    }
}

foreach r [exp_ast $ast] { puts $r}

puts "\nsimple:"
foreach r [exp_ast_nt $ast] { puts $r}


Grammar:
PEG harzilein (command) 
 command <- cmdname S* '{' S* operation? (S* ';' S* operation?)* '}' ;
 operation <- assignment / command ;
 assignment <- varname S* '=' S* multivalue ;
 multivalue <- assignment / value;

 leaf: cmdname <- ident ;
 leaf: varname <- ident ; 
 leaf: value <- ident ;
 ident <- ('_' / <alnum>)+ ;
 void: S <- <space> ;
END;

Language test:
command { foo = bar ; bar = baz ; nested_bar {foo=quux = quuuux}}

Result:
command
cmdname command
operation {assignment {varname foo} {multivalue {value bar}}}
operation {assignment {varname bar} {multivalue {value baz}}}
operation {command {cmdname nested_bar} {operation {assignment {varname foo} {multivalue {assignment {varname quux} {multivalue {value quuuux}}}}}}}

simple:
command
{foo bar}
{bar baz}
{nested_bar {{foo {{quux quuuux}}}}}