diff --git a/mode_c.py b/mode_c.py index daf4d8c..cf2341d 100644 --- a/mode_c.py +++ b/mode_c.py @@ -4,23 +4,29 @@ from mode_python import StringGrammar # this might not be complete... # see http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_3.html#SEC44 - class MacroGrammar(Grammar): rules = [ PatternRule('name', r'(?:(?<=#define )) *[a-zA-Z_][a-zA-Z0-9_]*'), - PatternRule('continued', r'\\ *$'), + + PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), + PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), + PatternRule(r"delimiter", r"->|\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=|\?"), + + PatternRule(r"integer", r"-?(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), + PatternRule(r"float", r"-?(?:[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+)"), RegionRule(r'string', '"', StringGrammar, '"'), - PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'") + PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'"), + + PatternRule(r"continued", r"\\\n$"), ] class CGrammar(Grammar): rules = [ PatternRule(r'include', r'#include(?!=[a-zA-Z0-9_])'), PatternRule(r'header', r'<[-A-Za-z/0-9_\.]+>|"[-A-Za-z/0-9_\.]+"'), - PatternRule(r'macro', r'#(?:else|endif)'), - RegionRule(r'macro', r'#(?:assert|cpu|define|elif|error|ident|ifdef|ifndef|if|import|include_next|line|machine|pragma|pragma_once|system|unassert|undef|warning)(?!=[a-zA-Z0-9_])', MacroGrammar, r'[^\\ ] *$'), - RegionRule(r'macrocomment', r'#if +(?:0|NULL|FALSE)', Grammar, r'#endif'), + RegionRule(r'macro', r'#(?:assert|cpu|define|elif|else|endif|error|ident|ifdef|ifndef|if|import|include_next|line|machine|pragma|pragma_once|system|unassert|undef|warning)(?!=[a-zA-Z0-9_])', MacroGrammar, r'\n$'), + RegionRule(r'comment', '/\*', Grammar, '\*/'), PatternRule(r'comment', r'//.*$'), @@ -41,7 +47,8 @@ class CGrammar(Grammar): PatternRule(r"integer", r"(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), PatternRule(r"float", r"[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+"), RegionRule(r'string', '"', StringGrammar, '"'), - PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'") + PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'"), + PatternRule(r"eol", r"\n$"), ] class CTabber(tab2.StackTabber): @@ -81,6 +88,9 @@ class CTabber(tab2.StackTabber): def _handle_open_token(self, currlvl, y, i): self._opt_pop('cont') + token = self.get_token(y, i) + if token.string == '{': + self._opt_pop('cond') currlvl = tab2.StackTabber._handle_open_token(self, currlvl, y, i) return currlvl def _handle_close_token(self, currlvl, y, i): @@ -89,7 +99,10 @@ class CTabber(tab2.StackTabber): token = self.get_token(y, i) if self.is_rightmost_token(y, i): if token.string == '}': + self._opt_pop('cond') self._opt_pop('cont') + elif self._peek_name() == 'cond': + pass else: self._opt_append('cont', currlvl + 4) return currlvl @@ -97,7 +110,18 @@ class CTabber(tab2.StackTabber): token = self.get_token(y, i) fqname = token.fqname() if fqname == 'delimiter' and token.string == ';': + self._opt_pop('cond') self._opt_pop('cont') + self._opt_pop('cond') + #currlvl = self.get_curr_level() + + elif fqname == 'keyword': + if token.string in ('do', 'else', 'for', 'if', 'while'): + self._append('cond', currlvl + 4) + elif token.string == 'break': + self._opt_pop('case') + elif token.string == 'case': + self._opt_append('case', currlvl + 4) elif fqname == 'string.start': self._opt_append('string', None) @@ -122,17 +146,17 @@ class CTabber(tab2.StackTabber): self._opt_pop('macroblock', None) if self.is_rightmost_token(y, i): - if(not fqname.startswith('string') and - not fqname.startswith('comment') and - not fqname.startswith('macro') and - not fqname == 'header' and - not fqname == 'null' and - token.string not in ('}', ';', '(', '{', '[', ',')): - try: - self._opt_append('cont', currlvl + 4) - except: - raise Exception, "%r + 4 for %r (%r) on line %d" % \ - (currlvl, fqname, token.string, y) + if self._has_markers() and self._peek_name() == 'cond': + pass + elif(not fqname.startswith('string') and + not fqname.startswith('comment') and + not fqname.startswith('macro') and + not fqname == 'delimiter' and + not fqname == 'header' and + not fqname == 'null' and + not fqname == 'eol' and + token.string not in ('}', ';', '(', '{', '[', ',')): + self._opt_append('cont', currlvl + 4) return currlvl class C(mode2.Fundamental): @@ -163,14 +187,21 @@ class C(mode2.Fundamental): 'macro.start': color.build('blue', 'default'), 'macro.name': color.build('yellow', 'default'), 'macro.null': color.build('magenta', 'default'), + #'macro.null': color.build('default', 'default'), 'macro.continued': color.build('red', 'default'), + 'macro.delimiter': color.build('default', 'default'), + 'macro.integer': color.build('green', 'default'), + 'macro.float': color.build('green', 'default'), 'macro.char': color.build('green', 'default'), 'macro.string.start': color.build('green', 'default'), 'macro.string.escaped': color.build('magenta', 'default'), 'macro.string.octal': color.build('magenta', 'default'), + #'macro.string.escaped': color.build('default', 'default'), + #'macro.string.octal': color.build('default', 'default'), 'macro.string.null': color.build('green', 'default'), 'macro.string.end': color.build('green', 'default'), 'macro.end': color.build('magenta', 'default'), + #'macro.end': color.build('default', 'default'), 'label': color.build('magenta', 'default'), 'keyword': color.build('cyan', 'default'), diff --git a/mode_perl.py b/mode_perl.py index ad65805..b330c72 100644 --- a/mode_perl.py +++ b/mode_perl.py @@ -99,7 +99,7 @@ class PerlGrammar(Grammar): PatternRule(r'operator2', r"(?:xor|or|not|ne|lt|le|gt|ge|eq|cmp|and)(?![a-zA-Z_])"), PatternRule(r'bareword', r'(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*'), - + PatternRule(r"eol", r"\n$"), ] class PerlTabber(tab2.StackTabber): diff --git a/tab2.py b/tab2.py index 058d17a..11503a3 100644 --- a/tab2.py +++ b/tab2.py @@ -164,8 +164,18 @@ class StackTabber(Tabber): def _handle_other_token(self, currlvl, y, i): return currlvl + def _has_markers(self): + return len(self.markers) > 0 + def _empty(self): + return len(self.markers) == 0 def _append(self, name, level): self.markers.append(Marker(name, level)) + def _peek(self): + return self.markers[-1] + def _peek_name(self): + return self.markers[-1].name + def _peek_level(self): + return self.markers[-1].level def _pop(self): self.markers.pop(-1) def _pop_until(self, *names): @@ -175,6 +185,7 @@ class StackTabber(Tabber): return else: self.markers.pop(-1) + def _opt_append(self, name, level): if self.markers and self.markers[-1].name == name: pass