Skip to content

Instantly share code, notes, and snippets.

View gosukiwi's full-sized avatar

Federico Ramirez gosukiwi

View GitHub Profile
class BoldVisitor
def visit(node)
"<strong>#{node.value}</strong>"
end
end
class EmphasisVisitor
def visit(node)
"<em>#{node.value}</em>"
end
class SentenceVisitor
SENTENCE_VISITORS = {
"BOLD" => BoldVisitor,
"EMPHASIS" => EmphasisVisitor,
"TEXT" => TextVisitor
}.freeze
def visit(node)
visitor_for(node).visit(node)
end
class ParagraphVisitor
def visit(paragraph_node)
"<p>#{sentences_for(paragraph_node)}</p>"
end
private
def sentences_for(paragraph_node)
paragraph_node.sentences.map do |sentences|
sentence_visitor.visit(sentences)
class BodyVisitor
def visit(body_node)
body_node.paragraphs.map do |paragraph|
paragraph_visitor.visit(paragraph)
end.join
end
private
def paragraph_visitor
class Generator
def generate(ast)
body_visitor.visit(ast)
end
private
def body_visitor
BodyVisitor.new
end
Body := Paragraph*
Paragraph := SentenceAndNewline
| SentenceAndEOF
SentenceAndNewline := Sentence+ NEWLINE NEWLINE
SentencesAndEOF := Sentence+ NEWLINE EOF
| Sentence+ EOF
Sentence := EmphasizedText
Start := Binop
Binop := Subtraction
Subtraction := Adition "-" Binop
| Adition
Adition := Division "+" Binop
| Division
Division := Multiplication "/" Binop
| Multiplication
Multiplication := Number "*" Binop
| Number
class BaseParser
private
# We use some reflection to prettify the parser depedencies. Basically, from
# calling a `foo_parser` method is the same as doing `ParserFactory.build('foo_parser')`.
#
def method_missing(name, *args, &block)
raise ArgumentError.new("Method #{name} does not exist.") unless name.to_s.end_with?('_parser')
ParserFactory.build(name, *args, &block)
end
Start := Binop
Binop := Binop Operator Binop
| Number
Operator := + | - | * | /
Number := 0 | 1 | 2 | ... | 9
+------[START]----------+
| | |
v v v
[NUMBER=2] [OPERATOR=+] [BINOP]
|
+------------+----------+
| | |
v v v
[NUMBER=2] [OPERATOR=-] [NUMBER=4]