Skip to content

Instantly share code, notes, and snippets.

@matthewd
Created May 16, 2011 17:07
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 matthewd/974863 to your computer and use it in GitHub Desktop.
Save matthewd/974863 to your computer and use it in GitHub Desktop.
%%{
attr_accessor :heredocs
def setup
@heredocs = []
end
def heredoc(term, indent, value, dynamic)
h = heredoc_(term, indent, value, dynamic)
@heredocs << h
h
end
def pop_heredoc
@heredocs.pop
end
}
strings = string:s ~str(s)
| "%Q" /[^A-Za-z0-9]/:lft { strend = string_end(lft) } qstring([strend]):s .:rgt &{ rgt == strend } ~str(s)
| "%q" /[^A-Za-z0-9]/:lft { strend = string_end(lft) } lstring([strend], ["\\"]):s .:rgt &{ rgt == strend } ~str(s)
| "%" /[^A-Za-z0-9]/:lft { strend = string_end(lft) } qstring([strend]):s .:rgt &{ rgt == strend } ~str(s)
| "<<" "-"?:indent heredoc_ref(indent):r { r }
heredoc_ref(indent) = "'" < /[^']+/ > "'" { heredoc(text, !!indent, dstr_([]), false) }
| "\"" < /[^"]+/ > "\"" { heredoc(text, !!indent, dstr_([]), true) }
| "`" < /[^`]+/ > "`" { heredoc(text, !!indent, xstr_(dstr_([])), true) }
| < identifier > { heredoc(text, !!indent, dstr_([]), true) }
| < constant > { heredoc(text, !!indent, dstr_([]), true) }
%% heredoc_ = ast HereDoc(term, indent, value, dynamic)
newline = < ("\r" "\n"? | "\n") > @pending_heredocs { text }
pending_heredocs = &{ h = pop_heredoc } @pending_heredocs heredoc(h)
| &{ true }
heredoc_stop(h) = < /[^\r\n]*(?:\r\n?|\n)/ > &{ h.stop?(text) }
heredoc_line(h) = &{ h.dynamic } !heredoc_stop(h) qstring(NEWLINE):items newline:nl { items + [nl] }
| !{ h.dynamic } !heredoc_stop(h) lstring(NEWLINE, []):items newline:nl { items + [nl] }
heredoc(h) = heredoc_line(h)*:lines heredoc_stop(h) { lines.each do |l| l.each do |atom| h.value.parts << atom end end; h.collapse; nil }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment