Coverage for C:\leo.repo\leo-editor\leo\plugins\importers\pascal.py : 89%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#@+leo-ver=5-thin
2#@+node:ekr.20140723122936.18147: * @file ../plugins/importers/pascal.py
3"""The @auto importer for the pascal language."""
4import re
5from typing import Any, Dict, List
6from leo.core import leoGlobals as g
7from leo.plugins.importers import linescanner
8Importer = linescanner.Importer
9#@+others
10#@+node:ekr.20161126171035.2: ** class Pascal_Importer
11class Pascal_Importer(Importer):
12 """The importer for the pascal lanuage."""
14 def __init__(self, importCommands, **kwargs):
15 """Pascal_Importer.__init__"""
16 super().__init__(
17 importCommands,
18 language='pascal',
19 state_class=Pascal_ScanState,
20 strict=False,
21 )
23 #@+others
24 #@+node:ekr.20161126171035.4: *3* pascal_i.clean_headline
25 pascal_clean_pattern = re.compile(r'^(function|procedure)\s+([\w_.]+)')
27 def clean_headline(self, s, p=None):
28 """Return a cleaned up headline s."""
29 m = self.pascal_clean_pattern.match(s)
30 return '%s %s' % (m.group(1), m.group(2)) if m else s.strip()
32 #@+node:ekr.20161127115120.1: *3* pascal_i.cut_stack
33 def cut_stack(self, new_state, stack):
34 """Cut back the stack until stack[-1] matches new_state."""
35 # This underflow could happen as the result of extra 'end' statement in user code.
36 if len(stack) > 1:
37 stack.pop()
39 #@+node:ekr.20161127104208.1: *3* pascal_i.ends_block
40 def ends_block(self, line, new_state, prev_state, stack):
41 """True if line ends a function or procedure."""
42 if prev_state.context:
43 return False
44 ls = line.lstrip()
45 val = g.match_word(ls, 0, 'end')
46 return val
47 #@+node:ekr.20161129024448.1: *3* pascal_i.get_new_dict
48 #@@nobeautify
50 def get_new_dict(self, context):
51 """
52 Return a *general* state dictionary for the given context.
53 Subclasses may override...
54 """
55 comment, block1, block2 = self.single_comment, self.block1, self.block2
57 def add_key(d, key, data):
58 aList = d.get(key,[])
59 aList.append(data)
60 d[key] = aList
62 d: Dict[str, List[Any]]
64 if context:
65 d = {
66 # key kind pattern ends?
67 '\\': [('len+1', '\\', None),],
68 '"': [('len', '"', context == '"'),],
69 "'": [('len', "'", context == "'"),],
70 }
71 if block1 and block2:
72 add_key(d, block2[0], ('len', block1, True))
73 else:
74 # Not in any context.
75 d = {
76 # key kind pattern new-ctx deltas
77 '\\':[('len+1', '\\', context, None),],
78 '"': [('len', '"', '"', None),],
79 "'": [('len', "'", "'", None),],
80 '{': [('len', '{', context, (1,0,0)),],
81 '}': [('len', '}', context, (-1,0,0)),],
82 '(': [('len', '(', context, (0,1,0)),],
83 ')': [('len', ')', context, (0,-1,0)),],
84 '[': [('len', '[', context, (0,0,1)),],
85 ']': [('len', ']', context, (0,0,-1)),],
86 }
87 if comment:
88 add_key(d, comment[0], ('all', comment, '', None))
89 if block1 and block2:
90 add_key(d, block1[0], ('len', block1, block1, None))
91 return d
92 #@+node:ekr.20161126182009.1: *3* pascal_i.starts_block
93 pascal_pattern_table = (
94 re.compile(r'^(function|procedure)\s+([\w_.]+)\s*\((.*)\)\s*\;\s*\n'),
95 re.compile(r'^(interface)\s*\n')
96 )
98 def starts_block(self, i, lines, new_state, prev_state):
99 """True if the line starts a block."""
100 if prev_state.context:
101 return False
102 line = lines[i]
103 for pattern in self.pascal_pattern_table:
104 m = pattern.match(line)
105 if m:
106 return True
107 return False
108 #@-others
109#@+node:ekr.20161126171035.6: ** class class Pascal_ScanState
110class Pascal_ScanState:
111 """A class representing the state of the pascal line-oriented scan."""
113 def __init__(self, d=None):
114 """Pascal_ScanState.__init__"""
115 if d:
116 prev = d.get('prev')
117 self.context = prev.context
118 else:
119 self.context = ''
121 def __repr__(self):
122 """Pascal_ScanState.__repr__"""
123 return "Pascal_ScanState context: %r" % (self.context)
125 __str__ = __repr__
127 #@+others
128 #@+node:ekr.20161126171035.7: *3* pascal_state.level
129 def level(self):
130 """Pascal_ScanState.level."""
131 return 0 # Not used
133 #@+node:ekr.20161126171035.8: *3* pascal_state.update
134 def update(self, data):
135 """
136 Pascal_ScanState.update
138 Update the state using the 6-tuple returned by i.scan_line.
139 Return i = data[1]
140 """
141 context, i, delta_c, delta_p, delta_s, bs_nl = data
142 # All ScanState classes must have a context ivar.
143 self.context = context
144 return i
145 #@-others
146#@-others
147importer_dict = {
148 'func': Pascal_Importer.do_import(),
149 'extensions': ['.pas'],
150}
151#@@language python
152#@@tabwidth -4
155#@-leo