Files
2026-07-13 20:00:07 +02:00

83 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""Parsing routines for JPL text PCK files.
For an (incomplete) summary of the file format, look for the heading
“NAIF Text Kernel Format” in the “PCK Required Reading”:
https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/pck.html
"""
import re
def load(lines, variables):
"""Load PCK text kernel names and values into a ``variables`` dict."""
for name, equals, values in parse(lines):
if equals == b'=':
if len(values) == 1:
variables[name] = values[0] # unbox a scalar value
else:
variables[name] = values
elif equals == b'+=':
old = variables.get(name)
if old is None:
old = variables[name] = []
elif not isinstance(old, list):
old = [old] # box an earlier scalar before extending
old.extend(values)
def parse(lines):
"""Yield ``(name, equals, values)`` bytestrings from a PCK text kernel.
This merely reads raw assignment statements; it doesn’t combine
multiple ``+=`` assignments to create single values. The byte
string ``equals`` will be either ``b'='`` or ``b'+='``. Scalars are
returned as a ``values`` list one item long.
"""
tokens = iter(_parse_tokens(lines))
for token in tokens:
name = token.decode('ascii')
equals = next(tokens)
if equals not in (b'=', b'+='):
raise ValueError('an equals sign is expected after %r' % name)
token = next(tokens)
if token == b'(':
values = []
for token in tokens:
if token == b')':
break
values.append(_evaluate(token))
else:
values = [_evaluate(token)]
yield name, equals, values
def _evaluate(token):
"""Return a string, integer, or float parsed from a PCK text kernel."""
if token[0:1].startswith(b"'"):
return token[1:-1].decode('ascii')
if token.isdigit():
return int(token)
if token.startswith(b'@'):
raise NotImplementedError('TODO: need parser for dates,'
' like @01-MAY-1991/16:25')
token = token.replace(b'D', b'E') # for numbers like -1.4D-12
return float(token)
_token_re = re.compile(b"[A-Za-z]\\w+|=|\\+=|\\(|\\)|'[^']*'|[^), ]+")
def _parse_tokens(lines):
"""Yield all the tokens inside the data segments of a PCK text file."""
lines = iter(lines)
for line in lines:
if b'\\begindata' not in line:
continue # save cost of strip() on most lines
line = line.strip()
if line != b'\\begindata':
continue
for line in lines:
line = line.strip()
if line == b'\\begintext':
break
for token in _token_re.findall(line):
yield token