From bfa188627e04f34d1d734db39f69caf37312eda8 Mon Sep 17 00:00:00 2001 From: moculus Date: Tue, 3 Feb 2009 14:56:22 +0000 Subject: [PATCH] java fixes and parsing --HG-- branch : pmacs2 --- mode/java.py | 41 ++++++++++++---- parse.py | 130 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 134 insertions(+), 37 deletions(-) diff --git a/mode/java.py b/mode/java.py index 6a79828..a1b71cd 100644 --- a/mode/java.py +++ b/mode/java.py @@ -3,6 +3,7 @@ import context from lex import Grammar, PatternRule, RegionRule from mode.python import StringGrammar2 from mode.c import CTabber2 +from parse import Any, And, Or, Optional, Name, Match, Matchs class CommentGrammar(Grammar): rules = [ @@ -60,6 +61,23 @@ class JavaTabber2(tab.StackTabber2): 'comment.data', 'comment.null', 'comment.end') class JavaContext(context.Context): + class_match = And(Optional(Name('spaces')), + Matchs('keyword', ('public', 'protected', 'private')), + Name('spaces'), + Match('keyword', 'class'), + Name('spaces'), + Name('identifier')) + class_offset = 1 + method_match = And(Optional(Name('spaces')), + Matchs('keyword', ('public', 'protected', 'private')), + Name('spaces'), + Optional(And(Match('keyword', 'static'), Name('spaces'))), + Any(), + Name('spaces'), + Name('identifier'), + Optional(Name('spaces')), + Match('delimiter', '(')) + method_offset = 2 def _regen_stack(self, y): if y > 0 and self.namelines[y - 1][1]: return list(self.namelines[y - 1][1]) @@ -78,24 +96,29 @@ class JavaContext(context.Context): g = highlights.tokens[i] gl = len(g) - if gl > 2 and g[0].match('keyword', 'class'): - curr = g[2].string - elif gl > 4 and g[2].match('keyword', 'class'): - curr = g[4].string + result = self.class_match.match(g) + if result: + n = result[0] - self.class_offset + curr = g[n].string + + result = self.method_match.match(g) + if result: + n = result[0] - self.method_offset + curr = g[n].string if curr is not None and curr not in self.names: self.names[curr] = i - if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen: - y2 += 1 - for t in g: if t.match('delimiter', '{'): - stack.append(t.string) + stack.append(curr) elif t.match('delimiter', '}'): - #assert stack, "uh oh" if stack: stack.pop(-1) + if stack: + curr = stack[-1] + else: + curr = None if curr: self.namelines[i] = (curr, tuple(stack)) diff --git a/parse.py b/parse.py index 0c57a6e..091d447 100644 --- a/parse.py +++ b/parse.py @@ -1,23 +1,80 @@ +import re import lex +MAX_MAX = 1024 + class Rule(object): def __init__(self, *rules): self.rules = rules def match(self, tokens): + if not tokens: + return [] + return self._match(tokens) + def _match(self, tokens): raise Exception("unimplemented") +class Any(Rule): + def __init__(self): + pass + def _match(self, tokens): + if tokens: + return [1] + else: + return [] + +class Name(Rule): + def __init__(self, name): + self.name = name + def _match(self, tokens): + if tokens[0].name == self.name: + return [1] + else: + return [] +class Names(Rule): + def __init__(self, names): + self.names = names + def _match(self, tokens): + if token.name in self.names: + return [1] + else: + return [] + +class String(Rule): + def __init__(self, s): + self.string = s + def _match(self, tokens): + if token.string == self.string: + return [1] + else: + return [] +class Strings(Rule): + def __init__(self, ss): + self.strings = ss + def _match(self, tokens): + if token.string in self.strings: + return [1] + else: + return [] +class Stringre(Rule): + def __init__(self, r): + self.regex = re.compile(r) + def _match(self, tokens): + if self.regex.match(token.string): + return [1] + else: + return [] + class Match(Rule): method = lex.Token.match def __init__(self, *args): self.args = args def match(self, tokens): if not tokens: - return False - elif method(tokens[0], *self.args): - tokens.pop(0) - return True + return [] + elif self.method(tokens[0], *self.args): + return [1] else: - return False + return [] class Matchs(Match): method = lex.Token.matchs class Matchp(Match): @@ -32,16 +89,20 @@ class Fqmatchp(Match): class And(Rule): def match(self, tokens): + n = 0 for r in self.rules: - if not r.match(tokens): - return False - return True + result = r.match(tokens[n:]) + if not result: + return [] + n += result[0] + return [n] class Or(Rule): def match(self, tokens): for r in self.rules: - if r.match(tokens): - return True - return False + result = r.match(tokens[n:]) + if result: + return result + return [] class Repeat(Rule): def __init__(self, rule, minimum, maximum): @@ -49,27 +110,40 @@ class Repeat(Rule): self.minimum = minimum self.maximum = maximum def match(self, tokens): + n = 0 for i in range(0, self.minimum): - if not self.rule.match(tokens): - return False - while self.rules.match(tokens): - pass - return True - self.rule.match(tokens) - return True + result = self.rule.match(tokens[n:]) + if not result: + return [] + n += result[0] + for i in range(self.minimum, self.maximum): + result = self.rule.match(tokens[n:]) + if not result: + return [n] + n += result[0] + return [n] -class Star(Rule): +class Optional(Repeat): def __init__(self, rule): - self.rule = rule - def match(self, tokens): - if not self.rule.match(tokens): - return False - while self.rules.match(tokens): - pass - return True + self.rule = rule + self.minimum = 0 + self.maximum = 1 +class Star(Repeat): + def __init__(self, rule): + self.rule = rule + self.minimum = 0 + self.maximum = MAX_MAX +class Plus(Repeat): + def __init__(self, rule): + self.rule = rule + self.minimum = 1 + self.maximum = MAX_MAX + class End(Rule): def __init__(self): pass def match(self, tokens): - return not tokens - + if tokens: + return [] + else: + return [0]