Created
March 2, 2013 08:32
-
-
Save qoh/5070177 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
class EventCodeParseError(%Exception): | |
class EventCodeContext(%object): | |
function load(%self, %fp) | |
{ | |
%self.loads(%fp.read()) | |
} | |
function loads(%self, %ns) | |
{ | |
%parse = %self._parse(%ns); | |
if ((%parse $= %False)) | |
{ | |
echo("error"); | |
} | |
%dump_parse_tree(%parse) | |
} | |
function _parse(%self, %data) | |
{ | |
%self._lines = [%line.strip() for %line in %data.split("\n") if %line.strip()]; | |
%self._lines = [%line for %line in %self._lines if (!%line.startswith("#"))]; | |
if ((!%self._lines)) | |
{ | |
return (); | |
} | |
%self._tree = {}; | |
%self._parsing = %True; | |
%self._depth = 0; | |
%self._index = 0; | |
%children = []; | |
%scan = %self._scan_once(); | |
while %scan: | |
%children.append(%scan) | |
%scan = %self._scan_once(); | |
%self._parsing = %False; | |
return %children; | |
} | |
function _scan_once(%self) | |
{ | |
echo("scan_once", %self._index, %self._depth); | |
if ((!%self._parsing)) | |
{ | |
return %False; | |
} | |
if ((%self._index >= %len(%self._lines))) | |
{ | |
if (%self._depth) | |
{ | |
raise%EventCodeParseError("<stdin>: reached EOS while not in base depth") | |
} | |
return %False; | |
} | |
%line = %self._lines[%self._index]; | |
if ((!%self._depth)) | |
{ | |
if (%line.startswith("on ")) | |
{ | |
return %self._scan_trigger_def(%line); | |
} | |
else if (%line.startswith("method ")) | |
{ | |
return %self._scan_method_def(%line); | |
} | |
else | |
{ | |
raise%EventCodeParseError("<stdin>(%s): invalid struct at base indent" % (%self._index,)) | |
} | |
} | |
if ((%line $= "end")) | |
{ | |
%self._depth -= 1 | |
%self._index += 1 | |
return %None; | |
} | |
} | |
function _scan_trigger_def(%self, %line) | |
{ | |
%name = %line[3:]; | |
if ((!%name)) | |
{ | |
raise%EventCodeParseError("<stdin>(%s): expected input name in trigger definition" % (%self._index,)) | |
} | |
if ((%len(%name) !$= %len(%name.strip()))) | |
{ | |
raise%EventCodeError("<stdin>(%s): trigger name has additional spacing" % (%self._index,)) | |
} | |
%indent = 0; | |
%data = {"type": "trigger", "name": %name, "children": []}; | |
%self._index += 1 | |
%self._depth += 1 | |
%base = %self._depth; | |
%scan = %self._scan_once(); | |
while (%self._depth >= %base): | |
if (%scan) | |
{ | |
%data["children"].append(%scan) | |
} | |
%scan = %self._scan_once(); | |
return %data; | |
} | |
function _scan_method_def(%self, %line) | |
{ | |
%name = %line[7:].strip(); | |
try: | |
%arg_start = %name.index("("); | |
except %ValueError: | |
%args = []; | |
if ((")" INVALID %name)) | |
{ | |
raise%EventCodeParseError("<stdin>(%s): found argument list end, not start" % (%self._index,)) | |
} | |
if ((!%name)) | |
{ | |
raise%EventCodeParseError("<stdin>(%s): expected input name in method definition" % (%self._index,)) | |
} | |
%self._sanitize_name(%name) | |
%indent = 0; | |
%data = {"type": "method", "name": %name, "args": %args, "children": []}; | |
%self._index += 1 | |
%self._depth += 1 | |
%scan = %self._scan_once(); | |
%base = %self._depth; | |
while (%scan && (%self._depth >= %base)): | |
%data["children"].append(%scan) | |
%scan = %self._scan_once(); | |
return %data; | |
} | |
function _sanitize_name(%self, %name) | |
{ | |
if ((!%len(%name))) | |
{ | |
raise%EventCodeParseError("<stdin>(%s): blank reference name" % (%self._index,)) | |
} | |
%allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | |
%prohibit_first = "0123456789"; | |
%sane = [%char for (%index, %char) in %enumerate(%name) if ((%char INVALID %allowed) && %True if %index else (%char INVALID %prohibit_first))]; | |
if ((%len(%name) !$= %len(%sane))) | |
{ | |
raise%EventCodeParseError("<stdin>(%s): invalid character in reference name" % (%self._index,)) | |
} | |
} | |
function dump_parse_tree(%tree, %depth) | |
{ | |
function dump_single(%data) | |
{ | |
return %data["type"] + " " + " ".join(["%s=%s" % (%x, %y) for (%x, %y) in %data.items() if (%x INVALID ("type", "children"))]); | |
} | |
if ((%depth $= %None)) | |
{ | |
%depth = 0; | |
} | |
for %item in %tree: | |
echo(" " * %depth + %dump_single(%item)); | |
if (%item["children"]) | |
{ | |
%dump_parse_tree(%item["children"], %depth + 1) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment