Skip to content

Commit a6e4377

Browse files
authored
Merge pull request #13 from stasm/spans-everywhere
Most AST nodes can now have a Span. Use FluentParser(with_spans=True) to enable this behavior. The with_annotations config option to FluentParser has been removed. The parser always produces Annotations if necessary now.
2 parents 3b30830 + feb1678 commit a6e4377

17 files changed

+669
-473
lines changed

fluent/migrate/context.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ class MergeContext(object):
4646
"""
4747

4848
def __init__(self, lang, reference_dir, localization_dir):
49-
self.fluent_parser = FluentParser(
50-
with_spans=False, with_annotations=False
51-
)
49+
self.fluent_parser = FluentParser(with_spans=False)
5250
self.fluent_serializer = FluentSerializer()
5351

5452
# An iterable of plural category names relevant to the context's

fluent/migrate/transforms.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def eval_node(subnode):
7979
return node.traverse(eval_node)
8080

8181

82-
class Transform(FTL.Node):
82+
class Transform(FTL.BaseNode):
8383
def __call__(self, ctx):
8484
raise NotImplementedError
8585

@@ -282,7 +282,7 @@ def merge_adjecent_text(acc, cur):
282282

283283
def traverse(self, fun):
284284
def visit(value):
285-
if isinstance(value, FTL.Node):
285+
if isinstance(value, FTL.BaseNode):
286286
return value.traverse(fun)
287287
if isinstance(value, list):
288288
return fun(map(visit, value))
@@ -299,7 +299,7 @@ def visit(value):
299299

300300
def to_json(self):
301301
def to_json(value):
302-
if isinstance(value, FTL.Node):
302+
if isinstance(value, FTL.BaseNode):
303303
return value.to_json()
304304
else:
305305
return value

fluent/migrate/util.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
from fluent.util import ftl
77

88

9-
fluent_parser = FluentParser(
10-
with_spans=False,
11-
with_annotations=False
12-
)
9+
fluent_parser = FluentParser(with_spans=False)
1310

1411

1512
def parse(Parser, string):

fluent/syntax/ast.py

Lines changed: 88 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55

66
def to_json(value):
7-
if isinstance(value, Node):
7+
if isinstance(value, BaseNode):
88
return value.to_json()
99
if isinstance(value, list):
1010
return list(map(to_json, value))
@@ -19,25 +19,21 @@ def from_json(value):
1919
k: from_json(v)
2020
for k, v in value.items()
2121
if k != 'type'
22-
if k != 'span'
2322
}
24-
node = cls(**args)
25-
26-
# Spans need to be added via add_span, not __init__.
27-
if 'span' in value:
28-
span = value['span']
29-
# Message and section comments don't have their own spans.
30-
if span is not None:
31-
node.add_span(span['start'], span['end'])
32-
33-
return node
23+
return cls(**args)
3424
if isinstance(value, list):
3525
return list(map(from_json, value))
3626
else:
3727
return value
3828

3929

40-
class Node(object):
30+
class BaseNode(object):
31+
"""Base class for all Fluent AST nodes.
32+
33+
All productions described in the ASDL subclass BaseNode, including Span and
34+
Annotation. Implements __str__, to_json and traverse.
35+
"""
36+
4137
def traverse(self, fun):
4238
"""Postorder-traverse this node and apply `fun` to all child nodes.
4339
@@ -49,7 +45,7 @@ def traverse(self, fun):
4945

5046
def visit(value):
5147
"""Call `fun` on `value` and its descendants."""
52-
if isinstance(value, Node):
48+
if isinstance(value, BaseNode):
5349
return value.traverse(fun)
5450
if isinstance(value, list):
5551
return fun(list(map(visit, value)))
@@ -79,162 +75,165 @@ def __str__(self):
7975
return json.dumps(self.to_json())
8076

8177

82-
class Resource(Node):
83-
def __init__(self, body=None, comment=None):
84-
super(Resource, self).__init__()
85-
self.body = body or []
86-
self.comment = comment
87-
78+
class SyntaxNode(BaseNode):
79+
"""Base class for AST nodes which can have Spans."""
8880

89-
class Entry(Node):
90-
def __init__(self, span=None, annotations=None):
91-
super(Entry, self).__init__()
81+
def __init__(self, span=None, **kwargs):
82+
super(SyntaxNode, self).__init__(**kwargs)
9283
self.span = span
93-
self.annotations = annotations or []
9484

9585
def add_span(self, start, end):
9686
self.span = Span(start, end)
9787

88+
89+
class Resource(SyntaxNode):
90+
def __init__(self, body=None, comment=None, **kwargs):
91+
super(Resource, self).__init__(**kwargs)
92+
self.body = body or []
93+
self.comment = comment
94+
95+
96+
class Entry(SyntaxNode):
97+
def __init__(self, annotations=None, **kwargs):
98+
super(Entry, self).__init__(**kwargs)
99+
self.annotations = annotations or []
100+
98101
def add_annotation(self, annot):
99102
self.annotations.append(annot)
100103

101104

102105
class Message(Entry):
103-
def __init__(
104-
self, id, value=None, attributes=None, tags=None, comment=None,
105-
span=None, annotations=None):
106-
super(Message, self).__init__(span, annotations)
106+
def __init__(self, id, value=None, attributes=None, tags=None,
107+
comment=None, **kwargs):
108+
super(Message, self).__init__(**kwargs)
107109
self.id = id
108110
self.value = value
109-
self.attributes = attributes
110-
self.tags = tags
111+
self.attributes = attributes or []
112+
self.tags = tags or []
111113
self.comment = comment
112114

113-
class Pattern(Node):
114-
def __init__(self, elements):
115-
super(Pattern, self).__init__()
115+
class Pattern(SyntaxNode):
116+
def __init__(self, elements, **kwargs):
117+
super(Pattern, self).__init__(**kwargs)
116118
self.elements = elements
117119

118-
class TextElement(Node):
119-
def __init__(self, value):
120-
super(TextElement, self).__init__()
120+
class TextElement(SyntaxNode):
121+
def __init__(self, value, **kwargs):
122+
super(TextElement, self).__init__(**kwargs)
121123
self.value = value
122124

123-
class Expression(Node):
124-
def __init__(self):
125-
super(Expression, self).__init__()
125+
class Expression(SyntaxNode):
126+
def __init__(self, **kwargs):
127+
super(Expression, self).__init__(**kwargs)
126128

127129
class StringExpression(Expression):
128-
def __init__(self, value):
129-
super(StringExpression, self).__init__()
130+
def __init__(self, value, **kwargs):
131+
super(StringExpression, self).__init__(**kwargs)
130132
self.value = value
131133

132134
class NumberExpression(Expression):
133-
def __init__(self, value):
134-
super(NumberExpression, self).__init__()
135+
def __init__(self, value, **kwargs):
136+
super(NumberExpression, self).__init__(**kwargs)
135137
self.value = value
136138

137139
class MessageReference(Expression):
138-
def __init__(self, id):
139-
super(MessageReference, self).__init__()
140+
def __init__(self, id, **kwargs):
141+
super(MessageReference, self).__init__(**kwargs)
140142
self.id = id
141143

142144
class ExternalArgument(Expression):
143-
def __init__(self, id):
144-
super(ExternalArgument, self).__init__()
145+
def __init__(self, id, **kwargs):
146+
super(ExternalArgument, self).__init__(**kwargs)
145147
self.id = id
146148

147149
class SelectExpression(Expression):
148-
def __init__(self, expression, variants):
149-
super(SelectExpression, self).__init__()
150+
def __init__(self, expression, variants, **kwargs):
151+
super(SelectExpression, self).__init__(**kwargs)
150152
self.expression = expression
151153
self.variants = variants
152154

153155
class AttributeExpression(Expression):
154-
def __init__(self, id, name):
155-
super(AttributeExpression, self).__init__()
156+
def __init__(self, id, name, **kwargs):
157+
super(AttributeExpression, self).__init__(**kwargs)
156158
self.id = id
157159
self.name = name
158160

159161
class VariantExpression(Expression):
160-
def __init__(self, id, key):
161-
super(VariantExpression, self).__init__()
162+
def __init__(self, id, key, **kwargs):
163+
super(VariantExpression, self).__init__(**kwargs)
162164
self.id = id
163165
self.key = key
164166

165167
class CallExpression(Expression):
166-
def __init__(self, callee, args):
167-
super(CallExpression, self).__init__()
168+
def __init__(self, callee, args, **kwargs):
169+
super(CallExpression, self).__init__(**kwargs)
168170
self.callee = callee
169171
self.args = args
170172

171-
class Attribute(Node):
172-
def __init__(self, id, value):
173-
super(Attribute, self).__init__()
173+
class Attribute(SyntaxNode):
174+
def __init__(self, id, value, **kwargs):
175+
super(Attribute, self).__init__(**kwargs)
174176
self.id = id
175177
self.value = value
176178

177-
class Tag(Node):
178-
def __init__(self, name):
179-
super(Tag, self).__init__()
179+
class Tag(SyntaxNode):
180+
def __init__(self, name, **kwargs):
181+
super(Tag, self).__init__(**kwargs)
180182
self.name = name
181183

182-
class Variant(Node):
183-
def __init__(self, key, value, default = False):
184-
super(Variant, self).__init__()
184+
class Variant(SyntaxNode):
185+
def __init__(self, key, value, default=False, **kwargs):
186+
super(Variant, self).__init__(**kwargs)
185187
self.key = key
186188
self.value = value
187189
self.default = default
188190

189-
class NamedArgument(Node):
190-
def __init__(self, name, val):
191-
super(NamedArgument, self).__init__()
191+
class NamedArgument(SyntaxNode):
192+
def __init__(self, name, val, **kwargs):
193+
super(NamedArgument, self).__init__(**kwargs)
192194
self.name = name
193195
self.val = val
194196

195-
class Identifier(Node):
196-
def __init__(self, name):
197-
super(Identifier, self).__init__()
197+
class Identifier(SyntaxNode):
198+
def __init__(self, name, **kwargs):
199+
super(Identifier, self).__init__(**kwargs)
198200
self.name = name
199201

200202
class Symbol(Identifier):
201-
def __init__(self, name):
202-
super(Symbol, self).__init__(name)
203+
def __init__(self, name, **kwargs):
204+
super(Symbol, self).__init__(name, **kwargs)
203205

204206
class Comment(Entry):
205-
def __init__(self, content=None, span=None, annotations=None):
206-
super(Comment, self).__init__(span, annotations)
207+
def __init__(self, content=None, **kwargs):
208+
super(Comment, self).__init__(**kwargs)
207209
self.content = content
208210

209211
class Section(Entry):
210-
def __init__(self, name, comment=None, span=None, annotations=None):
211-
super(Section, self).__init__(span, annotations)
212+
def __init__(self, name, comment=None, **kwargs):
213+
super(Section, self).__init__(**kwargs)
212214
self.name = name
213215
self.comment = comment
214216

215217
class Function(Identifier):
216-
def __init__(self, name):
217-
super(Function, self).__init__(name)
218+
def __init__(self, name, **kwargs):
219+
super(Function, self).__init__(name, **kwargs)
218220

219221
class Junk(Entry):
220-
def __init__(self, content=None, span=None, annotations=None):
221-
super(Junk, self).__init__(span, annotations)
222+
def __init__(self, content=None, **kwargs):
223+
super(Junk, self).__init__(**kwargs)
222224
self.content = content
223225

224226

225-
class Span(Node):
226-
def __init__(self, start, end):
227-
super(Span, self).__init__()
227+
class Span(BaseNode):
228+
def __init__(self, start, end, **kwargs):
229+
super(Span, self).__init__(**kwargs)
228230
self.start = start
229231
self.end = end
230232

231233

232-
class Annotation(Node):
233-
def __init__(self, code, args=None, message=None):
234-
super(Annotation, self).__init__()
234+
class Annotation(SyntaxNode):
235+
def __init__(self, code, args=None, message=None, **kwargs):
236+
super(Annotation, self).__init__(**kwargs)
235237
self.code = code
236238
self.args = args or []
237239
self.message = message
238-
239-
def add_span(self, start, end):
240-
self.span = Span(start, end)

0 commit comments

Comments
 (0)