Esempio n. 1
1
    def initBNF(self):
        indentStack = [1]
        encoding = Literal("<").suppress() + identifier("encoding") + Literal(
            ">").suppress()
        constdecl = Group((const + identifier + assign + value).setParseAction(
            self.const_action))
        vardecl = Group(
            (type_("type_") + Optional(encoding) + identifier("name") +
             Optional(assign + value("value") + Optional(identifier)("unit"))
             ).setParseAction(self.var_action))
        insertdecl = Group(
            (insert + dblQuotedString + LineEnd().suppress()).setParseAction(
                self.insert_action))
        procedurecall = Group((identifier + Literal("(").suppress() + Optional(
            delimitedList(
                (identifier + Optional(assign + identifier)).setParseAction(
                    self.named_param_action))) +
                               Literal(")").suppress()).setParseAction(
                                   self.procedurecall_action))
        condition = Group(
            (identifier("leftidentifier") + comparison("comparison") +
             (identifier("identifier")
              | value.setParseAction(self.value_action))).setParseAction(
                  self.condition_action))("condition")
        pointer = Literal("*") + identifier

        rExp = Forward()
        #numexpression = Forward()

        opexpression = (identifier("operand") +
                        (Literal(">>") | Literal("<<") | Literal("+")
                         | Literal("*") | Literal("/") | Literal("-"))("op") +
                        Group(rExp)("argument")).setParseAction(
                            self.opexpression_action)
        rExp << (
            procedurecall | opexpression | identifier("identifier")
            | value.setParseAction(self.value_action) |
            #Group( Suppress("(") + rExp + Suppress(")") ) |
            #Group( "+" + rExp) |
            #Group( "-" + rExp) |
            Group(Literal("not") + rExp))
        rExpCondition = Group(
            (Optional(not_)("not_") + rExp("rExp"))).setParseAction(
                self.rExp_condition_action)("condition")
        rExp.setParseAction(self.rExp_action)

        assignment = ((identifier | pointer)("lval") + assign +
                      rExp("rval")).setParseAction(self.assignment_action)
        addassignment = ((identifier | pointer)("lval") +
                         (Literal("+=") | Literal("-=") | Literal("*=")
                          | Literal("&=") | Literal("|=") | Literal(">>=")
                          | Literal("/=") | Literal("<<="))("op") +
                         Group(rExp)("rval")).setParseAction(
                             self.addassignement_action)

        statement = Forward()
        statementBlock = indentedBlock(statement, indentStack).setParseAction(
            self.statementBlock_action)
        procedure_statement = Group(
            (Keyword("def").suppress() + identifier("funcname") +
             Literal("(").suppress() + Literal(")").suppress() +
             colon.suppress() + statementBlock).setParseAction(
                 self.def_action))
        while_statement = Group(
            (Keyword("while").suppress() +
             (condition | rExpCondition)("condition") + colon.suppress() +
             statementBlock("statementBlock")).setParseAction(
                 self.while_action))
        if_statement = (Keyword("if") + condition + colon +
                        statementBlock("ifblock") + Optional(
                            Keyword("else").suppress() + colon +
                            statementBlock("elseblock"))).setParseAction(
                                self.if_action)
        statement << (procedure_statement | while_statement | if_statement
                      | procedurecall | assignment | addassignment)

        decl = constdecl | vardecl | insertdecl | Group(statement)

        self.program = ZeroOrMore(decl)
        self.program.ignore(pythonStyleComment)
Esempio n. 2
0
def parse_survey():
    indent_stack = [1]
    stmt = Forward()

    identifier = Word(alphas, alphanums + "_")
    number = Word(nums)
    doublequoted_string = QuotedString('"', escChar="\\")
    singlequoted_string = QuotedString("'", escChar="\\")
    string = doublequoted_string | singlequoted_string
    value = number | string

    # TODO Parse expressions properly.
    # op = oneOf("+ - * /")
    comp_op = oneOf("= != >= > <= <")

    comment = Group("#" + restOfLine)

    command = Group("@" + identifier + OneOrMore((identifier | value), stopOn=LineEnd()))

    variable = Group("${" + identifier + "}")
    dot = Literal(".")
    expr = Group((variable | dot) + comp_op + value)
    if_cond = "if" + (expr | value)
    if_body = indentedBlock(pp.ungroup(stmt), indent_stack)
    if_block = Group(if_cond + Suppress(":") + if_body)

    q_name = identifier
    q_type = Group(OneOrMore(identifier))
    q_label = string
    q_param = ((identifier + identifier) | (identifier + value))
    q_params = ZeroOrMore(q_param, stopOn=LineEnd())
    question = Group(q_name + q_type + Suppress(":") + Optional(q_label) + q_params)

    group_params = Group(ZeroOrMore(q_param, stopOn=LineEnd()) + Optional(if_cond))

    group_label = string
    group_def = "group" + Group(identifier + Optional(group_label)) + group_params + Optional(if_cond) + Suppress(":")
    group_body = indentedBlock(pp.ungroup(stmt), indent_stack)
    group_block = Group(group_def + group_body)

    repeat_def = "repeat" + Group(identifier + Optional(group_label)) + group_params + Suppress(":")
    repeat_block = Group(repeat_def + group_body)

    # TODO Add + Suppress(LineEnd())?
    stmt <<= (comment | command | if_block | group_block | repeat_block | question)
    stmts = OneOrMore(stmt)

    return stmts
Esempio n. 3
0
def parse_choices():
    indent_stack = [1]
    stmt = Forward()

    identifier = Word(alphas, alphanums + "_")
    number = Word(nums)
    string = QuotedString('"', escChar="\\")
    value = number | string

    comment = Group("#" + restOfLine)

    command = Group("@" + identifier +
                    OneOrMore((identifier | value), stopOn=LineEnd()))

    choice_param = ((identifier + identifier) | (identifier + value))
    choice_params = Group(ZeroOrMore(choice_param, stopOn=LineEnd()))
    choice_value = value
    choice_label = value
    choice = Group(choice_value + choice_label + choice_params)

    list_name = identifier
    list_def = "list" + list_name + choice_params + Suppress(":")
    list_body = indentedBlock(ungroup(stmt), indent_stack)
    list_block = Group(list_def + list_body)

    stmt <<= (comment | command | list_block | choice)
    stmts = OneOrMore(stmt)

    return stmts
Esempio n. 4
0
def _build_csv_parser():
    separator = pp.Suppress(':')
    key = pp.Word(pp.printables, excludeChars=':')
    value = pp.Regex(r'[^\n\r]*') + pp.LineEnd().suppress()

    block_name = key + separator  + pp.LineEnd().suppress()

    key_value = key + separator + value

    header = (pp.LineStart().suppress() +  pp.Word(pp.nums) + pp.ZeroOrMore( pp.White().suppress() + pp.Word(pp.nums)) + pp.LineEnd().suppress())

    csv_header = pp.delimitedList(pp.Word(pp.printables, excludeChars=',')) + pp.LineEnd().suppress()

    csv_row = pp.delimitedList(pp.Word(pp.nums + ';.+-e_') | pp.Literal('custom')) + pp.LineEnd().suppress()

    indent_stack = [1]
    block = pp.Forward()
    block_body = ( block | key_value)

    indented_block = pp.Dict(pp.ungroup(pp.indentedBlock(block_body, indent_stack)))
    block << ( block_name + indented_block | key_value)

    return pp.Optional(header) + pp.ZeroOrMore(pp.Dict(pp.Group(block))).setResultsName('meta') + \
        csv_header.setResultsName('csvHeader') + \
        pp.Group(pp.OneOrMore(pp.Group(csv_row))).setResultsName('csvValues')
Esempio n. 5
0
def DOCSTR_BLOCK(expr, resultsName=None):  # pylint: disable=invalid-name
    """Block with an optional docstring followed by one of more `expr`."""

    # Copied from pyparsing.indentedBlock
    def checkSubIndent(s, l, t):  # pylint: disable=invalid-name
        curCol = pp.col(l, s)  # pylint: disable=invalid-name
        if curCol > _indentation_stack[-1]:
            _indentation_stack.append(curCol)
        else:
            raise pp.ParseException(s, l, 'not a subentry')

    def checkUnindent(s, l, t):  # pylint: disable=invalid-name
        del t
        if l >= len(s):
            return
        curCol = pp.col(l, s)  # pylint: disable=invalid-name
        if not (_indentation_stack and curCol < _indentation_stack[-1]
                and curCol <= _indentation_stack[-2]):
            raise pp.ParseException(s, l, 'not an unindent')
        _indentation_stack.pop()

    INDENT = (  # pylint: disable=invalid-name
        pp.Empty() +
        pp.Empty().setParseAction(checkSubIndent)).setName('INDENT')
    UNDENT = pp.Empty().setParseAction(checkUnindent).setName('UNINDENT')  # pylint: disable=invalid-name

    docstring = Group(
        Tag('docstring') + pp.QuotedString('"""', multiline=True))
    code = Optional(pp.indentedBlock(expr, _indentation_stack, False), [])
    if resultsName:
        code = code.setResultsName(resultsName)

    body = INDENT + Optional(docstring)('docstring') + code + UNDENT
    return S(':') + NEWLINE - body
Esempio n. 6
0
def _build_ana_rcp_parser():
    separator = pp.Suppress(':')
    key = pp.Word(pp.printables, excludeChars=':')
    value = pp.Regex(r'[^\n\r]*') + pp.LineEnd().suppress()

    block_name = key + separator + pp.LineEnd().suppress()
    platemap_keylist = pp.Literal(
        'platemap_comp4plot_keylist') + separator + pp.delimitedList(
            pp.Word(pp.alphas))
    run_ids = pp.Literal('run_ids') + separator + pp.delimitedList(
        pyparsing_common.integer)
    plate_id = (pp.Literal('plate_ids') |
                pp.Literal('plate_id')) + separator + pyparsing_common.integer

    key_value = (platemap_keylist | run_ids | plate_id
                 | key + separator + value)

    indent_stack = [1]
    block = pp.Forward()
    block_body = (block | key_value)

    indented_block = pp.Dict(
        pp.ungroup(pp.indentedBlock(block_body, indent_stack)))
    block << (block_name + indented_block | key_value)

    return pp.OneOrMore(pp.Dict(pp.Group(block)))
Esempio n. 7
0
    def parse(self, data=""):
        """Parse ssh-config data

        args:
            data (str)

        returns:
            Parsed config or None (dict)
        """

        if data:
            self.raw = data

        SPACE = White().suppress()
        SEP = Suppress(SPACE) | Suppress("=")
        HOST = CaselessLiteral("Host").suppress()
        MATCH = CaselessLiteral("Match").suppress()
        KEY = Word(alphanums)
        VALUE = Word(alphanums + ' ~%*?!._-+/,"')
        paramValueDef = SkipTo("#" | lineEnd)
        indentStack = [1]

        HostDecl = (HOST | MATCH) + SEP + VALUE
        paramDef = Dict(Group(KEY + SEP + paramValueDef))
        block = indentedBlock(paramDef, indentStack)
        HostBlock = Dict(Group(HostDecl + block))
        try:
            return OneOrMore(HostBlock).ignore(pythonStyleComment).parseString(self.raw)
        except ParseException as e:
            print(e)
        return None
Esempio n. 8
0
    def make_ccss_parser(self):
        # CleverCSS (CCSS) grammar
        def _parse_name(string, location, tokens):
            for t in tokens:
                if t[-1] == ';':
                    t.replace(';', '')
        def _parse_property_value(string, location, tokens):
            pass

        indent_stack = [1]
        PROPERTY_NAME = Word(alphanums + '-*')
        PROPERTY_VALUE = Word(alphanums + ' (`\'/,%#-."\\);$_').setParseAction(_parse_name)
        PROPERTY_LINE_END = ((Optional(Word(';')).suppress() + LineEnd()) |
                            LineEnd().suppress())
        CCSS_PROPERTY = Group(PROPERTY_NAME +
                            Word(':').suppress() +
                            PROPERTY_VALUE.setParseAction(_parse_property_value) +
                            PROPERTY_LINE_END
                        ).setResultsName('property')
        CCSS_BREAK = Word('&')
        CCSS_CLASS_NAME = Word(alphanums + '.#_-*[]\'="')
        CCSS_SINGLE_CLASS = Combine(
                                Optional(
                                    Combine(CCSS_BREAK + Optional(White()) + Word('>')) |
                                    Combine(CCSS_BREAK + Optional(White()) + Word(':')) |
                                    CCSS_BREAK
                                ) +
                                Optional(White()) +
                                (CCSS_CLASS_NAME ^
                                (CCSS_CLASS_NAME + Word(':') + CCSS_CLASS_NAME))
                            )
        CCSS_SELECTOR = Group(OneOrMore(CCSS_SINGLE_CLASS))
        CCSS_SELECTOR_GROUP = Group(delimitedList(CCSS_SELECTOR) +
                                    Word(':').suppress() +
                                    LineEnd().suppress()
                              ).setResultsName('selectors')
        CCSS_DEF = Forward()
        CCSS_DEF << (Group(
                        Optional(LineEnd()).suppress() +
                        CCSS_SELECTOR_GROUP +
                        indentedBlock(
                            OneOrMore(CCSS_PROPERTY).setResultsName('properties') |
                            OneOrMore(CCSS_DEF)
                        , indent_stack).setResultsName('nodes')
                    )).setResultsName('content')
        CCSS = OneOrMore(CCSS_DEF).ignore(cStyleComment)
        return CCSS
Esempio n. 9
0
    def parse(self, data=""):
        if data:
            self.raw = data
        SPACE = White().suppress()
        HOST = Literal("Host").suppress()
        KEY = Word(alphanums + "~*._-/")
        VALUE = Word(alphanums + "~*._-/")
        paramValueDef = SkipTo("#" | lineEnd)
        indentStack = [1]

        HostDecl = HOST + SPACE + VALUE
        paramDef = Dict(Group(KEY + SPACE + paramValueDef))
        block = indentedBlock(paramDef, indentStack)
        HostBlock = Dict(Group(HostDecl + block))
        try:
            return OneOrMore(HostBlock).ignore(pythonStyleComment).parseString(self.raw)
        except ParseException as e:
            return None
Esempio n. 10
0
def _get_block(file_lines, line) -> str:
    """
    Return a Python block of code beginning in line.

    :param file_lines: Lines of code
    :param line: First line of block
    """
    frst_ln = file_lines[line - 1]
    file_lines = file_lines[line - 1:]
    rem_file = "\n".join(file_lines)
    indent_stack = [len(frst_ln) - len(frst_ln.lstrip(' ')) + 1]
    prs_block = Forward()
    block_line = SkipTo(LineEnd())
    block_header = SkipTo(LineEnd())
    block_body = indentedBlock(prs_block, indent_stack)
    block_def = Group(block_header + block_body)
    # pylint: disable=pointless-statement
    prs_block << (block_def | block_line)
    block_list = prs_block.parseString(rem_file).asList()
    block_str = (lang.lists_as_string(block_list, '', 0))
    return block_str.rstrip()
Esempio n. 11
0
    def parser(self):
        integer = Regex('\d+').setParseAction(lambda x, y, z: int(z[0]))
        floating_point = Regex('[+-]?(\d*[.])?\d+(e[+-]\d+)?').setParseAction(
            lambda x, y, z: float(z[0])
        )  #Group(Optional(Suppress('-')) + Regex('\d+') + Optional(Literal('.') + Regex('\d+')))
        left_bracket = Suppress('[')
        right_bracket = Suppress(']')
        variable_name = Word(alphas + '0123456789_')
        lt = Literal('<')
        branch = (integer + Suppress(':') + left_bracket + variable_name + lt +
                  floating_point + right_bracket +
                  Group(Literal('yes=') + integer) + Suppress(',') +
                  Group(Literal('no=') + integer) + Suppress(',') +
                  Group(Literal('missing=') + integer))
        # branch
        leaf = integer + Suppress(':') + Suppress('leaf=') + floating_point

        stack = [1]
        tree = Forward()
        tree << (leaf ^ (branch + indentedBlock(tree, stack)))
        return OneOrMore(tree)
Esempio n. 12
0
    def buildSyntax(self):
        '''WIP'''
        dreamScript = pyp.Forward()

        # Constants
        singlelineString = pyp.QuotedString(
            '"', '\\').setResultsName('string').setParseAction(self.makeString)
        fileRef = pyp.QuotedString(
            "'",
            '\\').setResultsName('fileRef').setParseAction(self.makeFileRef)
        multilineString = pyp.QuotedString(
            quoteChar='{"', endQuoteChar='"}',
            multiline=True).setResultsName('string').setParseAction(
                self.makeString)
        number = pyp.Regex(r'\d+(\.\d*)?([eE]\d+)?').setResultsName(
            'number').setParseAction(self.makeNumber)

        # Other symbols
        listStart = pyp.Suppress('list(')
        listEnd = pyp.Suppress(')')

        VAR_GLOBAL = pyp.Keyword('global')
        VAR_CONST = pyp.Keyword('const')
        SLASH = pyp.Literal('/')
        EQUAL = pyp.Literal('=')
        VAR = pyp.Keyword('var')

        #############################
        # Grammar
        #############################

        constant = singlelineString | fileRef | multilineString | number | dreamList

        #  Lists
        listElement = constant | (constant + EQUAL + constant)
        listElement = pyp.operatorPrecedence(listElement, [
            (
                "=",
                2,
                pyp.opAssoc.LEFT,
            ),
        ])
        listContents = pyp.delimitedList(listElement)
        dreamList << pyp.Group(listStart + listContents + listEnd)
        dreamList.setParseAction(self.handleList)

        #  Paths
        relpath = pyp.ident | relpath + SLASH + pyp.ident
        abspath = SLASH + relpath
        path = (abspath | relpath).setParseAction(self.handlePath)
        pathslash = path + SLASH

        #  Preprocessor stuff
        ppStatement = pyp.Forward()

        ppDefine = pyp.Keyword('#define') + pyp.ident.setResultsName(
            'name') + pyp.restOfLine.setResultsName('value')
        ppDefine.setParseAction(self.handlePPDefine)
        ppUndef = pyp.Keyword('#undef') + pyp.ident.setResultsName('name')
        ppUndef.setParseAction(self.handlePPUndef)

        ppIfdef = (pyp.Keyword('#ifdef') +
                   pyp.ident.setResultsName('name')).setParseAction(
                       self.handlePPIfdef)
        ppIfndef = (pyp.Keyword('#ifndef') +
                    pyp.ident.setResultsName('name')).setParseAction(
                        self.handlePPIfndef)
        ppElse = (pyp.Keyword('#else') +
                  pyp.ident.setResultsName('name')).setParseAction(
                      self.handlePPElse)
        ppEndif = pyp.Keyword('#endif').setParseAction(self.handlePPElse)

        ppStatement = pyp.lineStart + (ppIfdef | ppIfndef | ppElse | ppEndif)

        # Var Declarations
        ##########################
        var_modifiers = pyp.ZeroOrMore(
            SLASH + (VAR_GLOBAL | VAR_CONST)).setResultsName('modifiers')
        var_assignment = EQUAL + constant
        varblock_inner_ref = pyp.ident.setResultsName('name') + pyp.Optional(
            var_assignment)
        var_argument = VAR + pyp.Optional(
            abspath) + SLASH + pyp.ident.setResultsName('name') + pyp.Optional(
                var_assignment)
        varblock_inner_decl = var_modifiers + pyp.Optional(
            abspath) + SLASH + varblock_inner_ref
        varblock_element = varblock_inner_decl | varblock_inner_ref
        varblock = VAR + pyp.indentedBlock(var_blockinner_decl)
        inline_vardecl = VAR + varblock_inner_decl
        vardecl = varblock | inline_vardecl

        # Proc Declarations
        PROC = pyp.Keyword('proc')
        proc_args = '(' + pyp.delimitedList(
            var_argument | pyp.ident.setResultsName('name')) + ')'
        procblock_proc = pyp.ident.setResultsName(
            'name') + proc_args + pyp.indentedBlock(proc_instructions)
        procblock = PROC + pyp.indentedBlock(procblock_proc, [1])

        # Atom blocks
        atomdecl = pyp.Forward()
        atomdecl << path + pyp.indentedBlock(vardecl | atomdecl | procdecl,
                                             [1])

        return dreamScript
Esempio n. 13
0
SW = lambda kw: S(W(kw))
Group = pp.Group  # pylint: disable=invalid-name
Optional = pp.Optional  # pylint: disable=invalid-name
LineNum = pp.lineno  # pylint: disable=invalid-name

# Grammar for Python Type Declaration (CLIF version)


def fail_block(s, unused_loc, expr, err):
    raise pp.ParseFatalException(s, err.loc, 'invalid statement in %s' % expr)


_indentation_stack = [1]  # Holds cols to indent from.
BLOCK = lambda el: (
    S(':') + NEWLINE -  # pylint: disable=g-long-lambda
    pp.indentedBlock(el, _indentation_stack).setFailAction(fail_block))


def reset_indentation():  # pylint: disable=invalid-name
    _indentation_stack[:] = [1]


K = lambda el: pp.Keyword(el).setParseAction(lambda el, loc, t: [t[0], loc])
# pylint: disable=undefined-variable
E = lambda el: pp.Empty().setParseAction(lambda: el)
Tag = lambda el: pp.Empty().setParseAction(lambda s, loc, t: [el, loc])  # pylint: disable=invalid-name
# pylint: enable=undefined-variable
NEWLINE = pp.lineEnd.setWhitespaceChars(' ').suppress().ignore(
    pp.pythonStyleComment)

Esempio n. 14
0
    def __init__(self, fragment_file, sdkconfig):
        try:
            fragment_file = open(fragment_file, "r")
        except TypeError:
            pass

        path = os.path.realpath(fragment_file.name)

        indent_stack = [1]

        class parse_ctx:
            fragment = None  # current fragment
            key = ""  # current key
            keys = list()  # list of keys parsed
            key_grammar = None  # current key grammar

            @staticmethod
            def reset():
                parse_ctx.fragment_instance = None
                parse_ctx.key = ""
                parse_ctx.keys = list()
                parse_ctx.key_grammar = None

        def fragment_type_parse_action(toks):
            parse_ctx.reset()
            parse_ctx.fragment = FRAGMENT_TYPES[
                toks[0]]()  # create instance of the fragment
            return None

        def expand_conditionals(toks, stmts):
            try:
                stmt = toks["value"]
                stmts.append(stmt)
            except KeyError:
                try:
                    conditions = toks["conditional"]
                    for condition in conditions:
                        try:
                            _toks = condition[1]
                            _cond = condition[0]
                            if sdkconfig.evaluate_expression(_cond):
                                expand_conditionals(_toks, stmts)
                                break
                        except IndexError:
                            expand_conditionals(condition[0], stmts)
                except KeyError:
                    for tok in toks:
                        expand_conditionals(tok, stmts)

        def key_body_parsed(pstr, loc, toks):
            stmts = list()
            expand_conditionals(toks, stmts)

            if parse_ctx.key_grammar.min and len(
                    stmts) < parse_ctx.key_grammar.min:
                raise ParseFatalException(
                    pstr, loc,
                    "fragment requires at least %d values for key '%s'" %
                    (parse_ctx.key_grammar.min, parse_ctx.key))

            if parse_ctx.key_grammar.max and len(
                    stmts) > parse_ctx.key_grammar.max:
                raise ParseFatalException(
                    pstr, loc,
                    "fragment requires at most %d values for key '%s'" %
                    (parse_ctx.key_grammar.max, parse_ctx.key))

            try:
                parse_ctx.fragment.set_key_value(parse_ctx.key, stmts)
            except Exception as e:
                raise ParseFatalException(
                    pstr, loc,
                    "unable to add key '%s'; %s" % (parse_ctx.key, e.message))
            return None

        key = Word(alphanums + "_") + Suppress(":")
        key_stmt = Forward()

        condition_block = indentedBlock(key_stmt, indent_stack)
        key_stmts = OneOrMore(condition_block)
        key_body = Suppress(key) + key_stmts
        key_body.setParseAction(key_body_parsed)

        condition = originalTextFor(
            SDKConfig.get_expression_grammar()).setResultsName("condition")
        if_condition = Group(
            Suppress("if") + condition + Suppress(":") + condition_block)
        elif_condition = Group(
            Suppress("elif") + condition + Suppress(":") + condition_block)
        else_condition = Group(
            Suppress("else") + Suppress(":") + condition_block)
        conditional = (if_condition + Optional(OneOrMore(elif_condition)) +
                       Optional(else_condition)).setResultsName("conditional")

        def key_parse_action(pstr, loc, toks):
            key = toks[0]

            if key in parse_ctx.keys:
                raise ParseFatalException(
                    pstr, loc,
                    "duplicate key '%s' value definition" % parse_ctx.key)

            parse_ctx.key = key
            parse_ctx.keys.append(key)

            try:
                parse_ctx.key_grammar = parse_ctx.fragment.get_key_grammars(
                )[key]
                key_grammar = parse_ctx.key_grammar.grammar
            except KeyError:
                raise ParseFatalException(
                    pstr, loc, "key '%s' is not supported by fragment" % key)
            except Exception as e:
                raise ParseFatalException(
                    pstr, loc,
                    "unable to parse key '%s'; %s" % (key, e.message))

            key_stmt << (conditional
                         | Group(key_grammar).setResultsName("value"))

            return None

        def name_parse_action(pstr, loc, toks):
            parse_ctx.fragment.name = toks[0]

        key.setParseAction(key_parse_action)

        ftype = Word(alphas).setParseAction(fragment_type_parse_action)
        fid = Suppress(":") + Word(alphanums + "_.").setResultsName("name")
        fid.setParseAction(name_parse_action)
        header = Suppress("[") + ftype + fid + Suppress("]")

        def fragment_parse_action(pstr, loc, toks):
            key_grammars = parse_ctx.fragment.get_key_grammars()
            required_keys = set(
                [k for (k, v) in key_grammars.items() if v.required])
            present_keys = required_keys.intersection(set(parse_ctx.keys))
            if present_keys != required_keys:
                raise ParseFatalException(
                    pstr, loc, "required keys %s for fragment not found" %
                    list(required_keys - present_keys))
            return parse_ctx.fragment

        fragment_stmt = Forward()
        fragment_block = indentedBlock(fragment_stmt, indent_stack)

        fragment_if_condition = Group(
            Suppress("if") + condition + Suppress(":") + fragment_block)
        fragment_elif_condition = Group(
            Suppress("elif") + condition + Suppress(":") + fragment_block)
        fragment_else_condition = Group(
            Suppress("else") + Suppress(":") + fragment_block)
        fragment_conditional = (
            fragment_if_condition +
            Optional(OneOrMore(fragment_elif_condition)) +
            Optional(fragment_else_condition)).setResultsName("conditional")

        fragment = (header +
                    OneOrMore(indentedBlock(key_body, indent_stack,
                                            False))).setResultsName("value")
        fragment.setParseAction(fragment_parse_action)
        fragment.ignore("#" + restOfLine)

        deprecated_mapping = DeprecatedMapping.get_fragment_grammar(
            sdkconfig, fragment_file.name).setResultsName("value")

        fragment_stmt << (Group(deprecated_mapping) | Group(fragment)
                          | Group(fragment_conditional))

        def fragment_stmt_parsed(pstr, loc, toks):
            stmts = list()
            expand_conditionals(toks, stmts)
            return stmts

        parser = ZeroOrMore(fragment_stmt)
        parser.setParseAction(fragment_stmt_parsed)

        self.fragments = parser.parseFile(fragment_file, parseAll=True)

        for fragment in self.fragments:
            fragment.path = path
Esempio n. 15
0
RPAREN = pp.Suppress(')')
LBRACK = pp.Suppress('[')
RBRACK = pp.Suppress(']')
COLON = pp.Suppress(':')
NAME = pp.Word(pp.alphas + '_', pp.alphanums + '_')

string = pp.quotedString().setParseAction(pp.removeQuotes)
number = ppc.number()
comment = '#' + pp.restOfLine
var = NAME.copy().setParseAction(el.Var)

expr = pp.Forward()
stmt = pp.Forward()

stack = [1]
suite = pp.indentedBlock(expr, stack)

params = pp.Optional(pp.delimitedList(expr))

ruledecl = pp.Suppress('rule') + NAME + \
        pp.Group(LPAREN + params + RPAREN) + COLON
ruledef = pp.Group(ruledecl + suite).setParseAction(el.Rule)

grouped = (LPAREN + expr + RPAREN).setParseAction(el.Group)
listed = (LBRACK + params + RBRACK).setParseAction(el.List)
call = (NAME + LPAREN + params + RPAREN).setParseAction(el.Call)

sliceops = (opt(expr) + ':' + opt(expr) + opt(':' + expr)) | expr
slice = (LBRACK + sliceops + RBRACK).setParseAction(el.Slice)

compops = pp.oneOf('== != <= < >= >') | (L('is') + L('not')) | \
Esempio n. 16
0
def get_syntax():
    """
    Get the syntax suitable for parsing `pactl list` output

    The syntax parses valid text and produces a list of :class:`Record` objects
    """
    # The syntax uses indenting so a shared indent stack is required to parse
    # output properly. See indentedBlock() documentation for details
    indent_stack = [1]
    # VALUE
    # VALUE = p.Regex(".+").setResultsName("VALUE")
    property_value = (
        p.indentedBlock(
            p.Word(p.alphanums + ".").setResultsName("PROP_NAME")
            + p.Suppress('=')
            + p.QuotedString('"').setResultsName("PROP_VALUE"),
            indent_stack
        ).setResultsName("prop-value")
    )
    simple_value = p.ungroup(
        p.Combine(
            p.Regex(r".*")
            + p.Optional(
                p.indentedBlock(p.Regex(".+"), indent_stack)
            ),
            joinString='\n',
            adjacent=False
        )
    ).setResultsName("simple-value")
    value = p.Or(
        [property_value, simple_value]
    ).setResultsName("value")
    # NAME
    NAME = p.Regex("[^:]+").setResultsName("NAME")
    # entry: NAME ':' [VALUE] [indented<VALUE>]
    entry = (
        NAME + p.Suppress(":") + value
    ).setResultsName(
        "entry"
    ).setParseAction(
        Entry.from_tokens
    )
    # HEADER
    HEADER = p.restOfLine.setResultsName("HEADER")
    # record: HEADER '\n' indented<entry>
    record = (
        HEADER
        + p.Suppress(p.lineEnd)
        + p.indentedBlock(entry, indent_stack).setResultsName("entry-list")
    ).setResultsName(
        "record"
    ).setParseAction(
        Record.from_tokens
    )
    # record_list: record+
    record_list = p.OneOrMore(
        record
    ).setResultsName(
        "record-list"
    )
    syntax = record_list
    syntax.enablePackrat()
    return syntax
Esempio n. 17
0
class TypeDocGrammar:
    r"""
    Grammar to parse boto3 docs syntax.

    EOL ::= ["\r"] "\n"
    SOL ::= LINE_START
    line ::= [^EOL]+ EOL
    word ::= alphanums + "_"
    indented_block ::= INDENT (line_indented | any_line)
    line_indented ::= any_line indented_block
    type_definition ::= ":type" [^:]+ ":" [^EOL]+
    rtype_definition ::= ":rtype:" [^EOL]+
    returns_definition ::= (":returns:" | ":return:") [^EOL]+
    param_definition ::= ":param" [^:]+ ":" [^EOL]+ EOL [indented_block]
    response_structure ::= "**Response Structure**" line [indented_block]
    typed_dict_key_line ::= "-" "**" word "**" "*(" word ")" "--*" [^EOL]+ + EOL
    type_line ::= "-" "*(" word ")" "--*" [^EOL]+ + EOL
    any_line ::= typed_dict_key_line | type_line | line
    """

    indent_stack = [1]
    SOL = LineStart().suppress()
    EOL = LineEnd().suppress()
    word = Word(alphanums + "_")
    line = SkipTo(LineEnd()) + EOL
    line_indented = Forward()
    any_line = Forward()
    indented_block = indentedBlock(
        line_indented | any_line, indentStack=indent_stack
    ).setResultsName("indented")
    line_indented <<= any_line + indented_block

    type_definition = (
        SOL
        + Literal(":type")
        + SkipTo(":").setResultsName("name")
        + Literal(":")
        + SkipTo(EOL).setResultsName("type_name")
    )

    rtype_definition = SOL + Literal(":rtype:") + SkipTo(EOL).setResultsName("type_name")

    returns_definition = (
        SOL
        + (Literal(":returns:") | Literal(":return:"))
        + SkipTo(EOL).setResultsName("description")
    )

    param_definition = (
        SOL
        + Literal(":param")
        + SkipTo(":").setResultsName("name")
        + Literal(":")
        + SkipTo(EOL).setResultsName("description")
        + EOL
        + Optional(indented_block)
    )

    response_structure = Literal("**Response Structure**") + line_indented

    typed_dict_key_line = (
        Literal("-")
        + White(ws=" \t")
        + Literal("**")
        + word.setResultsName("name")
        + Literal("**")
        + White(ws=" \t")
        + Literal("*(")
        + word.setResultsName("type_name")
        + Literal(")")
        + White(ws=" \t")
        + Literal("--*")
        + SkipTo(EOL).setResultsName("description")
        + EOL
    )

    type_line = (
        Literal("-")
        + White(ws=" \t")
        + Literal("*(")
        + word.setResultsName("type_name")
        + Literal(")")
        + White(ws=" \t")
        + Literal("--*")
        + SkipTo(EOL).setResultsName("description")
        + EOL
    )

    any_line <<= (typed_dict_key_line | type_line | line).setResultsName("line")

    @classmethod
    def fail_action(
        cls, _input_string: str, _chr_index: int, _source: str, error: BaseException
    ) -> None:
        """
        Check for input end.
        """
        if "found end of text" not in str(error):
            raise error

    @classmethod
    def reset(cls) -> None:
        """
        Reset call stack and packrat.
        """
        cls.disable_packrat()
        cls.indented_block.setFailAction(cls.fail_action)
        cls.indent_stack.clear()
        cls.indent_stack.append(1)

    @staticmethod
    def enable_packrat() -> None:
        """
        Enable packrat boost.
        """
        ParserElement.enablePackrat(cache_size_limit=128)

    @staticmethod
    def disable_packrat() -> None:
        """
        Disable packrat boost.
        """
        ParserElement.enablePackrat(cache_size_limit=None)
Esempio n. 18
0
conditionals = Forward()

conditional = Group(comparable_expression + comparison + comparable_expression) | \
              Group(lpar + conditionals + rpar)
              
conditionals << Optional(not_logic) + conditional + ZeroOrMore(binary_logic + conditional)

if_keyword = Literal('if')

if_statement = (if_keyword + conditionals).setParseAction(IfStatement)

option = Forward()

response_definition = text + lineEnd.suppress() + Optional(if_statement + Literal('then').suppress())
response = (response_definition + ZeroOrMore(indentedBlock(option, indentStack, True))).setParseAction(Response)

event_send = Literal('->')
event_message_separator = Literal('!').suppress()

event_atom = atom.copy().setParseAction(lambda t: repr(t[0]))
event_message = quotedString | event_atom
event_send_separator = Literal(',').suppress()
event_statement = (event_send + event_atom + event_message_separator + event_message).setParseAction(Event)

options_delimiter =  Literal('~')
options_definition = options_delimiter + text + Optional(event_statement + ZeroOrMore(event_send_separator + event_statement))

option << (options_definition + ZeroOrMore(indentedBlock(response, indentStack, True))).setParseAction(Option)

dialog_begin = Literal('begin').suppress() + Group(atom + Optional(Literal('extends').suppress() + atom))
Esempio n. 19
0
interface_id = Word(alphanums + ":")

#TODO: make function to return thesline_ip_addresse
password = "******" + word_param
enable_password = "******" + word_param
banner_motd = "banner motd " + word_param("type") + restOfLine("path")

line_ip_address = "ip address" + ipAddressWithMask("ip")
line_description = "description" + restOfLine("description")
line_ip_ospf_cost = "ip ospf cost" + integer("cost")

interface_properties = OneOrMore(
    line_ip_address("ip address") | line_description("description")
    | line_ip_ospf_cost("ospf cost") | comment | hash_comment)

interface_indent = indentedBlock(interface_properties, indentStack,
                                 True)("indent")
interface_id = "interface" + interface_id("id")

interface = (interface_id +
             Optional(interface_indent)).setParseAction(fn_interface)
interfaces = OneOrMore(
    interface.setResultsName("interface", listAllMatches=True))

#### BGP
#TODO: put each protocol stanza into a function - variable scope, etc
router_bgp = "router bgp" + integer("asn")

#TODO: can router-id be an integer too?

#false_no: returns False if "no" is present, otherwise returns True
false_no = Optional(Literal("no").setParseAction(lambda x: False),
Esempio n. 20
0
from pyparsing import (indentedBlock, Regex, Suppress, Group, Optional,
                       OneOrMore, restOfLine, Forward, Literal,
                       ParserElement, Combine, StringEnd, 
                       ParseResults)
 
ParserElement.setDefaultWhitespaceChars(' \t')
 
#COLON = Suppress(Literal(':'))
#label = Suppress(Literal('-')) + Group(OneOrMore(Regex(r'\w+'))) + COLON
label = Group(OneOrMore(Regex(r'\S+')))
nonWhite = Regex(r'\S+')
value = Combine(nonWhite + restOfLine)
item = Forward()
indentStack = [1]
item << (label + Optional(value) +
         Optional(indentedBlock(item, indentStack, True)))
 
parser = OneOrMore(indentedBlock(item, indentStack, False)) + StringEnd()
###

single_top = '''
a
  a1
    a11
      a111?
      a112fdsafdsafd fdsa fdsafdsafdsa fdsafdsa fdsa fdsa fsdafdsa
      a113
    a12
    a13
  a2
  a3
Esempio n. 21
0
attribute = Word(alphanums + '_-')
value = (Word(alphanums+ '._-') ^ QuotedString('"'))

command = oneOf('Resource Attr Replace Apply SetCache Set Rule Insert Compose Copy Debug Literal Defmac Fetch Script Deliver Prerequisite Modify')
named_command = command + Optional(value)
command_property  = Group(attribute + colon + value)

def printCommandName(parse_string, location, matched_tokens_list):
    import time
    print 'COMMAND (%s):' % str(time.clock()), matched_tokens_list

# This recursive statement form taken from http://w3facility.info/question/simple-demonstration-of-using-pyparsings-indentedblock-recursively/
statement = ((command + newline) ^ (command + arrow) ^ (named_command + arrow)) + ZeroOrMore(command_property)
statement.setParseAction(printCommandName)
statementBlock = Forward()
statementBlock << statement + Optional(indentedBlock(statementBlock, [1]))

if __name__ == '__main__':
    from pyparsing import *
    import pprint
    import sys

    #statement.setDebug(True)

    FILE = sys.argv[1]
    for i, l in enumerate(file(FILE).read().split('\n')):
        print i+1, l
    parseTree = statementBlock.parseFile(FILE)
    print '\n'
    pprint.pprint(parseTree.asList())
Esempio n. 22
0
)
named_command = command + Optional(value)
command_property = Group(attribute + colon + value)


def printCommandName(parse_string, location, matched_tokens_list):
    import time
    print 'COMMAND (%s):' % str(time.clock()), matched_tokens_list


# This recursive statement form taken from http://w3facility.info/question/simple-demonstration-of-using-pyparsings-indentedblock-recursively/
statement = ((command + newline) ^ (command + arrow) ^
             (named_command + arrow)) + ZeroOrMore(command_property)
statement.setParseAction(printCommandName)
statementBlock = Forward()
statementBlock << statement + Optional(indentedBlock(statementBlock, [1]))

if __name__ == '__main__':
    from pyparsing import *
    import pprint
    import sys

    #statement.setDebug(True)

    FILE = sys.argv[1]
    for i, l in enumerate(file(FILE).read().split('\n')):
        print i + 1, l
    parseTree = statementBlock.parseFile(FILE)
    print '\n'
    pprint.pprint(parseTree.asList())
Esempio n. 23
0
File: gen.py Progetto: becketta/ctip
 def _get_parser():
     """
     Create parser for genfile using pyparsing library.
     
     Returns:
         Parser capable of turning a genfile into a consumable ParseResults object.
     """
     
     def strip_quotes(orig, loc, toks):
         """Strip quotation marks from the end of a string if present."""
         s = toks[0]
         if len(s) > 1:
             if (s[0] == '"' and s[-1] == '"') or (s[0] == "'" and s[-1] == "'"):
                 s = s[1:-1]
         return s
         
     ########## Define important literals ############
         
     pound = p.Literal("#")
     point = p.Literal(".")
     comma = p.Literal(",")
     e     = p.CaselessLiteral("E")
     colon = p.Literal(":").suppress()
     white = p.White(" \t\r")
     endl  = p.LineEnd().suppress()
     plus  = p.Literal("+")
     minus = p.Literal("-")
     nums  = p.Word(p.nums)
         
     ######### Define important constructs ###########
     
     # Define comment structure    
     comment = pound + p.restOfLine
         
     # non-quoted string
     non_quoted_token = p.Word(p.printables, excludeChars="#,")
     non_quoted_token += p.Optional(~endl + white + ~p.FollowedBy(comma|pound|endl))
     non_quoted = p.Combine(p.OneOrMore(non_quoted_token))
     
     # quoted string                        
     quote = (p.QuotedString('"', escChar="\\") | p.QuotedString("'", escChar="\\"))
     quote.addParseAction(strip_quotes)
     
     # integer
     integer = p.Word("+-"+p.nums, p.nums)
     integer.setParseAction( lambda s,l,t: int(t[0]) )
     
     # floating point number
     fpoint = p.Combine( p.Optional(plus|minus) + p.Optional(nums) +
                             point + nums + p.Optional( e + integer ) )
     fpoint.setParseAction( lambda s,l,t: float(t[0]) )
     
     # Any number
     number = (fpoint | integer)
     
     # range specification
     range_spec = number + colon + number + p.Optional(colon + number)
     range_spec.addParseAction( lambda s,l,t: [tuple(t)] )
     
     ######### Define grammar #########################
      
     # Indent stack needed for the pyparsing indentBlock function
     indent_stack = [1]
     # Statement used for recursive definition of genfile grammar
     stmt = p.Forward()
 
     # Variable names must start with a letter and can include
     # numbers, dashes, underscores, and periods.
     variable = p.Word(p.alphas, p.alphanums + "-_.")
     
     # Comma separated list of values
     value = (range_spec | number | quote | non_quoted)
     values = p.delimitedList(value)
 
     # Variable domain/scope:
     #       variable = val1, val2, val3 ...
     scope = variable("var") + p.Suppress("=") + p.Group(values)("values")
     
     # Dependencies are variable domains nested beneath another scope
     deps = p.indentedBlock(stmt, indent_stack)
     
     # A suite is a variable scope along with all of its dependencies
     suite = scope + p.Optional(deps("deps"))
     stmt << suite
     
     # A gen schema is one or more suites of variables
     genschema = p.OneOrMore(p.Group(suite))
     
     # A genfile starts with an optional schema name then defines a gen schema
     genfile = p.Optional(variable("name") + p.FollowedBy(p.lineEnd)) + genschema("schema")
     # Ignore comments in genfile
     genfile.ignore(comment)
     
     return genfile
Esempio n. 24
0
 def buildSyntax(self):
     '''WIP'''
     dreamScript = pyp.Forward()
     
     # Constants
     singlelineString = pyp.QuotedString('"', '\\').setResultsName('string').setParseAction(self.makeString)
     fileRef = pyp.QuotedString("'", '\\').setResultsName('fileRef').setParseAction(self.makeFileRef)
     multilineString = pyp.QuotedString(quoteChar='{"', endQuoteChar='"}', multiline=True).setResultsName('string').setParseAction(self.makeString)
     number = pyp.Regex(r'\d+(\.\d*)?([eE]\d+)?').setResultsName('number').setParseAction(self.makeNumber)
     
     # Other symbols
     listStart = pyp.Suppress('list(')
     listEnd = pyp.Suppress(')')
     
     VAR_GLOBAL = pyp.Keyword('global')
     VAR_CONST = pyp.Keyword('const')
     SLASH = pyp.Literal('/')
     EQUAL = pyp.Literal('=')
     VAR = pyp.Keyword('var')
     
     #############################
     # Grammar
     #############################
     
     constant = singlelineString | fileRef | multilineString | number | dreamList
     
     #  Lists
     listElement = constant | (constant + EQUAL + constant)
     listElement = pyp.operatorPrecedence(listElement, [
                             ("=", 2, pyp.opAssoc.LEFT,),
                             ])
     listContents = pyp.delimitedList(listElement)
     dreamList << pyp.Group(listStart + listContents + listEnd)
     dreamList.setParseAction(self.handleList)
     
     #  Paths
     relpath = pyp.ident | relpath + SLASH + pyp.ident
     abspath = SLASH + relpath
     path = (abspath | relpath).setParseAction(self.handlePath)
     pathslash = path + SLASH
     
     #  Preprocessor stuff
     ppStatement = pyp.Forward()
     
     ppDefine = pyp.Keyword('#define') + pyp.ident.setResultsName('name') + pyp.restOfLine.setResultsName('value')
     ppDefine.setParseAction(self.handlePPDefine)
     ppUndef = pyp.Keyword('#undef') + pyp.ident.setResultsName('name')
     ppUndef.setParseAction(self.handlePPUndef)
     
     ppIfdef = (pyp.Keyword('#ifdef') + pyp.ident.setResultsName('name')).setParseAction(self.handlePPIfdef)
     ppIfndef = (pyp.Keyword('#ifndef') + pyp.ident.setResultsName('name')).setParseAction(self.handlePPIfndef)
     ppElse = (pyp.Keyword('#else') + pyp.ident.setResultsName('name')).setParseAction(self.handlePPElse)
     ppEndif = pyp.Keyword('#endif').setParseAction(self.handlePPElse)
     
     ppStatement = pyp.lineStart + (ppIfdef | ppIfndef | ppElse | ppEndif)
     
     # Var Declarations
     ##########################
     var_modifiers = pyp.ZeroOrMore(SLASH + (VAR_GLOBAL | VAR_CONST)).setResultsName('modifiers')
     var_assignment = EQUAL + constant
     varblock_inner_ref = pyp.ident.setResultsName('name') + pyp.Optional(var_assignment)
     var_argument = VAR + pyp.Optional(abspath) + SLASH + pyp.ident.setResultsName('name') + pyp.Optional(var_assignment)
     varblock_inner_decl = var_modifiers + pyp.Optional(abspath) + SLASH + varblock_inner_ref
     varblock_element = varblock_inner_decl | varblock_inner_ref
     varblock = VAR + pyp.indentedBlock(var_blockinner_decl)
     inline_vardecl = VAR + varblock_inner_decl
     vardecl = varblock | inline_vardecl
     
     # Proc Declarations
     PROC = pyp.Keyword('proc')
     proc_args = '(' + pyp.delimitedList(var_argument | pyp.ident.setResultsName('name')) + ')'
     procblock_proc = pyp.ident.setResultsName('name') + proc_args + pyp.indentedBlock(proc_instructions)
     procblock = PROC + pyp.indentedBlock(procblock_proc, [1])
     
     # Atom blocks
     atomdecl = pyp.Forward()
     atomdecl << path + pyp.indentedBlock(vardecl | atomdecl | procdecl , [1])
     
     
     return dreamScript
Esempio n. 25
0
import pyparsing as pp
version = pp.__version__

W = pp.Keyword
S = pp.Suppress
SW = lambda kw: S(W(kw))
Group = pp.Group        # pylint: disable=invalid-name
Optional = pp.Optional  # pylint: disable=invalid-name
LineNum = pp.lineno     # pylint: disable=invalid-name


# Grammar for Python Type Declaration (CLIF version)

_indentation_stack = [1]  # Holds cols to indent from.
BLOCK = lambda el: S(':') + NEWLINE - pp.indentedBlock(el, _indentation_stack)


def reset_indentation():  # pylint: disable=invalid-name
  _indentation_stack[:] = [1]

K = lambda el: pp.Keyword(el).setParseAction(lambda el, loc, t: [t[0], loc])
E = lambda el: pp.Empty().setParseAction(lambda: el)
Tag = lambda el: pp.Empty().setParseAction(lambda s, loc, t: [el, loc])  # pylint: disable=invalid-name
NEWLINE = pp.lineEnd.setWhitespaceChars(' ').suppress().ignore(
    pp.pythonStyleComment)


def PARENS(el):           # pylint: disable=invalid-name
  el.ignore(pp.pythonStyleComment)
  return S('(') - el - S(')')
Esempio n. 26
0
banner_motd = "banner motd " + word_param("type") + restOfLine("path")


line_ip_address = "ip address" + ipAddressWithMask("ip")
line_description = "description" + restOfLine("description")
line_ip_ospf_cost = "ip ospf cost" + integer("cost")

interface_properties = OneOrMore(
    line_ip_address("ip address") |
    line_description("description") |
    line_ip_ospf_cost("ospf cost") |
    comment|
    hash_comment
    )

interface_indent = indentedBlock(interface_properties, indentStack, True)("indent")
interface_id = "interface" + interface_id("id")

interface = ( interface_id + Optional(interface_indent)).setParseAction(fn_interface)
interfaces = OneOrMore(interface.setResultsName("interface", listAllMatches=True))


#### BGP
#TODO: put each protocol stanza into a function - variable scope, etc
router_bgp = "router bgp" + integer("asn")

#TODO: can router-id be an integer too?

#false_no: returns False if "no" is present, otherwise returns True
false_no = Optional(Literal("no").setParseAction(lambda x: False), default = True)
#bgp_synchronization = Optional(false_no, default =True) + "synchronization"