yacc support; brm in-progress

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-10-28 19:48:44 +00:00
parent 6a3002fa6c
commit 79f120d089
7 changed files with 383 additions and 5 deletions

View File

@ -134,7 +134,7 @@ class Application(object):
'latex', 'insertmini', 'conf', 'haskell', 'erlang', 'latex', 'insertmini', 'conf', 'haskell', 'erlang',
'iperl', 'iperlmini', 'ipython', 'ipythonmini', 'awk', 'iperl', 'iperlmini', 'ipython', 'ipythonmini', 'awk',
'bds', #XYZ 'bds', #XYZ
'shell', 'shellmini', 'fstab' 'shell', 'shellmini', 'fstab', 'yacc',
) )
for name in names: for name in names:
exec("import mode.%s; mode.%s.install(self)" % (name, name)) exec("import mode.%s; mode.%s.install(self)" % (name, name))

View File

@ -0,0 +1,127 @@
%{
#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
extern char* yytext;
/*extern char * yylval;*/
/*
Parser for linker map files.
*/
void print_node(xmlNodePtr node) {
xmlDocPtr doc = NULL;
doc = xmlNewDoc("1.0");
xmlDocSetRootElement(doc, node);
xmlSaveFile("ldmap.out.xml", doc);
}
%}
%union {
char* strn;
xmlNodePtr node;
};
%token SYMBOL LPAREN RPAREN HEX;
%token OBJ_FILE ARCH_FILE DYN_FILE;
%token HEADER ARCH_HEADER
%type<strn> thingie file objfile archfile dynfile sym hexval head
%type<node> arch_section arch_list arch_entry
%%
thingie: thingie file { printf("File: %s\n", $2); $$ = $2;}
| thingie sym { printf("Sym: %s\n", $2); $$ = $2;}
| thingie hexval { printf("Hex: %s\n", $2); $$ = $2;}
| thingie head { printf("Header: %s\n", $2); $$ = $2;}
| thingie arch_section { printf("Arch section:\n"); print_node($2); $$ = ""}
| thingie '(' { $$= "";}
| thingie ')' { $$= "";}
| thingie '*' { $$ = ""; }
| thingie ',' { $$ = ""; }
| thingie '=' { $$ = ""; }
| thingie '+' { $$ = ""; }
| thingie '&' { $$ = ""; }
| thingie '!' { $$ = ""; }
| thingie '?' { $$ = ""; }
| thingie ':' { $$ = ""; }
| { $$ = "end" }
;
arch_section: ARCH_HEADER arch_list
{
$$ = xmlNewNode(NULL, "arch-section");
xmlAddChild($$, $2);
}
arch_list:
arch_list arch_entry arch_entry '(' sym ')'
{
xmlNodePtr tmp;
tmp = xmlNewNode(NULL, "added");
/*$$ = $6; xmlAddChild($6, $1); */
xmlAddChild(tmp, $2);
xmlAddChild(tmp, $3);
xmlNewProp(tmp, "symbol", $5);
xmlAddChild($1, tmp);
$$ = $1;
}
| arch_list arch_entry file '(' sym ')'
{
xmlNodePtr tmp;
tmp = xmlNewNode(NULL, "added");
xmlAddChild(tmp, $2);
xmlNewChild(tmp, NULL, "file", $3);
xmlNewProp(tmp, "symbol", $5);
xmlAddChild($1, tmp);
$$ = $1;
}
| {$$ = xmlNewNode(NULL, "arch-list")}
arch_entry: archfile '(' file ')'
{
$$= xmlNewNode(NULL, "archive");
xmlNodeAddContent($$, $1);
xmlNewProp($$, "member", $3);
}
file: objfile { $$ = $1; }
| archfile { $$ = $1; }
| dynfile { $$ = $1; };
dynfile: DYN_FILE { $$ = strdup(yytext); };
objfile: OBJ_FILE { $$ = strdup(yytext); };
archfile: ARCH_FILE { $$ = strdup(yytext); };
sym: SYMBOL { $$ = strdup(yytext); };
hexval: HEX { $$ = strdup(yytext); };
head: HEADER { $$ = strdup(yytext); };
%%
main() {
/* do {*/
yyparse();
/* } while (!feof(yyin) );*/
}
yyerror( char * s) {
fprintf(stderr, "yyerror is: %s ; %s\n", s, yytext);
}

156
mode/brm.py Normal file
View File

@ -0,0 +1,156 @@
import re, sets, string
import color, method, minibuffer, mode, searchutil
from point import Point
subgroup_re = re.compile(r'((?:\\\\)*)\\(0|[1-9][0-9]*)')
class ReplaceOne(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
_replace(m)
_find_next(m, False)
_finish(m, w)
class ReplaceDone(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
_replace(m)
_end(w)
w.set_error("Replace done")
class SkipReplace(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
_find_next(m, True)
_finish(m, w)
class ReplaceAll(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
while m.p1 is not None:
_replace(m)
_find_next(m, False)
_end(w)
w.set_error("Replace ended")
class BrmCancel(method.Method):
def execute(self, w, **vargs):
_end(w)
w.set_error("BRM cancelled")
def _find_next(m, move=False):
s = m.before
w = m.old_window
c = w.logical_cursor()
try:
if m.is_literal:
r = re.compile(searchutil.escape_literal(s))
else:
r = re.compile(s)
except:
(m.p1, m.p2) = (None, None)
return False
if move:
newc = searchutil.find_next(r, w, False, start=c.add(1, 0))
else:
newc = searchutil.find_next(r, w, False, start=c.add(0, 0))
if newc:
(m.p1, m.p2, m.match) = newc
return True
else:
(m.p1, m.p2, m.match) = (None, None, None)
return False
def _get_before(m):
if m.match is None:
return m.before
else:
return m.match.group(0)
def _get_after(m):
if m.after is None:
return None
elif m.match is None:
return m.after
def _repl(match):
(pre, num) = (match.group(1), int(match.group(2)))
if num == 0 or m.match.lastindex and num <= m.match.lastindex:
return pre + m.match.group(num)
else:
return match.group(0)
return subgroup_re.sub(_repl, m.after)
def _set_prompt(m):
w = m.old_window
if m.p1 is None:
#w.application.mini_prompt = '%r was not found' % m.before
w.application.mini_prompt = '[%r] %r was not found' % (m.p1, m.before)
return
(x, y) = m.p1.xy()
count = 0
while y < len(w.buffer.lines):
count += w.buffer.lines[y][x:].count(m.before)
y += 1
x = 0
after = _get_after(m)
before = _get_before(m)
if count > 1:
p = 'Replace %r with %r [ynadq] (%d occurances)?' % (before, after, count)
elif count == 1:
p = 'Replace %r with %r [ynadq] (1 occurance)?' % (before, after)
elif count == 0:
p = 'Replace %r with %r [ynadq] (0 occurances)?' % (before, after)
#raise Exception("this can't happen")
else:
raise Exception("this REALLY can't happen")
w.application.mini_prompt = p
def _replace(m):
m.old_window.buffer.delete(m.p1, m.p2)
if m.after:
after = _get_after(m)
m.old_window.buffer.insert_string(m.p1, after)
def _finish(m, w):
if m.p1 is None:
_end(w)
w.set_error("Replace ended")
else:
_set_prompt(m)
def _end(w):
w.application.close_mini_buffer()
w.application.clear_highlighted_ranges('search')
w.buffer.method.old_cursor = None
w.buffer.method.old_window = None
assert not w.application.mini_active
class Brm(mode.Fundamental):
modename = 'Bicycle-Repairman'
actions = [ReplaceAll, ReplaceDone, ReplaceOne, SkipReplace, BrmCancel]
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.actions = {}
self.bindings = {}
#self.add_bindings('replace-all', ('a', '!',))
#self.add_bindings('replace-done', ('d',))
#self.add_bindings('replace-one', ('y', 'SPACE',))
#self.add_bindings('skip-replace', ('n', 'DELETE',))
self.add_bindings('brm-cancel', ('q', 'RETURN', 'C-]', 'C-n', 'C-p', 'C-a', 'C-e', 'C-f', 'C-b', 'C-g'))
m = w.buffer.method
found = _find_next(m, False)
if not found:
w.set_error('%r was not found' % m.before)
raise minibuffer.MiniBufferError
_set_prompt(m)
install = Brm.install

View File

@ -63,7 +63,8 @@ class CGrammar(Grammar):
PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'"), PatternRule(r'char', r"'.'|'\\.'|'\\[0-7]{3}'"),
PatternGroupRule(r'includegrp', r'macro.start', r'# *include', r'spaces', PatternGroupRule(r'includegrp', r'macro.start', r'# *include', r'spaces',
r' +', r'header', r'< *[-A-Za-z/0-9_.]+ *>|" *[-A-Za-z/0-9_.]+ *"'), r' +', r'header', r'< *[-A-Za-z/0-9_.]+ *>|" *[-A-Za-z/0-9_.]+ *"',
'macro.end', r'\n$'),
PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"), PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"),

View File

@ -1,8 +1,14 @@
import commands, os.path, sets, string, sys, traceback import commands, os.path, sets, string, sys, traceback
import color, completer, context, default, mode, method, regex, tab import color, completer, context, default, mode, method, regex, tab, method.introspect
from point import Point from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
try:
import bike
has_bike = True
except ImportError:
has_bike = False
class StringGrammar1(Grammar): class StringGrammar1(Grammar):
rules = [ rules = [
PatternRule(r'octal', r'\\[0-7]{3}'), PatternRule(r'octal', r'\\[0-7]{3}'),
@ -365,6 +371,33 @@ class PythonListNames(method.Method):
output = '\n'.join(sorted(names)) + "\n" output = '\n'.join(sorted(names)) + "\n"
w.application.data_buffer("*Python-List-Names*", output, switch_to=True) w.application.data_buffer("*Python-List-Names*", output, switch_to=True)
class PythonBrmFindReferences(method.Method):
def _execute(self, w, **vargs):
if w.mode.brm is None:
w.set_error('bicycle repairman not installed')
return
path = w.buffer.path
cursor = w.logical_cursor()
y, x = cursor.yx()
refs = w.mode.brm.findReferencesByCoordinates(path, y, x)
lines = []
n = 0
for r in refs:
f, n, c = r.filename, r.lineno, r.confidence
s = '%s:%d: %3d%% confidence' % (f, n, c)
lines.append(s)
n += 1
if n == 0:
w.set_error('no references found')
return
data = '\n'.join(lines)
w.application.data_buffer("*References*", data, switch_to=True)
if n == 1:
w.set_error('1 reference found')
else:
w.set_error('%d references found' % n)
class PythonNameCompleter(completer.Completer): class PythonNameCompleter(completer.Completer):
def _get_dict(self, w): def _get_dict(self, w):
return w.buffer.method.old_window.mode.context.get_names() return w.buffer.method.old_window.mode.context.get_names()
@ -502,7 +535,7 @@ class Python(mode.Fundamental):
} }
actions = [PythonInitNames, PythonListNames, PythonGotoName, actions = [PythonInitNames, PythonListNames, PythonGotoName,
PythonGotoFunction, PythonGotoClass, PythonCheckSyntax, PythonGotoFunction, PythonGotoClass, PythonCheckSyntax,
PythonDictCleanup, PythonSemanticComplete, PythonDictCleanup, PythonSemanticComplete, PythonBrmFindReferences,
PythonInsertTripleSquotes, PythonInsertTripleDquotes] PythonInsertTripleSquotes, PythonInsertTripleDquotes]
completers = { completers = {
"pythonname": PythonNameCompleter(None), "pythonname": PythonNameCompleter(None),
@ -533,4 +566,10 @@ class Python(mode.Fundamental):
self.add_bindings('python-semantic-complete', ('C-c TAB',)) self.add_bindings('python-semantic-complete', ('C-c TAB',))
self.context = PythonContext(self) self.context = PythonContext(self)
# bicycle repairman!
if has_bike:
self.brm = bike.init()
else:
self.brm = None
install = Python.install install = Python.install

51
mode/yacc.py Normal file
View File

@ -0,0 +1,51 @@
import color, mode, tab
from lex import Grammar, PatternRule, RegionRule
from mode.c import C, CGrammar, CTabber2
_rules = list(CGrammar.rules)
_rules.insert(0, PatternRule(r"yacc_directive", r"^%[a-zA-Z_]+"))
_rules.insert(1, PatternRule(r"yacc_section", r"%%"))
_rules.insert(2, PatternRule(r"yacc_delimiter", r"%{|%}"))
_rules.insert(3, PatternRule(r"yacc_production", r"^[a-z_]+:"))
_rules.insert(4, PatternRule(r"yacc_var", r"\$[0-9\$]"))
_rules.insert(5, PatternRule(r"yacc_empty", r"^ +\n$"))
class TrueDict(dict):
def __contains__(self, k): return True
def __getitem__(self, k): return True
def __setitem__(self, k): pass
def __delitem__(self, k): raise Exception, 'not possible'
def __len__(self): return 1
def __repr__(self): return '<TrueDict()>'
def get(self, k): return True
class YaccGrammar(CGrammar):
rules = _rules
class YaccTabber(CTabber2):
open_tokens = {'delimiter': {'{': '}', '(': ')', '[': ']'},
'yacc_delimiter': {'%{': '%}'}}
close_tokens = {'delimiter': {'}': '{', ')': '(', ']': '['},
'yacc_delimiter': {'%}': '%{'}}
control_tokens = {'yacc_production': TrueDict()}
scope_tokens = {}
end_at_eof = False
end_at_tokens = {'yacc_empty': TrueDict()}
nocontinue_tokens = {}
start_free_tokens = {'string.start': 'string.end'}
end_free_tokens = {'string.end': 'string.start'}
class Yacc(mode.Fundamental):
modename = 'yacc'
extensions = ['.y']
grammar = YaccGrammar
tabbercls = YaccTabber
colors = {
'yacc_directive': ('yellow', 'default', 'bold'),
'yacc_section': ('yellow', 'default', 'bold'),
'yacc_delimiter': ('yellow', 'default', 'bold'),
'yacc_production': ('yellow', 'default', 'bold'),
'yacc_var': ('yellow', 'default', 'bold'),
}
install = Yacc.install

6
tab.py
View File

@ -296,7 +296,7 @@ class StackTabber2(Tabber):
def _match(self, *names): def _match(self, *names):
return self.stack and self.stack[-1].name in names return self.stack and self.stack[-1].name in names
def _nomatch(self, *names): def _nomatch(self, *names):
return self.stack and self.stack[-1].name not in names return not self.stack or self.stack[-1].name not in names
def _pop(self, *names): def _pop(self, *names):
if self._match(*names): if self._match(*names):
self.stack.pop() self.stack.pop()
@ -408,6 +408,10 @@ class StackTabber2(Tabber):
self._pop('macro') self._pop('macro')
return return
#d = self.end_at_tokens.get(name, {})
#if d:
# raise Exception, (name, s, d, d.get(s), d[s])
# remove implicit continuation # remove implicit continuation
if self.end_at_eof and i + start == end: if self.end_at_eof and i + start == end:
self._pop_while('continue', 'control') self._pop_while('continue', 'control')