Skip to content

Instantly share code, notes, and snippets.

@Twisol
Created June 8, 2011 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Twisol/1014793 to your computer and use it in GitHub Desktop.
Save Twisol/1014793 to your computer and use it in GitHub Desktop.
%% name = Lupin::Parser
%% {
require 'rubinius/debugger'
require 'ast'
attr_accessor :ast
def process_string_escapes (text)
text = text.to_s
text.gsub! /\\(\d{1,3}|\D)/m do
seq = $1
case seq
when 'a' then "\a"
when 'b' then "\b"
when 'f' then "\f"
when 'n' then "\n"
when 'r' then "\r"
when 't' then "\t"
when 'v' then "\v"
when "\\" then "\\"
when "\r" then "\n"
when /\d{1,3}/ then seq.to_i.chr
else seq
end
end
text
end
}
# Top-level
root = - chunk:e - eof {@ast = e}
eof = !.
# A chunk is a block with no parent scope.
chunk = block
# TODO: add laststat (return/break)
block = (stat ";"?)*
# TODO: add actual statements
stat = expression
identifier = </[A-Za-z_][A-Za-z_0-9]*/> { text }
# Expressions
# The higher in the list, the later they're evaluated. (lower precedence)
expression = prec1
prec1 = prec2:value
(- (B_ "or" B_ {:or}
):op
- prec2:rhs
{ value = [op, value, rhs] }
)* {value}
prec2 = prec3:value
(- (B_ "and" B_ {:and}
):op
- prec3:rhs
{ value = [op, value, rhs] }
)* {value}
prec3 = prec4:value
(- ( "<" {:lt}
| ">" {:gt}
| "<=" {:lte}
| ">=" {:gte}
| "~=" {:neq}
| "==" {:eql}
):op
- prec4:rhs
{ value = [op, value, rhs] }
)* {value}
prec4 = prec5:value
(- ( ".." {:concat}
):op
- prec5:rhs
{ value = [op, value, rhs] }
)* {value}
prec5 = prec6:value
(- ( "+" {:add}
| "-" {:sub}
):op
- prec6:rhs
{ value = [op, value, rhs] }
)* {value}
prec6 = prec7:value
(- ( "*" {:mul}
| "/" {:div}
| "%" {:mod}
):op
- prec7:rhs
{ value = [op, value, rhs] }
)* {value}
prec7 = (B_ "not" B_ {:not}
| "#" {:len}
| "-" {:unm}
):op
- prec7:value
{ value = [op, value] }
| prec8:value
{value}
prec8 = prec9:lhs -
("^" {:pow}
):op -
prec8:rhs
{value = [op, lhs, rhs]}
| prec9:value
{ value }
prec9 = "(" - expression:value - ")" { value }
| prec10
prec10 = primitive
# Primitives
primitive = B_ "nil" B_ {[:nil]}
| B_ "false" B_ {[:false]}
| B_ "true" B_ {[:true]}
| "..." {[:varargs]}
| number
| string
# Numbers
number = (hex-literal | dec-literal):lit {[:number, lit]}
hex-literal = "0x" </[A-Fa-f0-9]+/> { text.to_i(16) }
dec-literal = dec-literal-base:b dec-literal-exponent:x { b * (10 ** x) }
| dec-literal-base
dec-literal-base = </\d*\.\d+/ | /\d+\.?/> { text.to_f }
dec-literal-exponent = /[Ee]/ </[+-]?\d+/> { text.to_i }
# Strings
string = (sgl-string | dbl-string | long-string):string {[:string, string]}
sgl-string = "'" </(\\.|[^\'\n])*/m> "'" {process_string_escapes(text)}
dbl-string = "\"" </(\\.|[^\"\n])*/m> "\"" {process_string_escapes(text)}
long-string = long-string-start:e
<(!long-string-end(e) .)*>
long-string-end(e)
{text}
long-string-equals = <"="*> {text}
long-string-start = "[" <long-string-equals> "[" {text}
long-string-end(eqs) = "]" long-string-equals:e &{e.length == eqs.length} "]"
# Whitespace/comments
- = (whitespace | comment)*
whitespace = /\s+/
comment = "--" (line-comment | block-comment):comment {[:comment, comment]}
line-comment = !long-string-start </[^\n]*/> ("\n" | eof) {text}
block-comment = long-string
B_ = /\b|^|$/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment