I also forgot to push the changes last night.
On Wednesday, June 4, 2014 11:01:33 PM UTC-4, Abe Schneider wrote: > > After playing around with a bunch of alternatives, I think I've come up > with decent action semantics: > > @transform <name> begin > <label> = <action> > end > > For example, a simple graph grammar might look like: > > @grammar nodetest begin > start = +node_def > node_def = node_label + node_name + lbrace + data + rbrace > node_name = string_value + space > > data = *(line + semicolon) > line = string_value + space > string_value = r"[_a-zA-Z][_a-zA-Z0-9]*" > > lbrace = "{" + space > rbrace = "}" + space > semicolon = ";" + space > node_label = "node" + space > space = r"[ \t\n]*" > end > > with it's actions to create some data structure: > > type MyNode > name > values > > function MyNode(name, values) > new(name, values) > end > end > > > with: > @transform tograph begin > # ignore these > lbrace = nothing > rbrase = nothing > semicolon = nothing > node_label = nothing > space = nothing > > # special action so we don't have to define every label > default = children > > string_value = node.value > value = node.value > line = children > data = MyNode("", children) > node_def = begin > local name = children[1] > local cnode = children[2] > cnode.name = name > return cnode > end > end > > and finally, to apply the transform: > > (ast, pos, error) = parse(nodetest, data) > result = apply(tograph, ast) > println(result) # {MyNode("foo",{"a","b"}),MyNode("bar",{"c","d"})} > > The magic in '@transform' basically just creates the dictionary like > before, but automatically wraps the expression on the RHS as an anonymous > function (node, children) -> expr. > > I'm currently looking for a better name than 'children', as it's > potentially confusing and misleading. It's actually the values of the child > nodes (as opposed to node.children). Maybe cvalues? > > On Sunday, May 25, 2014 10:28:45 PM UTC-4, Abe Schneider wrote: >> >> I wrote a quick PEG Parser for Julia with Packrat capabilities: >> >> https://github.com/abeschneider/PEGParser >> >> It's a first draft and needs a ton of work, testing, etc., but if this is >> of interest to anyone else, here is a quick description. >> >> Grammars can be defined using most of the standard EBNF syntax. For >> example, a simple math grammar can be defined as: >> >> @grammar mathgrammar begin >> >> start = expr >> number = r"([0-9]+)" >> expr = (term + op1 + expr) | term >> term = (factor + op2 + term) | factor >> factor = number | pfactor >> pfactor = ('(' + expr + ')') >> op1 = '+' | '-' >> op2 = '*' | '/' >> end >> >> >> >> To parse a string with the grammar: >> >> (node, pos, error) = parse(mathgrammar, "5*(2-6)") >> >> This will create an AST which can then be transformed to a value. >> Currently this is accomplished by doing: >> >> math = Dict() >> >> math["number"] = (node, children) -> float(node.value) >> math["expr"] = (node, children) -> >> length(children) == 1 ? children : eval(Expr(:call, children[2], >> children[1], children[3])) >> math["factor"] = (node, children) -> children >> math["pfactor"] = (node, children) -> children[2] >> math["term"] = (node, children) -> >> length(children) == 1 ? children : eval(Expr(:call, children[2], >> children[1], children[3])) >> math["op1"] = (node, children) -> symbol(node.value) >> math["op2"] = (node, children) -> symbol(node.value) >> >> >> Ideally, I would like to simplify this to using multi-dispatch on symbols >> (see previous post), but for now this is the easiest way to define actions >> based on node attributes. >> >> Finally, to transform the tree: >> >> result = transform(math, node) # will give the value of 20 >> >> Originally I was going to attach the transforms to the rules themselves >> (similiar to boost::spirit). However, there were two reasons for not doing >> this: >> >> 1. To implement the packrat part of the parser, I needed to cache the >> results which meant building an AST anyways >> 2. It's nice to be apply to get different transforms for the same >> grammar (e.g. you may want to transform the result into HTML, LaTeX, etc.) >> >> The downside of the separation is that it adds some more complexity to >> the process. >> >