Hide keyboard shortcuts

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.""" 

13 

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 ) 

22 

23 #@+others 

24 #@+node:ekr.20161126171035.4: *3* pascal_i.clean_headline 

25 pascal_clean_pattern = re.compile(r'^(function|procedure)\s+([\w_.]+)') 

26 

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() 

31 

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() 

38 

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 

49 

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 

56 

57 def add_key(d, key, data): 

58 aList = d.get(key,[]) 

59 aList.append(data) 

60 d[key] = aList 

61 

62 d: Dict[str, List[Any]] 

63 

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 ) 

97 

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.""" 

112 

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 = '' 

120 

121 def __repr__(self): 

122 """Pascal_ScanState.__repr__""" 

123 return "Pascal_ScanState context: %r" % (self.context) 

124 

125 __str__ = __repr__ 

126 

127 #@+others 

128 #@+node:ekr.20161126171035.7: *3* pascal_state.level 

129 def level(self): 

130 """Pascal_ScanState.level.""" 

131 return 0 # Not used 

132 

133 #@+node:ekr.20161126171035.8: *3* pascal_state.update 

134 def update(self, data): 

135 """ 

136 Pascal_ScanState.update 

137 

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 

153 

154 

155#@-leo