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.20161027100313.1: * @file ../plugins/importers/perl.py 

3"""The @auto importer for Perl.""" 

4import re 

5from typing import Any, Dict, List 

6from leo.plugins.importers import linescanner 

7Importer = linescanner.Importer 

8#@+others 

9#@+node:ekr.20161027094537.13: ** class Perl_Importer 

10class Perl_Importer(Importer): 

11 """A scanner for the perl language.""" 

12 

13 def __init__(self, importCommands, **kwargs): 

14 """The ctor for the Perl_ImportController class.""" 

15 super().__init__( 

16 importCommands, 

17 language='perl', 

18 state_class=Perl_ScanState, 

19 ) 

20 

21 #@+others 

22 #@+node:ekr.20161027183713.1: *3* perl_i.clean_headline 

23 def clean_headline(self, s, p=None): 

24 """Return a cleaned up headline s.""" 

25 m = re.match(r'sub\s+(\w+)', s) 

26 return 'sub ' + m.group(1) if m else s 

27 #@+node:ekr.20161027194956.1: *3* perl_i.clean_nodes 

28 def clean_nodes(self, parent): 

29 """Clean nodes as part of the perl post pass.""" 

30 # Move trailing comments into following def nodes. 

31 for p in parent.subtree(): 

32 next = p.threadNext() 

33 # This can be a node *outside* parent's tree! 

34 if next and self.has_lines(next): 

35 lines = self.get_lines(p) 

36 if lines: 

37 tail = [] 

38 while lines and lines[-1].strip().startswith('#'): 

39 tail.append(lines.pop()) 

40 if tail: 

41 self.set_lines(p, lines) 

42 self.prepend_lines(next, reversed(tail)) 

43 

44 #@+node:ekr.20161129024520.1: *3* perl_i.get_new_dict (test) 

45 #@@nobeautify 

46 

47 def get_new_dict(self, context): 

48 """ 

49 Return a *general* state dictionary for the given context. 

50 Subclasses may override... 

51 """ 

52 comment, block1, block2 = self.single_comment, self.block1, self.block2 

53 

54 def add_key(d, key, data): 

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

56 aList.append(data) 

57 d[key] = aList 

58 

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

60 

61 if context: 

62 d = { 

63 # key kind pattern ends? 

64 '\\': [('len+1', '\\', None),], 

65 '=': [('len', '=cut', context == '='),], 

66 '/': [('len', '/', context == '/'),], 

67 '"': [('len', '"', context == '"'),], 

68 "'": [('len', "'", context == "'"),], 

69 } 

70 if block1 and block2: 

71 add_key(d, block2[0], ('len', block1, True)) 

72 else: 

73 # Not in any context. 

74 d = { 

75 # key kind pattern new-ctx deltas 

76 '\\':[('len+1', '\\', context, None),], 

77 '#': [('all', '#', context, None),], 

78 '=': [('len', '=', context, None),], 

79 't': [('len', 'tr///', '/', None),], 

80 's': [('len', 's///', '/', None),], 

81 'm': [('len', 'm//', '/', None),], 

82 '/': [('len', '/', '/', None),], 

83 '"': [('len', '"', '"', None),], 

84 "'": [('len', "'", "'", None),], 

85 '{': [('len', '{', context, (1,0,0)),], 

86 '}': [('len', '}', context, (-1,0,0)),], 

87 '(': [('len', '(', context, (0,1,0)),], 

88 ')': [('len', ')', context, (0,-1,0)),], 

89 '[': [('len', '[', context, (0,0,1)),], 

90 ']': [('len', ']', context, (0,0,-1)),], 

91 } 

92 if comment: 

93 add_key(d, comment[0], ('all', comment, '', None)) 

94 if block1 and block2: 

95 add_key(d, block1[0], ('len', block1, block1, None)) 

96 return d 

97 #@+node:ekr.20161027094537.12: *3* perl_i.skip_regex 

98 def skip_regex(self, s, i, pattern): 

99 """look ahead for a regex /""" 

100 assert self.match(s, i, pattern) 

101 i += len(pattern) 

102 while i < len(s) and s[i] in ' \t': 

103 i += 1 

104 if i < len(s) and s[i] == '/': 

105 i += 1 

106 while i < len(s): 

107 progress = i 

108 ch = s[i] 

109 if ch == '\\': 

110 i += 2 

111 elif ch == '/': 

112 i += 1 

113 break 

114 else: 

115 i += 1 

116 assert progress < i 

117 return i 

118 #@-others 

119#@+node:ekr.20161105095705.1: ** class Perl_ScanState 

120class Perl_ScanState: 

121 """A class representing the state of the perl line-oriented scan.""" 

122 

123 def __init__(self, d=None): 

124 """Perl_ScanState ctor.""" 

125 if d: 

126 prev = d.get('prev') 

127 self.context = prev.context 

128 self.curlies = prev.curlies 

129 self.parens = prev.parens 

130 else: 

131 self.context = '' 

132 self.curlies = self.parens = 0 

133 

134 def __repr__(self): 

135 """Perl_ScanState.__repr__""" 

136 return 'Perl_ScanState context: %r curlies: %s parens: %s' % ( 

137 self.context, self.curlies, self.parens) 

138 

139 __str__ = __repr__ 

140 

141 #@+others 

142 #@+node:ekr.20161119115617.1: *3* perl_state.level 

143 def level(self): 

144 """Perl_ScanState.level.""" 

145 return (self.curlies, self.parens) 

146 #@+node:ekr.20161119050522.1: *3* perl_state.update 

147 def update(self, data): 

148 """ 

149 Update the state using the 6-tuple returned by i.scan_line. 

150 Return i = data[1] 

151 """ 

152 context, i, delta_c, delta_p, delta_s, bs_nl = data 

153 # self.bs_nl = bs_nl 

154 self.context = context 

155 self.curlies += delta_c 

156 self.parens += delta_p 

157 # self.squares += delta_s 

158 return i 

159 

160 #@-others 

161 

162#@-others 

163importer_dict = { 

164 'func': Perl_Importer.do_import(), 

165 'extensions': ['.pl',], 

166} 

167#@@language python 

168#@@tabwidth -4 

169#@-leo