Skip to content

Instantly share code, notes, and snippets.

View gosukiwi's full-sized avatar

Federico Ramirez gosukiwi

View GitHub Profile
class SentenceParser < BaseParser
def match(tokens)
match_first tokens, emphasis_parser, bold_parser, text_parser
end
end
class BoldParser < BaseParser
def match(tokens)
return Node.null unless tokens.peek_or(%w(UNDERSCORE UNDERSCORE TEXT UNDERSCORE UNDERSCORE), %w(STAR STAR TEXT STAR STAR))
Node.new(type: 'BOLD', value: tokens.third.value, consumed: 5)
end
end
class TextParser < BaseParser
def match(tokens)
return Node.null unless tokens.peek('TEXT')
Node.new(type: 'TEXT', value: tokens.first.value, consumed: 1)
end
end
+------[START]--------+
| | |
v v v
[BINOP] [OPERATOR=-] [NUMBER=4]
|
+------------+----------+
| | |
v v v
[NUMBER=2] [OPERATOR=+] [NUMBER=2]
+------[START]----------+
| | |
v v v
[NUMBER=2] [OPERATOR=+] [BINOP]
|
+------------+----------+
| | |
v v v
[NUMBER=2] [OPERATOR=-] [NUMBER=4]
Start := Binop
Binop := Binop Operator Binop
| Number
Operator := + | - | * | /
Number := 0 | 1 | 2 | ... | 9
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 := Subtraction
Subtraction := Adition "-" Binop
| Adition
Adition := Division "+" Binop
| Division
Division := Multiplication "/" Binop
| Multiplication
Multiplication := Number "*" Binop
| Number
Body := Paragraph*
Paragraph := SentenceAndNewline
| SentenceAndEOF
SentenceAndNewline := Sentence+ NEWLINE NEWLINE
SentencesAndEOF := Sentence+ NEWLINE EOF
| Sentence+ EOF
Sentence := EmphasizedText
class Generator
def generate(ast)
body_visitor.visit(ast)
end
private
def body_visitor
BodyVisitor.new
end