]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/parser_tools.py
Avoid endless loops, e.g when an end_deeper is missing
[lyx.git] / lib / lyx2lyx / parser_tools.py
1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2002-2004 Dekel Tsur <dekel@lyx.org>, José Matos <jamatos@lyx.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 " This modules offer several free functions to help parse lines."
20
21 # Utilities for one line
22 def check_token(line, token):
23     """ check_token(line, token) -> bool
24
25     Return True if token is present in line and is the first element
26     else returns False."""
27
28     return line[:len(token)] == token
29
30
31 def is_nonempty_line(line):
32     """ is_nonempty_line(line) -> bool
33
34     Return False if line is either empty or it has only whitespaces,
35     else return True."""
36     return line != " "*len(line)
37
38
39 # Utilities for a list of lines
40 def find_token(lines, token, start, end = 0, exact = False):
41     """ find_token(lines, token, start[[, end], exact]) -> int
42
43     Return the lowest line where token is found, and is the first
44     element, in lines[start, end].
45
46     Return -1 on failure."""
47
48     if end == 0:
49         end = len(lines)
50     m = len(token)
51     for i in xrange(start, end):
52         if exact:
53             x = lines[i].split()
54             y = token.split()
55             if len(x) < len(y):
56                 continue
57             if x[:len(y)] == y:
58                 return i
59         else:
60             if lines[i][:m] == token:
61                 return i
62     return -1
63
64
65 def find_token_exact(lines, token, start, end = 0):
66     return find_token(lines, token, start, end, True)
67
68
69 def find_tokens(lines, tokens, start, end = 0, exact = False):
70     """ find_tokens(lines, tokens, start[[, end], exact]) -> int
71
72     Return the lowest line where one token in tokens is found, and is
73     the first element, in lines[start, end].
74
75     Return -1 on failure."""
76     if end == 0:
77         end = len(lines)
78
79     for i in xrange(start, end):
80         for token in tokens:
81             if exact:
82                 x = lines[i].split()
83                 y = token.split()
84                 if len(x) < len(y):
85                     continue
86                 if x[:len(y)] == y:
87                     return i            
88             else:
89                 if lines[i][:len(token)] == token:
90                     return i
91     return -1
92
93
94 def find_tokens_exact(lines, tokens, start, end = 0):
95     return find_tokens(lines, tokens, start, end, True)
96
97
98 def find_re(lines, rexp, start, end = 0):
99     """ find_token_re(lines, rexp, start[, end]) -> int
100
101     Return the lowest line where rexp, a regular expression, is found
102     in lines[start, end].
103
104     Return -1 on failure."""
105
106     if end == 0:
107         end = len(lines)
108     for i in xrange(start, end):
109         if rexp.match(lines[i]):
110                 return i
111     return -1
112
113
114 def find_token_backwards(lines, token, start):
115     """ find_token_backwards(lines, token, start) -> int
116
117     Return the highest line where token is found, and is the first
118     element, in lines[start, end].
119
120     Return -1 on failure."""
121     m = len(token)
122     for i in xrange(start, -1, -1):
123         line = lines[i]
124         if line[:m] == token:
125             return i
126     return -1
127
128
129 def find_tokens_backwards(lines, tokens, start):
130     """ find_tokens_backwards(lines, token, start) -> int
131
132     Return the highest line where token is found, and is the first
133     element, in lines[end, start].
134
135     Return -1 on failure."""
136     for i in xrange(start, -1, -1):
137         line = lines[i]
138         for token in tokens:
139             if line[:len(token)] == token:
140                 return i
141     return -1
142
143
144 def get_value(lines, token, start, end = 0, default = ""):
145     """ get_value(lines, token, start[[, end], default]) -> list of strings
146
147     Return tokens after token for the first line, in lines, where
148     token is the first element."""
149
150     i = find_token_exact(lines, token, start, end)
151     if i == -1:
152         return ""
153     if len(lines[i].split()) > 1:
154         return lines[i].split()[1]
155     else:
156         return default
157
158
159 def del_token(lines, token, start, end):
160     """ del_token(lines, token, start, end) -> int
161
162     Find the lower line in lines where token is the first element and
163     delete that line.
164
165     Returns the number of lines remaining."""
166
167     k = find_token_exact(lines, token, start, end)
168     if k == -1:
169         return end
170     else:
171         del lines[k]
172         return end - 1
173
174
175 def find_beginning_of(lines, i, start_token, end_token):
176     count = 1
177     while i > 0:
178         i = find_tokens_backwards(lines, [start_token, end_token], i-1)
179         if i == -1:
180             return -1
181         if check_token(lines[i], end_token):
182             count = count+1
183         else:
184             count = count-1
185         if count == 0:
186             return i
187     return -1
188
189
190 def find_end_of(lines, i, start_token, end_token):
191     count = 1
192     n = len(lines)
193     while i < n:
194         i = find_tokens(lines, [end_token, start_token], i+1)
195         if i == -1:
196             return -1
197         if check_token(lines[i], start_token):
198             count = count+1
199         else:
200             count = count-1
201         if count == 0:
202             return i
203     return -1
204
205
206 def find_nonempty_line(lines, start, end = 0):
207     if end == 0:
208         end = len(lines)
209     for i in xrange(start, end):
210         if is_nonempty_line(lines[i]):
211             return i
212     return -1