diff --git a/application.py b/application.py index d55bbd8..940a94b 100755 --- a/application.py +++ b/application.py @@ -175,6 +175,7 @@ class Application(object): 'haskell', 'erlang', 'iperl', 'iperlmini', 'ipython', 'ipythonmini', 'awk', 'shell', 'shellmini', 'fstab', 'yacc', 'pipe', 'mbox', 'error', 'lua', 'lily', 'forth', 'ebnf', 'colortest', 'go', + 'inform6' ) for name in names: exec("import mode.%s; mode.%s.install(self)" % (name, name)) diff --git a/lex.py b/lex.py index 617b93c..23dbc22 100755 --- a/lex.py +++ b/lex.py @@ -129,6 +129,14 @@ class PatternRule(Rule): class NocasePatternRule(PatternRule): reflags = re.IGNORECASE +class KeywordRule(PatternRule): + def __init__(self, name, words, ahead='[a-zA-Z0-9_]'): + escaped = [re.escape(w) for w in sorted(words, reverse=True)] + pattern = '(?:%s)(?!%s)' % ('|'.join(escaped), ahead) + PatternRule.__init__(self, name, pattern) +class NocaseKeywordRule(KeywordRule): + reflags = re.IGNORECASE + class PatternMatchRule(PatternRule): reflags = 0 def __init__(self, name, pattern, *names): diff --git a/mode/inform6.py b/mode/inform6.py new file mode 100644 index 0000000..25f9a69 --- /dev/null +++ b/mode/inform6.py @@ -0,0 +1,103 @@ +from mode import Fundamental +from lex import Grammar, PatternRule, RegionRule, NocaseKeywordRule + +directives = '''abbreviate array attribute btrace class constant default +dictionary end endif etrace extend fake_action global ifdef ifndef iftrue +iffalse ifv3 ifv5 import include link listsymbols listdict listverbs lowstring +ltrace message nearby nobtrace noetrace noltrace notrace object property +release replace serial statusline stub switches system_file trace verb +zcharacter'''.split() + +defines = '''array attribute class constant fake_action global lowstring nearby +object property'''.split() + +attributes = '''absent animate clothing concealed container door edible +enterable female general light lockable locked male moved neuter on open +openable pluralname proper scenery scored static supporter switchable talkable +transparent visited workflag worn'''.split() + +properties = '''n_to s_to e_to w_to ne_to se_to nw_to sw_to u_to d_to in_to +out_to add_to_scope after article articles before cant_go capacity daemon +describe description door_dir door_to each_turn found_in grammar initial +inside_description invent life list_together name number orders parse_name +plural react_after react_before short_name time_left time_out when_closed +when_open when_on when_off with_key'''.split() + +keywords = '''box break class continue do else font off font on for give has +hasnt if inversion jump move new_line notin objectloop ofclass print print_ret +private quit read remove restore return rfalse rtrue save spaces string style +bold style fixed style reverse style roman style underline switch to until +while with'''.split() + +class StringGrammar(Grammar): + rules = [ + PatternRule('escaped', r'\\.'), + PatternRule('data', r'[^\\"]+'), + ] + +class NameGrammar(Grammar): + rules = [ + PatternRule('escaped', r'\\.'), + PatternRule('data', r"[^\\']+"), + ] + +class Inform6Grammar(Grammar): + rules = [ + PatternRule('comment', '!.*$'), + PatternRule('inform6.char', "'.(?://.+)'"), + RegionRule('inform6.name', "'", NameGrammar, "'"), + RegionRule('inform6.string', '"', StringGrammar, '"'), + NocaseKeywordRule('inform6.directive', directives), + NocaseKeywordRule('inform6.define', defines), + NocaseKeywordRule('inform6.attribute', attributes), + NocaseKeywordRule('inform6.property', properties), + NocaseKeywordRule('inform6.keyword', keywords), + PatternRule('inform6.number', '\$\$[01]+'), + PatternRule('inform6.number', '\$[0-9a-fA-F]+'), + PatternRule('inform6.number', '[0-9]+'), + PatternRule('inform6.label', '\.[a-zA-Z_][a-zA-Z0-9_]*'), + PatternRule('inform6.identifier', '[a-zA-Z_][a-zA-Z0-9_]*'), + PatternRule('inform6.word', '[a-zA-Z_]+'), + PatternRule('delimiter', r'[\(\)\{\}\[\];]'), + PatternRule('spaces', ' +'), + PatternRule('eol', '\n'), + PatternRule('continuation', r'\\\n$'), + ] + +class Inform6(Fundamental): + name = 'inform6' + extensions = ['.inf'] + grammar = Inform6Grammar + commentc = '!' + opentokens = ('delimiter',) + opentags = {'(': ')', '[': ']', '{': '}'} + closetokens = ('delimiter',) + closetags = {')': '(', ']': '[', '}': '{'} + colors = { + 'inform6.label': ('magenta', 'default', 'bold'), + 'inform6.define': ('magenta', 'default', 'bold'), + + 'inform6.directive': ('blue', 'default', 'bold'), + 'inform6.keyword': ('blue', 'default', 'bold'), + + 'inform6.attribute': ('cyan', 'default', 'bold'), + 'inform6.property': ('cyan', 'default', 'bold'), + + 'inform6.string.start': ('green', 'default', 'bold'), + 'inform6.string.escaped': ('magenta', 'default', 'bold'), + 'inform6.string.data': ('green', 'default', 'bold'), + 'inform6.string.end': ('green', 'default', 'bold'), + + 'inform6.name.start': ('green', 'default', 'bold'), + 'inform6.name.escaped': ('magenta', 'default', 'bold'), + 'inform6.name.data': ('green', 'default', 'bold'), + 'inform6.name.end': ('green', 'default', 'bold'), + + } + _bindings = { + 'close-paren': (')',), + 'close-brace': ('}',), + 'close-bracket': (']',), + } + +install = Inform6.install