3 The syntax of a source list file is a very small subset of GNU Make. These
8 non-nested variable expansion
11 The goal is to allow Makefile's and SConscript's to share source listing.
14 class SourceListParser(object):
18 def _reset(self
, filename
=None):
19 self
.filename
= filename
23 self
.symbol_table
= {}
25 def _error(self
, msg
):
26 raise RuntimeError('%s:%d: %s' % (self
.filename
, self
.line_no
, msg
))
28 def _next_dereference(self
, val
, cur
):
29 """Locate the next $(...) in value."""
30 deref_pos
= val
.find('$', cur
)
33 elif val
[deref_pos
+ 1] != '(':
34 self
._error
('non-variable dereference')
36 deref_end
= val
.find(')', deref_pos
+ 2)
38 self
._error
('unterminated variable dereference')
40 return (deref_pos
, deref_end
+ 1)
42 def _expand_value(self
, val
):
43 """Perform variable expansion."""
47 deref_pos
, deref_end
= self
._next
_dereference
(val
, cur
)
52 sym
= val
[(deref_pos
+ 2):(deref_end
- 1)]
53 expanded
+= val
[cur
:deref_pos
] + self
.symbol_table
[sym
]
58 def _parse_definition(self
, line
):
59 """Parse a variable definition line."""
60 op_pos
= line
.find('=')
63 self
._error
('not a variable definition')
65 if op_pos
> 0 and line
[op_pos
- 1] in [':', '+']:
68 self
._error
('only := and += are supported')
70 # set op, sym, and val
71 op
= line
[op_pos
:op_end
]
72 sym
= line
[:op_pos
].strip()
73 val
= self
._expand
_value
(line
[op_end
:].lstrip())
76 self
.symbol_table
[sym
] = val
78 self
.symbol_table
[sym
] += ' ' + val
80 def _parse_line(self
, line
):
81 """Parse a source list line."""
83 if line
and line
[-1] == '\\':
84 # spaces around "\\\n" are replaced by a single space
86 self
.line_cont
+= line
[:-1].strip() + ' '
88 self
.line_cont
= line
[:-1].rstrip() + ' '
91 # combine with previous lines
93 line
= self
.line_cont
+ line
.lstrip()
97 begins_with_tab
= (line
[0] == '\t')
102 self
._error
('recipe line not supported')
104 self
._parse
_definition
(line
)
108 def parse(self
, filename
):
109 """Parse a source list file."""
110 if self
.filename
!= filename
:
112 lines
= fp
.read().splitlines()
116 self
._reset
(filename
)
118 self
.line_no
+= self
._parse
_line
(line
)
123 return self
.symbol_table