in reply to Re: Parse:RecDescent grammar help
in thread Parse:RecDescent grammar help


Hi Phillip,

Firstly, as Tachyon says these rules can get really funky really quickly, especialy when you want to try and model nested things of conditional instructions (as I'm finding out for with my tinkering).
That aside I've remodelled my rules(using my last example code) to accomodate the type of entries you wanted. First here are some definitions.... in my little language these are my types...

5 # Any number is a 'literal'
"fluffy" # encased text I call an 'identifier'
$cuddles # this is a 'variable'
@animals # this is an 'array'
%stuff # this is a hash


Now if you follow the rules you'll see that you can pretty much have any cobination of these...so you can do seksi things like this.. (put this in the text section from before as an example)

%stuff = { animal => @pets, age => 5, name => "fluffy", colour => $col };


(Just as a side note the $a = "hello" and $b = "world" should have already worked with my existing program, this bit is so you can embed 'variable's and 'array's in things)


Replace all the bits in my 'rules' section from before with the following and that should spice things up...
# --- Rules --- parse : stmt(s?) EOF { $item[1] } stmt : variable ';' { $item[1] } | array ';' { $item[1] } | hash ';' { $item[1] } | <error> arrayelement : term ',' { [ @item[0, 1] ] } | term { [ @item[0, 1] ] } arrayname : ARRAY IDENTIFIER { [ 'array', $item[2] ] } array : arrayname EQUAL arrayelement(s?) { [ @item[2, 4] ] } hashelement : IDENTIFIER HASHASSIGN term ',' { [ @item[0,1 +,3] ] } | IDENTIFIER HASHASSIGN term { [ @item[0,1,3] +] } hash : HASH IDENTIFIER EQUAL '{' hashelement(s?) '} +' { [ @item [0, 2, 5] ] } variablename : VAR IDENTIFIER { [ 'variable', $item[2] ] } variable : variablename EQUAL term { [ @item[0, 2, 4] ] } term : QUOTE IDENTIFIER QUOTE { [ 'identifier', $it +em[2] ] } | LITERAL { [ 'literal', $item[1] ] } | arrayname { $item[1] } | variablename { $item[1] }


....and the output for the example I gave you...
$VAR1 = [ [ 'hash', 'stuff', [ [ 'hashelement', 'animal', [ 'array', 'pets' ] ], [ 'hashelement', 'age', [ 'literal', '5' ] ], [ 'hashelement', 'name', [ 'identifier', 'fluffy' ] ], [ 'hashelement', 'colour', [ 'variable', 'col' ] ] ] ] ];

Have phun...
Regards Paul

Replies are listed 'Best First'.
Re^3: Parse:RecDescent grammar help
by pip9ball (Acolyte) on Oct 26, 2004 at 13:39 UTC
    Paul,

    Thank-you for the reply...I will try these changes out after Jury Duty :-(

    From the examples yourself and tachyon provided, I realize that the output of what's parsed can become very complex and get nasty real quick. Perhaps I'll need to set some limitations on how many nested statments are allowed...otherwise retreiving this data is going to be a nightmare.

    Thanks again!

    -Phillip


      Phillip,


      Limiting the rules.....Hmm I'm not sure how you do that. Once you make it recursive you can just keep on embedding and it will parse to its hearts content.
      Which then kinda puts the onus on have a smart system to traverse sed data. One the top level of the tree it would be a trivial task to search upper nodes for ones of say type 'array' then search that list for the presence of the correct one.
      I'm kinda enjoying this actually, because now I'm a lot more equipped to play with some of my rules after tinkering with this.


      Regards Paul
Re^3: Parse:RecDescent grammar help
by pip9ball (Acolyte) on Oct 27, 2004 at 02:11 UTC
    Paul, What version of perl are you using to produce this output. I am getting errors with the following input data.

    my $text = q {@dogs = ["dollar","mack"]; %myHash = {animals => @dogs, age = 5, names=> "fluffy"}; }; my $result = $parser->parse(\$text); OUTPUT ERROR (line -1): Invalid stmt: Was expecting ';' but found "["dollar","mack"];" instead Bad text.

    Thanks, -Phillip


      Phillip,
      This is because the rule format for Array I implemented is the following...

      @array = thing1, thing2, ....
      your example
      @dogs = [ "dollar", "mack" ];
      My method doesn't support the brackets yet. Its hard when you're making it from scratch and it looks like perl not to auto-assume that it would auto perform therse things but you would have to tell it how to do them...

      I removed the brackets and ran with the following... @dogs = "dollar", "mack";
      and it now runs but gives me gumby output see below:
      $VAR1 = [ [ '=', undef ] ];

      ok so mistake on my part =P replace the 'array' rule with this.. array     : arrayname EQUAL arraelement(s?) { [ @item[1,3] ] }
      now we add both lines back in...
      @dogs = "dollar", "mack"; %myHash = {animals => @dogs, age = 5, names=> "fluffy"}; gives the following output =) <code> $VAR1 = [ [ [ 'array', 'dogs' ], [ [ 'arrayelement', [ 'identifier', 'dollar' ] ], [ 'arrayelement', [ 'identifier', 'mack' ] ] ] ], [ 'hash', 'myHash', [ [ 'hashelement', 'animals', [ 'array', 'dogs' ] ], [ 'hashelement', 'age', [ 'literal', '5' ] ], [ 'hashelement', 'names', [ 'identifier', 'fluffy' ] ] ] ] ];

      A few things to note .... =)
      - The reference to '@dogs' in the myHash is just stored as text that is told to be of 'array' in the hash. It would be your job to search the tree so see if you had a valid array called 'dogs' in the tree to get data from, it doesn't auto put the dogs array inside the hash or make any kewl little pointers or anything.
      - I mentioned in my last note that you could pretty much use any combination or literal, itentifier, array or hash, but you can't actually have hashes embedded i.e. hashes of hashes. This is an easy change...just see what I did to the 'array' and 'variable' types.
      - You can easily make is so that you array rule did accomodate brackets too....think along the line of adding something like..
      array : arrayname EQUAL arrayelement(s?) { [ @item[1,3] ] } : arrayname EQUAL '[' arrayelement(s?) ']' { [ @item[1,4] ] }


      Regards Paul =)
      p.s. I'm using v5.8.4