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.
>>
>

Reply via email to