Exemple #1
0
def _generate_grammar(*, debug_parser: bool = False):
    pp.ParserElement.setDefaultWhitespaceChars(" \t")

    EOL = pp.Optional(pp.pythonStyleComment()) + pp.LineEnd()
    LC = pp.Suppress(pp.OneOrMore(EOL) + pp.White(ws=" \t", min=4))

    Identifier = pp.Word(initChars=pp.alphas, bodyChars=pp.alphanums + "_-")

    MultilineArgument = pp.QuotedString(
        quoteChar="<<<<", endQuoteChar=">>>>", multiline=True
    )
    SingleQuotedArgument = pp.QuotedString(quoteChar="'", escChar="\\")
    DoubleQuotedArgument = pp.QuotedString(quoteChar='"', escChar="\\")
    QuotedArgument = (SingleQuotedArgument | DoubleQuotedArgument | MultilineArgument)(
        "quoted"
    )
    SimpleArgument = pp.Word(pp.alphanums + "_-+*!$%&/()[]{}.,;:")("simple")
    Argument = (QuotedArgument | SimpleArgument) + pp.Optional(LC)

    KwArgument = pp.Combine(Identifier("key") + "=" + Argument)

    ArgumentList = pp.Group(pp.ZeroOrMore(pp.Group(KwArgument | Argument)))

    Command = (
        pp.locatedExpr(Identifier)("command") + pp.Optional(LC) + ArgumentList("args")
    )

    Grammar = pp.ZeroOrMore(pp.Group(pp.Optional(Command) + pp.Suppress(EOL)))

    if debug_parser:
        for expr_name in (
            "Grammar Command ArgumentList KwArgument Argument "
            "SimpleArgument QuotedArgument DoubleQuotedArgument "
            "SingleQuotedArgument MultilineArgument "
            "Identifier LC EOL".split()
        ):
            expr = locals()[expr_name]
            expr.setName(expr_name)
            expr.setDebug()

    Grammar.parseWithTabs()  # Keep tabs unexpanded!
    return Grammar
Exemple #2
0
def _generate_grammar(*, debug_parser: bool = False):
    pp.ParserElement.setDefaultWhitespaceChars(' \t')

    EOL = pp.Optional(pp.pythonStyleComment()) + pp.LineEnd()
    LC = pp.Suppress(pp.OneOrMore(EOL) + pp.White(ws=' \t', min=4))

    Identifier = pp.Word(initChars=pp.alphas, bodyChars=pp.alphanums + '_-')
    
    MultilineArgument = pp.QuotedString(quoteChar = '<<<<',
                                        endQuoteChar = '>>>>', multiline=True)
    SingleQuotedArgument = pp.QuotedString(quoteChar = '\'', escChar = '\\')
    DoubleQuotedArgument = pp.QuotedString(quoteChar = '"', escChar = '\\')
    QuotedArgument = (SingleQuotedArgument | DoubleQuotedArgument |
                      MultilineArgument)('quoted')
    SimpleArgument = pp.Word(pp.alphanums + '_-+*!$%&/()[]{}.,;:')('simple')
    Argument = (QuotedArgument | SimpleArgument) + pp.Optional(LC)

    KwArgument = pp.Combine(Identifier('key') + '=' + Argument)

    ArgumentList = pp.Group(pp.ZeroOrMore(pp.Group(KwArgument | Argument)))

    Command = pp.locatedExpr(Identifier)('command') + pp.Optional(LC) \
              + ArgumentList('args')

    Grammar = pp.ZeroOrMore(pp.Group(pp.Optional(Command) + pp.Suppress(EOL)))

    if debug_parser:
        for ename in 'Grammar Command ArgumentList KwArgument Argument ' \
                     'SimpleArgument QuotedArgument DoubleQuotedArgument ' \
                     'SingleQuotedArgument MultilineArgument ' \
                     'Identifier LC EOL'.split():
            expr = locals()[ename]
            expr.setName(ename)
            expr.setDebug()

    Grammar.parseWithTabs()  # Keep tabs unexpanded!
    return Grammar
Exemple #3
0
    def _generate_grammar(self):
        # Define grammar:
        pp.ParserElement.setDefaultWhitespaceChars(" \t")

        def add_element(name: str, value: pp.ParserElement):
            nonlocal self
            if self.debug:
                value.setName(name)
                value.setDebug()
            return value

        EOL = add_element("EOL", pp.Suppress(pp.LineEnd()))
        Else = add_element("Else", pp.Keyword("else"))
        Identifier = add_element(
            "Identifier",
            pp.Word(f"{pp.alphas}_", bodyChars=pp.alphanums + "_-./"))
        BracedValue = add_element(
            "BracedValue",
            pp.nestedExpr(ignoreExpr=pp.quotedString
                          | pp.QuotedString(quoteChar="$(",
                                            endQuoteChar=")",
                                            escQuote="\\",
                                            unquoteResults=False)).
            setParseAction(lambda s, l, t: ["(", *t[0], ")"]),
        )

        Substitution = add_element(
            "Substitution",
            pp.Combine(
                pp.Literal("$") +
                (((pp.Literal("$") + Identifier + pp.Optional(pp.nestedExpr()))
                  | (pp.Literal("(") + Identifier + pp.Literal(")"))
                  | (pp.Literal("{") + Identifier + pp.Literal("}"))
                  | (pp.Literal("$") + pp.Literal("{") + Identifier +
                     pp.Optional(pp.nestedExpr()) + pp.Literal("}"))
                  | (pp.Literal("$") + pp.Literal("[") + Identifier +
                     pp.Literal("]"))))),
        )
        LiteralValuePart = add_element(
            "LiteralValuePart", pp.Word(pp.printables, excludeChars="$#{}()"))
        SubstitutionValue = add_element(
            "SubstitutionValue",
            pp.Combine(
                pp.OneOrMore(Substitution | LiteralValuePart
                             | pp.Literal("$"))),
        )
        FunctionValue = add_element(
            "FunctionValue",
            pp.Group(
                pp.Suppress(pp.Literal("$") + pp.Literal("$")) + Identifier +
                pp.nestedExpr(
                )  # .setParseAction(lambda s, l, t: ['(', *t[0], ')'])
            ).setParseAction(lambda s, l, t: handle_function_value(*t)),
        )
        Value = add_element(
            "Value",
            pp.NotAny(Else | pp.Literal("}") | EOL) +
            (pp.QuotedString(quoteChar='"', escChar="\\")
             | FunctionValue
             | SubstitutionValue
             | BracedValue),
        )

        Values = add_element("Values", pp.ZeroOrMore(Value)("value"))

        Op = add_element(
            "OP",
            pp.Literal("=")
            | pp.Literal("-=")
            | pp.Literal("+=")
            | pp.Literal("*=")
            | pp.Literal("~="),
        )

        Key = add_element("Key", Identifier)

        Operation = add_element(
            "Operation",
            Key("key") + pp.locatedExpr(Op)("operation") + Values("value"))
        CallArgs = add_element("CallArgs", pp.nestedExpr())

        def parse_call_args(results):
            out = ""
            for item in chain(*results):
                if isinstance(item, str):
                    out += item
                else:
                    out += "(" + parse_call_args(item) + ")"
            return out

        CallArgs.setParseAction(parse_call_args)

        Load = add_element("Load", pp.Keyword("load") + CallArgs("loaded"))
        Include = add_element(
            "Include",
            pp.Keyword("include") + pp.locatedExpr(CallArgs)("included"))
        Option = add_element("Option",
                             pp.Keyword("option") + CallArgs("option"))
        RequiresCondition = add_element("RequiresCondition",
                                        pp.originalTextFor(pp.nestedExpr()))

        def parse_requires_condition(s, l_unused, t):
            # The following expression unwraps the condition via the additional info
            # set by originalTextFor.
            condition_without_parentheses = s[t._original_start +
                                              1:t._original_end - 1]

            # And this replaces the colons with '&&' similar how it's done for 'Condition'.
            condition_without_parentheses = (
                condition_without_parentheses.strip().replace(
                    ":", " && ").strip(" && "))
            return condition_without_parentheses

        RequiresCondition.setParseAction(parse_requires_condition)
        Requires = add_element(
            "Requires",
            pp.Keyword("requires") +
            RequiresCondition("project_required_condition"))

        FunctionArgumentsAsString = add_element(
            "FunctionArgumentsAsString", pp.originalTextFor(pp.nestedExpr()))
        QtNoMakeTools = add_element(
            "QtNoMakeTools",
            pp.Keyword("qtNomakeTools") +
            FunctionArgumentsAsString("qt_no_make_tools_arguments"),
        )

        # ignore the whole thing...
        DefineTestDefinition = add_element(
            "DefineTestDefinition",
            pp.Suppress(
                pp.Keyword("defineTest") + CallArgs +
                pp.nestedExpr(opener="{", closer="}", ignoreExpr=pp.LineEnd())
            ),
        )

        # ignore the whole thing...
        ForLoop = add_element(
            "ForLoop",
            pp.Suppress(
                pp.Keyword("for") + CallArgs +
                pp.nestedExpr(opener="{", closer="}", ignoreExpr=pp.LineEnd())
            ),
        )

        # ignore the whole thing...
        ForLoopSingleLine = add_element(
            "ForLoopSingleLine",
            pp.Suppress(
                pp.Keyword("for") + CallArgs + pp.Literal(":") +
                pp.SkipTo(EOL)),
        )

        # ignore the whole thing...
        FunctionCall = add_element("FunctionCall",
                                   pp.Suppress(Identifier + pp.nestedExpr()))

        Scope = add_element("Scope", pp.Forward())

        Statement = add_element(
            "Statement",
            pp.Group(Load
                     | Include
                     | Option
                     | Requires
                     | QtNoMakeTools
                     | ForLoop
                     | ForLoopSingleLine
                     | DefineTestDefinition
                     | FunctionCall
                     | Operation),
        )
        StatementLine = add_element("StatementLine",
                                    Statement + (EOL | pp.FollowedBy("}")))
        StatementGroup = add_element(
            "StatementGroup",
            pp.ZeroOrMore(StatementLine | Scope | pp.Suppress(EOL)))

        Block = add_element(
            "Block",
            pp.Suppress("{") + pp.Optional(EOL) + StatementGroup +
            pp.Optional(EOL) + pp.Suppress("}") + pp.Optional(EOL),
        )

        ConditionEnd = add_element(
            "ConditionEnd",
            pp.FollowedBy(
                (pp.Optional(pp.White()) +
                 (pp.Literal(":") | pp.Literal("{") | pp.Literal("|")))),
        )

        ConditionPart1 = add_element(
            "ConditionPart1",
            (pp.Optional("!") + Identifier + pp.Optional(BracedValue)))
        ConditionPart2 = add_element("ConditionPart2",
                                     pp.CharsNotIn("#{}|:=\\\n"))
        ConditionPart = add_element(
            "ConditionPart", (ConditionPart1 ^ ConditionPart2) + ConditionEnd)

        ConditionOp = add_element("ConditionOp",
                                  pp.Literal("|") ^ pp.Literal(":"))
        ConditionWhiteSpace = add_element(
            "ConditionWhiteSpace", pp.Suppress(pp.Optional(pp.White(" "))))

        ConditionRepeated = add_element(
            "ConditionRepeated",
            pp.ZeroOrMore(ConditionOp + ConditionWhiteSpace + ConditionPart))

        Condition = add_element("Condition",
                                pp.Combine(ConditionPart + ConditionRepeated))
        Condition.setParseAction(
            lambda x: " ".join(x).strip().replace(":", " && ").strip(" && "))

        # Weird thing like write_file(a)|error() where error() is the alternative condition
        # which happens to be a function call. In this case there is no scope, but our code expects
        # a scope with a list of statements, so create a fake empty statement.
        ConditionEndingInFunctionCall = add_element(
            "ConditionEndingInFunctionCall",
            pp.Suppress(ConditionOp) + FunctionCall +
            pp.Empty().setParseAction(lambda x: [[]]).setResultsName(
                "statements"),
        )

        SingleLineScope = add_element(
            "SingleLineScope",
            pp.Suppress(pp.Literal(":")) +
            pp.Group(Block | (Statement + EOL))("statements"),
        )
        MultiLineScope = add_element("MultiLineScope", Block("statements"))

        SingleLineElse = add_element(
            "SingleLineElse",
            pp.Suppress(pp.Literal(":")) + (Scope | Block |
                                            (Statement + pp.Optional(EOL))),
        )
        MultiLineElse = add_element("MultiLineElse", Block)
        ElseBranch = add_element(
            "ElseBranch",
            pp.Suppress(Else) + (SingleLineElse | MultiLineElse))

        # Scope is already add_element'ed in the forward declaration above.
        Scope <<= pp.Group(
            Condition("condition") + (SingleLineScope | MultiLineScope
                                      | ConditionEndingInFunctionCall) +
            pp.Optional(ElseBranch)("else_statements"))

        Grammar = StatementGroup("statements")
        Grammar.ignore(pp.pythonStyleComment())

        return Grammar
Exemple #4
0
    Keyword("and"),
    Keyword("or"),
    Keyword("xor"),
    Keyword("lsh"),
    Keyword("rsh"),
    Keyword("ja"),
    Keyword("ret"),
    Keyword("tax"),
    Keyword("txa"),
])

JUMP_OP = MatchFirst([
    Keyword("jeq"),
    Keyword("jneq"),
    Keyword("jne"),
    Keyword("jlt"),
    Keyword("jle"),
    Keyword("jgt"),
    Keyword("jge"),
    Keyword("jset"),
])

STATEMENT = Group(STATEMENT_OP('op') + ADDRESS('val'))('statement')
TARGET = Suppress(',') + ADDRESS
JUMP = Group(
    JUMP_OP('op') + ADDRESS('val') + TARGET('true') +
    Optional(TARGET)('false'))('jump')

TOKEN = Group(STATEMENT ^ JUMP ^ Group(pythonStyleComment('comment')))
PROGRAM = ZeroOrMore(TOKEN)