Created
June 23, 2014 00:28
-
-
Save vy-let/fee79dae38a7d4eec646 to your computer and use it in GitHub Desktop.
Smilef Shell Prototype Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
#encoding: utf-8 | |
require 'yaml' | |
require 'readline' | |
require 'parslet' | |
# | |
# Prototype Parser | |
# for the Smilef Shell Language | |
# by Talus Baddley (© 2014) | |
# | |
# “Smilef Makes Illegal Letters Enumerate Fewer. [-_^]” | |
# | |
# | |
# Examples: | |
# ^_^ [ btw This is a comment. 'btw' will be a function that evaluates to nil. ] | |
# ^_^ -> [history] [grep 'ditto -vcz'] [mate] [btw Pipe some things.] | |
# ^_^ vim /dev/random [btw Plain commands look the same.] | |
# ^_^ rm -rf [~ Downloads] [btw The function '~' will prepend the home dir.] | |
# ^_^ echo "Your Ruby lives at [which ruby]." [btw Double-quoted string interpolation.] | |
# | |
# | |
# Currently reads one line from the terminal | |
# and outputs the yaml of the parse tree. | |
# More info, and implementation, forthcoming. | |
# | |
class SmilefLang < Parslet::Parser | |
def any_except atom | |
atom.absent? >> any | |
end | |
rule(:toplevel) { space? >> (expressions.as(:expr_list) | expr_body.as(:implied_expr)) >> space? } | |
rule(:expressions) { expression >> (space >> expression).repeat(0) } | |
rule(:token) { expression | string } | |
rule(:expression) { lparen >> expr_body >> rparen } | |
rule(:expr_body) { ( | |
token.as(:expr_head) >> | |
(space >> token).repeat(0).as(:expr_args) | |
).as(:expr) } | |
rule(:string) { single_str | double_str | bare_str } | |
rule(:single_str) { str("'") >> single_body.as(:str_components) >> str("'") } | |
rule(:single_body) { (single_text_literal | single_quot_literal).repeat(0) } | |
rule(:single_text_literal) { any_except(str("'")).repeat(1).as(:text_literal) } | |
rule(:single_quot_literal) { str("''").as(:sq_literal) } | |
rule(:double_str) { str('"') >> double_body.as(:str_components) >> str('"') } | |
rule(:double_body) { (double_text_literal | expression | double_quot_literal | double_paren_literal).repeat(0) } | |
rule(:double_text_literal) { any_except( str('"') | expression | double_paren_literal ).repeat(1).as(:text_literal) } | |
rule(:double_quot_literal) { str('""').as(:dq_literal) } | |
rule(:double_paren_literal) { lparen.as(:text_literal) >> rparen } # Taking advantage of the fact that empty expressions are disallowed, this makes a literal [. | |
rule(:bare_str) { any_except( space | rparen ).repeat(1).as(:text_literal) } | |
rule(:lparen) { str('[') >> space? } | |
rule(:rparen) { space? >> str(']') } | |
rule(:space) { match('\s').repeat(1) } | |
rule(:space?) { space.maybe } | |
root(:toplevel) | |
end | |
begin | |
ligne = Readline.readline ' ^_^ ', true | |
puts YAML.dump( SmilefLang.new.parse ligne ) | |
rescue Parslet::ParseFailed => failure | |
puts failure.cause.ascii_tree | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment