Skip to content

Instantly share code, notes, and snippets.

@vy-let
Created June 23, 2014 00:28
Show Gist options
  • Save vy-let/fee79dae38a7d4eec646 to your computer and use it in GitHub Desktop.
Save vy-let/fee79dae38a7d4eec646 to your computer and use it in GitHub Desktop.
Smilef Shell Prototype Parser
#!/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