Einrückungssensitiver Parser mit Parslet in Ruby?

Ich versuche, eine einfache einrückungssensitive Syntax mit der zu analysierenParslet Bibliothek in Ruby.

Das Folgende ist ein Beispiel für die Syntax, die ich zu analysieren versuche:

level0child0
level0child1
  level1child0
  level1child1
    level2child0
  level1child2

Der resultierende Baum würde so aussehen:

[
  {
    :identifier => "level0child0",
    :children => []
  },
  {
    :identifier => "level0child1",
    :children => [
      {
        :identifier => "level1child0",
        :children => []
      },
      {
        :identifier => "level1child1",
        :children => [
          {
            :identifier => "level2child0",
            :children => []
          }
        ]
      },
      {
        :identifier => "level1child2",
        :children => []
      },
    ]
  }
]

Der Parser, den ich jetzt habe, kann Knoten der Verschachtelungsebenen 0 und 1 analysieren, kann aber nicht darüber hinaus analysieren:

require 'parslet'

class IndentationSensitiveParser < Parslet::Parser

  rule(:indent) { str('  ') }
  rule(:newline) { str("\n") }
  rule(:identifier) { match['A-Za-z0-9'].repeat.as(:identifier) }

  rule(:node) { identifier >> newline >> (indent >> identifier >> newline.maybe).repeat.as(:children) }

  rule(:document) { node.repeat }

  root :document

end

require 'ap'
require 'pp'

begin
  input = DATA.read

  puts '', '----- input ----------------------------------------------------------------------', ''
  ap input

  tree = IndentationSensitiveParser.new.parse(input)

  puts '', '----- tree -----------------------------------------------------------------------', ''
  ap tree

rescue IndentationSensitiveParser::ParseFailed => failure
  puts '', '----- error ----------------------------------------------------------------------', ''
  puts failure.cause.ascii_tree
end

__END__
user
  name
  age
recipe
  name
foo
bar

Es ist klar, dass ich einen dynamischen Zähler benötige, der erwartet, dass 3 Einrückungsknoten mit einem Bezeichner auf der Verschachtelungsebene 3 übereinstimmen.

Wie kann ich mit Parslet auf diese Weise einen einrückungssensitiven Syntaxparser implementieren? Ist es möglich?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage