Reputation: 8827
I have written a parser using treetop which successfully produces a parse tree, part of which is reproduced below.
SyntaxNode offset=4043, " ":
SyntaxNode offset=4043, " "
SyntaxNode offset=4044, " "
SyntaxNode offset=4045, " "
StringLiteral+StringLiteral1 offset=4046, "\"MS Sans Serif\"":
SyntaxNode offset=4046, "\""
SyntaxNode offset=4047, "MS Sans Serif":
SyntaxNode+StringLiteral0 offset=4047, "M":
SyntaxNode offset=4047, ""
SyntaxNode offset=4047, "M"
SyntaxNode+StringLiteral0 offset=4048, "S":
SyntaxNode offset=4048, ""
SyntaxNode offset=4048, "S"
SyntaxNode+StringLiteral0 offset=4049, " ":
SyntaxNode offset=4049, ""
SyntaxNode offset=4049, " "
SyntaxNode+StringLiteral0 offset=4050, "S":
SyntaxNode offset=4050, ""
SyntaxNode offset=4050, "S"
SyntaxNode+StringLiteral0 offset=4051, "a":
SyntaxNode offset=4051, ""
SyntaxNode offset=4051, "a"
SyntaxNode+StringLiteral0 offset=4052, "n":
SyntaxNode offset=4052, ""
SyntaxNode offset=4052, "n"
SyntaxNode+StringLiteral0 offset=4053, "s":
SyntaxNode offset=4053, ""
SyntaxNode offset=4053, "s"
SyntaxNode+StringLiteral0 offset=4054, " ":
SyntaxNode offset=4054, ""
SyntaxNode offset=4054, " "
SyntaxNode+StringLiteral0 offset=4055, "S":
SyntaxNode offset=4055, ""
SyntaxNode offset=4055, "S"
SyntaxNode+StringLiteral0 offset=4056, "e":
SyntaxNode offset=4056, ""
SyntaxNode offset=4056, "e"
SyntaxNode+StringLiteral0 offset=4057, "r":
SyntaxNode offset=4057, ""
SyntaxNode offset=4057, "r"
SyntaxNode+StringLiteral0 offset=4058, "i":
SyntaxNode offset=4058, ""
SyntaxNode offset=4058, "i"
SyntaxNode+StringLiteral0 offset=4059, "f":
SyntaxNode offset=4059, ""
SyntaxNode offset=4059, "f"
SyntaxNode offset=4060, "\""
Now that I have this tree, I don't know how to filter it so that I only process specific nodes that match a specific rule.
I am wanting to replace string literals with an identifier, that references the string in a string file.
cool_parser.treetop
rule string_literal
'"' (!'"' . / '""')* '"'
end
require 'treetop'
# Load the grammar
Treetop.load 'cool'
class Parser
# Create the parser
@@parser = CoolParser.new
def self.parse(data)
# Pass the data over to the parser instance
tree = @@parser.parse(data)
if(tree.nil?)
raise Exception, "Parse error at offset: #{@@parser.index}"
end
return tree
end
end
tree = Parser.parse(File.open("myfile.txt").read)
puts tree.inspect
Upvotes: 0
Views: 242
Reputation: 4132
I'm not sure what you mean by "replace with an identifier"? But, here's an example of returning the value of the string nodes as an array.
cool_parser.treetop
rule start
(not_string_literal / string_literal)*
{
def value
elements.map {|e| e.value }.compact
end
}
end
rule string_literal
'"' (!'"' . / '""')* '"'
{
def value
text_value
end
}
end
rule not_string_literal
!string_literal .
{
def value
end
}
end
Then access the parsed object's newly added value
method:
tree = Parser.parse(File.open("myfile.txt").read)
puts tree.value.inspect
# => ["\"strings\"", "\"sentences\""]
Upvotes: 1