zevv / npeg

PEGs for Nim, another take
MIT License
330 stars 22 forks source link

Help - how to handle captures and optionals #71

Closed mantielero closed 8 months ago

mantielero commented 8 months ago

I am having two difficutties and probably I am not using probably npeg here.

First issue: capturing optional elements

title <- >( whatever)
attributes <- >(whatever2)
delimitedBlocks <- ?title * >?attributes * >body:
   mycode

Given above's situation, $1 could be tittle, attributes or body. How can I check what it is? If in the code I do echo capture, the field name is empty.

Second issue: creating objects

I want to capture above's data in a ref object, where should I create it?

var blk:Block
new(blk)

I'd like to create the object in one place in order to do something like:

let parserBlocks* = peg("delimitedBlocks", myBlk):
  title <- >( whatever):
    blk.title = $1
  attributes <- >(whatever2):
    blk.attributes = $2
  delimitedBlocks <- ?title * >?attributes * >body:
    blk.body 
    myBlk.blocks &= blk
mantielero commented 8 months ago

Right now solved with closures:

proc parserBlocksGen():auto =
    var db:Block
    new(db)

    return  peg("delimitedBlocks", blk: Block):
              # Title
              title     <- '.' * >adoc.txt * adoc.crlf:
                db.title = $1
              attributes <- '[' * >*(1 - '[' - ']' - '\r' - '\n') * ']' * adoc.crlf:
                db.attributes = $1
              delimitedBlocks <- ?title * ?attributes * >R("blockDelimiter", adoc.blockDelimiters  * adoc.crlf ) * >*(!R("blockDelimiter") * *(1 - '\r' - '\n') * adoc.crlf) * R("blockDelimiter"):
                db.content = $2
                db.delimiter = $1

                blk.blocks &= db

let parserBlocks* = parserBlocksGen()

I will close this issue. If there is a better pattern, let me know: