forked from mirrors/gecko-dev
107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
import textwrap
|
|
|
|
import fluent.syntax.ast as FTL
|
|
from fluent.syntax.parser import FluentParser, FluentParserStream
|
|
|
|
|
|
fluent_parser = FluentParser(with_spans=False)
|
|
|
|
|
|
def parse(Parser, string):
|
|
if Parser is FluentParser:
|
|
return fluent_parser.parse(string)
|
|
|
|
# Parsing a legacy resource.
|
|
|
|
# Parse the string into the internal Context.
|
|
parser = Parser()
|
|
# compare-locales expects ASCII strings.
|
|
parser.readContents(string.encode("utf8"))
|
|
# Transform the parsed result which is an iterator into a dict.
|
|
return {ent.key: ent for ent in parser}
|
|
|
|
|
|
def ftl_resource_to_ast(code):
|
|
return fluent_parser.parse(ftl(code))
|
|
|
|
|
|
def ftl_resource_to_json(code):
|
|
return fluent_parser.parse(ftl(code)).to_json()
|
|
|
|
|
|
def ftl_pattern_to_json(code):
|
|
ps = FluentParserStream(ftl(code))
|
|
return fluent_parser.maybe_get_pattern(ps).to_json()
|
|
|
|
|
|
def to_json(merged_iter):
|
|
return {path: resource.to_json() for path, resource in merged_iter}
|
|
|
|
|
|
LOCALIZABLE_ENTRIES = (FTL.Message, FTL.Term)
|
|
|
|
|
|
def get_message(body, ident):
|
|
"""Get message called `ident` from the `body` iterable."""
|
|
for entity in body:
|
|
if isinstance(entity, LOCALIZABLE_ENTRIES) and entity.id.name == ident:
|
|
return entity
|
|
|
|
|
|
def get_transform(body, ident):
|
|
"""Get entity called `ident` from the `body` iterable."""
|
|
for transform in body:
|
|
if transform.id.name == ident:
|
|
return transform
|
|
|
|
|
|
def skeleton(node):
|
|
"""Create a skeleton copy of the given node.
|
|
|
|
For localizable entries, the value is None and the attributes are {}.
|
|
That's not a valid Fluent entry, so it requires further manipulation to
|
|
set values and/or attributes.
|
|
"""
|
|
if isinstance(node, LOCALIZABLE_ENTRIES):
|
|
return type(node)(id=node.id.clone(), value=None)
|
|
return node.clone()
|
|
|
|
|
|
def ftl(code):
|
|
"""Nicer indentation for FTL code.
|
|
|
|
The code returned by this function is meant to be compared against the
|
|
output of the FTL Serializer. The input code will end with a newline to
|
|
match the output of the serializer.
|
|
"""
|
|
|
|
# The code might be triple-quoted.
|
|
code = code.lstrip("\n")
|
|
|
|
return textwrap.dedent(code)
|
|
|
|
|
|
def fold(fun, node, init):
|
|
"""Reduce `node` to a single value using `fun`.
|
|
|
|
Apply `fun` against an accumulator and each subnode of `node` (in postorder
|
|
traversal) to reduce it to a single value.
|
|
"""
|
|
|
|
def fold_(vals, acc):
|
|
if not vals:
|
|
return acc
|
|
|
|
head = list(vals)[0]
|
|
tail = list(vals)[1:]
|
|
|
|
if isinstance(head, FTL.BaseNode):
|
|
acc = fold(fun, head, acc)
|
|
if isinstance(head, list):
|
|
acc = fold_(head, acc)
|
|
if isinstance(head, dict):
|
|
acc = fold_(head.values(), acc)
|
|
|
|
return fold_(tail, fun(acc, head))
|
|
|
|
return fold_(vars(node).values(), init)
|