52 lines
1.4 KiB
Ruby
52 lines
1.4 KiB
Ruby
|
|
module Vm
|
|
class Parser < Parslet::Parser
|
|
rule(:name) { match('[a-z]').repeat(1).as(:name) >> space? }
|
|
rule(:number) { match('[0-9]').repeat(1).as(:number) >> space? }
|
|
rule(:space) { match('\s').repeat(1) }
|
|
rule(:space?) { space.maybe }
|
|
|
|
rule(:args) {
|
|
lparen >>
|
|
((expression.as(:arg) >> (comma >> expression.as(:arg)).repeat(0)).maybe).as(:args) >>
|
|
rparen
|
|
}
|
|
|
|
rule(:funcall) { name.as(:funcall) >> args }
|
|
|
|
rule(:expression) { cond | funcall | number | name }
|
|
|
|
rule(:lparen) { str('(') >> space? }
|
|
rule(:rparen) { str(')') >> space? }
|
|
rule(:comma) { str(',') >> space? }
|
|
|
|
rule(:cond) {
|
|
if_kw >> lparen >> expression.as(:cond) >> rparen >>
|
|
body.as(:if_true) >>
|
|
else_kw >>
|
|
body.as(:if_false)
|
|
}
|
|
|
|
rule(:body) { lbrace >> expression.as(:body) >> rbrace }
|
|
rule(:lbrace) { str('{') >> space? }
|
|
rule(:rbrace) { str('}') >> space? }
|
|
rule(:comma) { str(',') >> space? }
|
|
rule(:if_kw) { str('if') >> space? }
|
|
rule(:else_kw) { str('else') >> space? }
|
|
|
|
rule(:func) {
|
|
func_kw >> name.as(:func) >> params >> body
|
|
}
|
|
|
|
rule(:func_kw) { str('function') >> space? }
|
|
|
|
rule(:params) {
|
|
lparen >>
|
|
((name.as(:param) >> (comma >> name.as(:param)).repeat(0)).maybe).as(:params) >>
|
|
rparen
|
|
}
|
|
|
|
rule(:root) { func.repeat(0) >> expression }
|
|
end
|
|
end
|