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):
16 self
.symbol_table
= {}
19 def _reset(self
, filename
=None):
20 self
.filename
= filename
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')
66 if line
[op_pos
- 1] in [':', '+', '?']:
69 self
._error
('only =, :=, and += are supported')
71 # set op, sym, and val
72 op
= line
[op_pos
:op_end
]
73 sym
= line
[:op_pos
].strip()
74 val
= self
._expand
_value
(line
[op_end
:].lstrip())
77 self
.symbol_table
[sym
] = val
79 self
.symbol_table
[sym
] += ' ' + val
81 if sym
not in self
.symbol_table
:
82 self
.symbol_table
[sym
] = val
84 def _parse_line(self
, line
):
85 """Parse a source list line."""
87 if line
and line
[-1] == '\\':
88 # spaces around "\\\n" are replaced by a single space
90 self
.line_cont
+= line
[:-1].strip() + ' '
92 self
.line_cont
= line
[:-1].rstrip() + ' '
95 # combine with previous lines
97 line
= self
.line_cont
+ line
.lstrip()
101 begins_with_tab
= (line
[0] == '\t')
106 self
._error
('recipe line not supported')
108 self
._parse
_definition
(line
)
112 def parse(self
, filename
):
113 """Parse a source list file."""
114 if self
.filename
!= filename
:
116 lines
= fp
.read().splitlines()
120 self
._reset
(filename
)
122 self
.line_no
+= self
._parse
_line
(line
)
127 return self
.symbol_table
129 def add_symbol(self
, name
, value
):
130 self
.symbol_table
[name
] = value