Source code for sirepo.template.elegant_command_parser

# -*- coding: utf-8 -*-
"""elegant command parser.

:copyright: Copyright (c) 2016 RadiaSoft LLC.  All Rights Reserved.
:license: http://www.apache.org/licenses/LICENSE-2.0.html
"""
from __future__ import absolute_import, division, print_function
from pykern.pkcollections import PKDict
from pykern.pkdebug import pkdc, pkdlog, pkdp
from sirepo.template.line_parser import LineParser
import re


_SKIP_COMMANDS = ["subprocess"]


[docs] def parse_file(command_text, update_filenames): parser = LineParser(0) lines = command_text.replace("\r", "").split("\n") prev_line = "" commands = [] for line in lines: parser.increment_line_number() if re.search(r"^#", line): continue line = re.sub(r"\!.*$", "", line) if not line: continue if re.search(r"\&end", line): if not _parse_line(parser, prev_line + " " + line, commands): break prev_line = "" elif re.search(r"\&", line) or prev_line: prev_line += " " + line else: # ignoring lines between command markers pass if prev_line and re.search(r"\&", prev_line): parser.raise_error("missing &end for command: {}".format(prev_line)) if update_filenames: _update_lattice_names(commands) return commands
def _parse_array_value(parser): # read off the end of the array value list # parse values until a "&end" or "value =" is reached # # response[2] = %s.vhrm, %s.hvrm, # distribution_type[0] = "gaussian", "gaussian", # enforce_rms_values[0] = 1,1,1, # distribution_type[0] = gaussian, gaussian, hard-edge, # distribution_type[0] = 3*"gaussian", # distribution_cutoff[0] = 3*3, res = "" index = parser.get_index() while True: value = parser.parse_value() if value == "&end": parser.reset_index(index) break parser.ignore_whitespace() if parser.peek_char() == "=": parser.reset_index(index) break if value: res += value else: if parser.peek_char() == ",": parser.assert_char(",") res += "," elif parser.peek_char() == "*": parser.assert_char("*") res += "*" else: parser.raise_error("expecting an array value") index = parser.get_index() if not res: parser.raise_error("missing array value") res = re.sub(r",$", "", res) return res def _parse_line(parser, line, commands): parser.set_line(line) parser.ignore_whitespace() parser.assert_char("&") command = PKDict( _id=parser.next_id(), _type=parser.parse_value(r"\s+"), ) if command["_type"] == "stop": return False parser.ignore_whitespace() while True: value = parser.parse_value() if not value: if parser.peek_char() == ",": parser.assert_char(",") continue parser.raise_error("expecting a command element") if value == "&end": break if parser.peek_char() == "=": parser.assert_char("=") if re.search(r"\[", value): command[value] = _parse_array_value(parser) else: command[value] = parser.parse_value(r"[\s,=\!)]") else: parser.raise_error("trailing input: {}".format(value)) parser.assert_end_of_line() if not command["_type"] in _SKIP_COMMANDS: commands.append(command) return True def _update_lattice_names(commands): # preserve the name of the first run_setup.lattice # others may map to previous save_lattice names is_first_run_setup = True save_lattices = [] for cmd in commands: if cmd["_type"] == "save_lattice": name = re.sub(r"\%s", "", cmd["filename"]) save_lattices.append(name) if cmd["_type"] == "run_setup": if is_first_run_setup: is_first_run_setup = False continue for index in reversed(range(len(save_lattices))): if re.search( re.escape(save_lattices[index]), cmd["lattice"], re.IGNORECASE ): cmd["lattice"] = ( "save_lattice" if index == 0 else "save_lattice{}".format(index + 1) ) break else: cmd["lattice"] = "Lattice"