Exemple #1
0
def comma_list(self, start):
    """
Iterate over a comma separated list

Args:
    self (Builder): Code constructor
    start (int): Current position in code

Returns:
    list : A list of 2-tuples that represents index start and end for each
    expression in list
    """

    if  self.code[start] not in c.l_start:
        self.syntaxerror(start, "list start")
    k = start+1

    while self.code[k] in " \t":
        k += 1

    if self.code[k] in "]}":
        return [[]]

    out = [[]]
    count = False

    while True:

        if self.code[k:k+3] == "...":
            k = findend.dots(self, k)

        elif self.code[k] in c.e_start:

            if count:
                self.syntaxerror(k, "comma list indicator")

            count = True
            end = findend.expression(self, k)
            out[-1].append((k, end))

            k = end

        elif self.code[k] == ",":

            if not count:
                self.syntaxerror(k, "comma list indicator")

            count = False

        elif self.code[k] == ";":

            if not count:
                self.syntaxerror(k, "comma list indicator")

            count = False
            out.append([])

        elif self.code[k] in c.l_end:
            return out

        k += 1
Exemple #2
0
def whileloop(self, parent, cur):
    '''
While loop

Args:
    self (Builder): Code constructor.
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int: Index to end of code block

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed",
    ... """while a
    ...   b
    ... end""")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   While         branches.whileloop   'while a'
       6     Expression  expression.create    'a'
       6     Var         variables.variable   'a'
      10 Codeblock   codeblock.codeblock 
      10   Statement     codeblock.codeblock  'b'
      10     Expression  expression.create    'b'
      10     Var         variables.variable   'b'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Block      code_block   TYPE
    1  1| While      code_block   TYPE
    1  7| | Var        unknown      TYPE    a
    2 11| | Block      code_block   TYPE
    2 11| | | Statement  code_block   TYPE
    2 11| | | | Var        unknown      TYPE    b
    '''

    if  self.code[cur:cur+5] != "while" and self.code[cur+5] not in c.k_end:
        self.syntaxerror(cur, "start of while-loop")
    start = cur

    k = cur+5
    while self.code[k] in " \t":
        k += 1

    end = findend.expression(self, k)

    if self.disp:
        print "%4d   While        " % cur,
        print "%-20s" % "branches.whileloop",
        print repr(self.code[cur:end+1])

    whileloop = mc.collection.While(parent, cur=cur)

    if self.code[k] == "(":
        k += 1
        while self.code[k] in " \t":
            k += 1

    cur = self.create_expression(whileloop, k)
    cur += 1

    cur += 1
    while self.code[cur] in " \t":
        cur += 1

    end = self.create_codeblock(whileloop, cur)

    whileloop.code = self.code[start:end+1]

    return end
Exemple #3
0
def ifbranch(self, parent, start):
    '''
If-ifelse-else branch

Args:
    self (Builder): Code constructor.
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int: Index to end of code block

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed",
    ... """if a
    ...   b
    ... elseif c
    ...   d
    ... end""")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   If            branches.ifbranch    'if a'
       3     Expression  expression.create    'a'
       3     Var         variables.variable   'a'
       4 Codeblock   codeblock.codeblock 
       7   Statement     codeblock.codeblock  'b'
       7     Expression  expression.create    'b'
       7     Var         variables.variable   'b'
       9   Else if       branches.ifbranch    'elseif c'
      16     Expression  expression.create    'c'
      16     Var         variables.variable   'c'
      17 Codeblock   codeblock.codeblock 
      20   Statement     codeblock.codeblock  'd'
      20     Expression  expression.create    'd'
      20     Var         variables.variable   'd'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Block      code_block   TYPE
    1  1| Branch     code_block   TYPE
    1  4| | If         code_block   TYPE
    1  4| | | Var        unknown      TYPE    a
    1  5| | | Block      code_block   TYPE
    2  8| | | | Statement  code_block   TYPE
    2  8| | | | | Var        unknown      TYPE    b
    3 10| | Elif       code_block   TYPE
    3 17| | | Var        unknown      TYPE    c
    3 18| | | Block      code_block   TYPE
    4 21| | | | Statement  code_block   TYPE
    4 21| | | | | Var        unknown      TYPE    d
    '''

    if  self.code[start:start+2] != "if" or self.code[start+2] not in c.k_end:
        self.syntaxerror(start, "if branch start")

    branch = mc.collection.Branch(parent, cur=start)

    cur = start

    cur += 2
    while self.code[cur] in " \t":
        cur += 1

    if  self.code[cur] not in c.e_start:
        self.syntaxerror(cur, "expression start")

    end = findend.expression(self, cur)

    if self.disp:
        print "%4d   If           " % (start),
        print "%-20s" % "branches.ifbranch",
        print repr(self.code[start:end+1])

    node = mc.collection.If(branch, cur=cur)

    if self.code[cur] == "(":
        cur += 1
        while self.code[cur] in " \t":
            cur += 1
    self.create_expression(node, cur)

    cur = end+1

    end = self.create_codeblock(node, cur)
    node.code = self.code[cur:end]
    cur = end

    while self.code[cur:cur+6] == "elseif" and self.code[cur+6] in c.k_end:

        node.code = self.code[start:cur]
        start = cur

        cur += 6
        while self.code[cur] in " \t":
            cur += 1

        end = findend.expression(self, cur)

        if self.disp:
            print "%4d   Else if      " % (start),
            print "%-20s" % "branches.ifbranch",
            print repr(self.code[start:end+1])

        node = mc.collection.Elif(branch, cur=start)

        if self.code[cur] == "(":
            cur += 1
            while self.code[cur] in " \t":
                cur += 1

        self.create_expression(node, cur)
        cur = end+1

        cur = end = self.create_codeblock(node, cur)


    cur = end
    node.code = self.code[start:cur]

    if self.code[cur:cur+4] == "else" and self.code[cur+4] in c.k_end:

        start = cur

        cur += 4

        if self.disp:
            print "%4d   Else         " % (start),
            print "%-20s" % "branches.ifbranch",
            print repr(self.code[start:start+5])

        node = mc.collection.Else(branch, cur=start)

        end = self.create_codeblock(node, cur)
        node.code = self.code[start:end+1]

    branch.code = self.code[start:end+1]

    return end
Exemple #4
0
def create(self, node, start, end=None, start_opr=None):
    """
Create expression in three steps:

    1) In order, split into sub-expressions for each dividing operator
    2) Address prefixes, postfixes, parenthesises, etc.
    3) Identify the remaining singleton

Args:
    self (Builder): Code constructor.
    node (Node): Reference to the parent node
    start (int): current possition in code
    end (int, optional): end of expression. Required for space-delimited expression.
    start_opr (str, optional): At which operator the recursive process is. (For internal use)

Returns:
	int : index to end of the expression

Examples::

    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a*b+c/d")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Statement     codeblock.codeblock  'a*b+c/d'
       0     Expression  expression.create    'a*b+c/d'
       0     Expression  expression.create    'a*b'
       0     Expression  expression.create    'a'
       0     Var         variables.variable   'a'
       2     Expression  expression.create    'b'
       2     Var         variables.variable   'b'
       4     Expression  expression.create    'c/d'
       4     Expression  expression.create    'c'
       4     Var         variables.variable   'c'
       6     Expression  expression.create    'd'
       6     Var         variables.variable   'd'
    >>> builder.configure(suggest=False)
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1 1Block      code_block   TYPE
    1 1| Statement  code_block   TYPE
    1 1| | Plus       expression   TYPE
    1 1| | | Mul        expression   TYPE
    1 1| | | | Var        unknown      TYPE    a
    1 3| | | | Var        unknown      TYPE    b
    1 5| | | Matrixdivisionexpression   TYPE
    1 5| | | | Var        unknown      TYPE    c
    1 7| | | | Var        unknown      TYPE    d
    """

    if self.code[start:start + 3] == "...":
        start = findend.dots(self, start)
        start += 1
        while self.code[start] in " \t":
            start += 1

    if self.code[start] == ":":

        if self.disp:

            print "%4d     Expression " % (start),
            print "%-20s" % "expression.create",
            print repr(self.code[start:start + 1])

            print "%4d     All        " % (start),
            print "%-20s" % "expression.create",
            print repr(self.code[start:start + 1])

        mc.collection.All(node, cur=start, code=self.code[start])
        return start

    if end is None:
        end = findend.expression(self, start)

    if self.disp:
        print "%4d     Expression " % (start),
        print "%-20s" % "expression.create",
        print repr(self.code[start:end + 1])

    if self.code[start] not in c.e_start:
        self.syntaxerror(start, "expression start")

    operators = [
        "||", "&&", "|", "&", "~=", "==", ">=", ">", "<=", "<", ":", "+", "-",
        ".*", "*", "./", "/", ".\\", "\\", ".^", "^"
    ]

    if not (start_opr is None):
        operators = operators[operators.index(start_opr) + 1:]

    for opr in operators:
        # Pre-screen
        if opr not in self.code[start:end + 1]:
            continue

        starts = [start]
        last = start
        ends = []

        k = start
        while True:

            if self.code[k] == "(":
                k = last = findend.paren(self, k)

            elif self.code[k] == "[":
                k = last = findend.matrix(self, k)

            elif self.code[k] == "{":
                k = last = findend.cell(self, k)

            elif self.code[k] == "'":
                if identify.string(self, k):
                    k = last = findend.string(self, k)
                else:
                    last = k

            elif opr == self.code[k:k + len(opr)]:

                if opr in "+-":
                    # no prefixes and no (scientific) numbers
                    if self.code[last] not in c.letters+c.digits+")]}" or\
                            self.code[k-1] in "dDeE" and self.code[k-2] in\
                            c.digits+"." and self.code[k+1] in c.digits:
                        k += 1
                        continue

                k += len(opr) - 1
                while self.code[k + 1] in " \t":
                    k += 1

                # no all-operator
                if opr == ":" and self.code[k + 1] in ",;\n)]}":
                    k += 1
                    continue

                starts.append(k + 1)
                ends.append(last)

            elif self.code[k] in c.letters + c.digits + "_":
                last = k

            k += 1
            if k >= end:
                ends.append(end)
                break

        if len(ends) > 1:

            node = retrieve_operator(self, opr)(node)
            node.cur = start
            node.code = self.code[starts[0]:ends[-1] + 1]

            for s, e in zip(starts, ends):
                create(self, node, s, e, opr)

            return end

    # All operators removed at this point!

    END = end

    # Prefixes
    while self.code[start] in "-~":

        if self.code[start] == "-":

            node = mc.collection.Neg(node,
                                     cur=start,
                                     code=self.code[start:end + 1])
            start += 1

        if self.code[start] == "~":

            node = mc.collection.Not(node,
                                     cur=start,
                                     code=self.code[start:end + 1])
            start += 1

        while self.code[start] in " \t":
            start += 1

    # Postfixes
    if self.code[end] == "'" and not self.code[start] == "'":
        if self.code[end - 1] == ".":
            node = mc.collection.Transpose(node,
                                           cur=start,
                                           code=self.code[start:end + 1])
            end -= 2
        else:
            node = mc.collection.Ctranspose(node,
                                            cur=start,
                                            code=self.code[start:end + 1])
            node.cur = start
            node.code = self.code[start:end + 1]
            end -= 1

        while self.code[end] in " \t":
            end -= 1

    # Parenthesis
    if self.code[start] == "(":
        if self.code[end] != ")":
            self.syntaxerror(end, "parenthesis end")

        node = mc.collection.Paren(node,
                                   cur=start,
                                   code=self.code[start:end + 1])

        start += 1
        while self.code[start] in " \t":
            start += 1

        end -= 1
        while self.code[end] in " \t":
            end -= 1

        return create(self, node, start, end)

    # Reserved keywords
    elif self.code[start:start +
                   3] == "end" and self.code[start + 3] in " +-:\t" + c.e_end:
        node = mc.collection.End(node,
                                 cur=start,
                                 code=self.code[start:start + 3])

    elif self.code[start:start + 6] == "return" and self.code[start +
                                                              6] in " ,;\n":
        node = mc.collection.Return(node,
                                    cur=start,
                                    code=self.code[start:start + 6])

    elif self.code[start:start + 5] == "break" and self.code[start +
                                                             5] in " ,;\n":
        node = mc.collection.Break(node,
                                   cur=start,
                                   code=self.code[start:start + 5])

    # Rest
    elif self.code[start] == "'":
        if self.code[end] != "'":
            self.syntaxerror(end, "string end")

        if "\n" in self.code[start:end]:
            self.syntaxerror(end, "non line-feed characters in string")

        mc.collection.String(node,
                             self.code[start + 1:end],
                             cur=start,
                             code=self.code[start:end + 1])

    elif self.code[start] in c.digits or\
            self.code[start] == "." and self.code[start+1] in c.digits:
        cur = self.create_number(node, start)

    elif self.code[start] == "[":
        cur = self.create_matrix(node, start)

    elif self.code[start] == "{":
        cur = self.create_cell(node, start)

    else:
        if self.code[start] not in c.letters + "@":
            self.syntaxerror(start, "variable name")

        cur = self.create_variable(node, start)

    return END
Exemple #5
0
def switch(self, parent, cur):
    '''
Switch-case branch

Args:
    self (Builder): Code constructor.
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int: Index to end of codeblock

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed",
    ... """switch a
    ... case b
    ...   c
    ... case d
    ...   d
    ... end""")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Switch        branches.switch      'switch a'
       7     Expression  expression.create    'a'
       7     Var         variables.variable   'a'
       9   Case          branches.switch      'case b'
      14     Expression  expression.create    'b'
      14     Var         variables.variable   'b'
      18 Codeblock   codeblock.codeblock 
      18   Statement     codeblock.codeblock  'c'
      18     Expression  expression.create    'c'
      18     Var         variables.variable   'c'
      20   Case          branches.switch      'case d'
      25     Expression  expression.create    'd'
      25     Var         variables.variable   'd'
      29 Codeblock   codeblock.codeblock 
      29   Statement     codeblock.codeblock  'd'
      29     Expression  expression.create    'd'
      29     Var         variables.variable   'd'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Block      code_block   TYPE
    1  1| Switch     code_block   TYPE
    1  8| | Var        unknown      TYPE    a
    2 10| | Case       code_block   TYPE
    2 15| | | Var        unknown      TYPE    b
    3 19| | | Block      code_block   TYPE
    3 19| | | | Statement  code_block   TYPE
    3 19| | | | | Var        unknown      TYPE    c
    4 21| | Case       code_block   TYPE
    4 26| | | Var        unknown      TYPE    d
    5 30| | | Block      code_block   TYPE
    5 30| | | | Statement  code_block   TYPE
    5 30| | | | | Var        unknown      TYPE    d
    '''

    if not (self.code[cur:cur+6] == "switch" and\
            self.code[cur+6] in " \t("):
        self.syntaxerror(cur, "start of switch branch")

    k = cur+6
    while self.code[k] in " \t":
        k += 1

    end = findend.expression(self, k)

    if self.disp:
        print "%4d   Switch       " % cur,
        print "%-20s" % "branches.switch",
        print repr(self.code[cur:end+1])

    switch = mc.collection.Switch(parent, cur=cur)

    self.create_expression(switch, k, end)

    k = end+1

    while self.code[k] in " \t\n;,":
        k += 1

    while self.code[k:k+4] == "case" and self.code[k+4] in " \t(":

        cur = k

        k += 4
        while self.code[k] in " \t":
            k += 1

        end = findend.expression(self, k)

        if self.disp:
            print "%4d   Case         " % cur,
            print "%-20s" % "branches.switch",
            print repr(self.code[cur:end+1])

        case = mc.collection.Case(switch, cur=cur)

        cur = self.create_expression(case, k, end)

        k = cur+1
        while self.code[k] in " \t;,\n":
            k += 1

        k = self.create_codeblock(case, k)

    if self.code[k:k+9] == "otherwise" and self.code[k+9] in " \t(,;\n":

        cur = k

        if self.disp:
            print "%4d   Otherwise    " % cur,
            print "%-20s" % "branches.switch",
            print repr(self.code[cur:cur+10])

        otherwise = mc.collection.Otherwise(switch, cur=cur)

        k += 9
        while self.code[k] in " \t\n;,":
            k += 1

        k = self.create_codeblock(otherwise, k)

    return k
Exemple #6
0
def codeblock(self, parent, start):
    '''
If-ifelse-else branch

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int: Index to end of codeblock

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a; 'b'; 3")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Statement     codeblock.codeblock  'a'
       0     Expression  expression.create    'a'
       0     Var         variables.variable   'a'
       3   Statement     codeblock.codeblock  "'b'"
       3     String  misc.string          "'b'"
       8   Statement     codeblock.codeblock  '3'
       8     Expression  expression.create    '3'
       8     Int         misc.number          '3'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Block      code_block   TYPE
    1  1| Statement  code_block   TYPE
    1  1| | Var        unknown      TYPE    a
    1  4| Statement  code_block   TYPE
    1  4| | String     string       string
    1  9| Statement  code_block   TYPE
    1  9| | Int        int          int
    '''
    cur = start
    block = mc.collection.Block(parent, cur=cur)

    if self.disp:
        print "%4d Codeblock  " % cur,
        print "%-20s" % "codeblock.codeblock"

    is_end_terminated = False

    while True:
        #print self.code[cur:cur+5]
        if self.code[cur] in " \t;":
            pass

        elif self.code[cur] == "\n":
            if len(self.code) - cur < 3:
                break

        #%#PARFOR token
        elif self.code[cur:cur + 8] == "%#PARFOR":
            cur = self.create_pragma_parfor(block, cur)

        elif self.code[cur] == "%":
            cur = self.create_comment(block, cur)

        elif self.code[cur:cur + 3] == "___":
            cur = self.create_verbatim(block, cur)

        elif self.code[cur] == "[":
            # Divide between statement and assignment
            eq_loc = findend.matrix(self, cur) + 1

            while self.code[eq_loc] in " \t":
                eq_loc += 1

            if self.code[eq_loc] == "=" and self.code[eq_loc + 1] != "=":
                cur = self.create_assigns(block, cur, eq_loc)

            else:
                statement = mc.collection.Statement(block, cur=cur)

                end = findend.expression(self, cur)
                if self.disp:
                    print "%4d   Statement    " % cur,
                    print "%-20s" % "codeblock.codeblock",
                    print repr(self.code[cur:end + 1])

                statement.code = self.code[cur:end + 1]

                cur = self.create_expression(statement, cur, end=end)

        elif self.code[cur] == "'":
            end = findend.string(self, cur)
            if self.disp:
                print "%4d   Statement    " % cur,
                print "%-20s" % "codeblock.codeblock",
                print repr(self.code[cur:end + 1])

            statement = mc.collection.Statement(block,
                                                cur=cur,
                                                code=self.code[cur:end + 1])

            cur = self.create_string(statement, cur)

        elif self.code[cur:cur + 4] == "case" and self.code[cur +
                                                            4] in c.k_end:
            break

        elif self.code[cur:cur + 5] == "catch" and self.code[cur +
                                                             5] in c.k_end:
            break

        elif self.code[cur:cur + 3] == "end" and self.code[cur + 3] in c.k_end:
            cur += 3
            is_end_terminated = True
            break

        elif self.code[cur:cur + 4] == "else" and self.code[cur +
                                                            4] in c.k_end:
            break

        elif self.code[cur:cur + 6] == "elseif" and self.code[cur +
                                                              6] in c.k_end:
            break

        elif self.code[cur:cur + 6] == "parfor" and self.code[cur +
                                                              6] in c.k_end:
            cur = self.create_parfor(block, cur)

        elif self.code[cur:cur + 3] == "for" and self.code[cur + 3] in c.k_end:
            cur = self.create_for(block, cur)

        elif self.code[cur:cur+8] == "function" and\
                self.code[cur+8] in c.k_end + "[":
            cur -= 1
            break

        elif self.code[cur:cur + 2] == "if" and self.code[cur + 2] in c.k_end:
            cur = self.create_if(block, cur)

        elif self.code[cur:cur + 9] == "otherwise" and self.code[cur +
                                                                 9] in c.k_end:
            break

        elif self.code[cur:cur + 6] == "switch" and self.code[cur +
                                                              6] in c.k_end:
            cur = self.create_switch(block, cur)

        elif self.code[cur:cur + 3] == "try" and self.code[cur + 3] in c.k_end:
            cur = self.create_try(block, cur)

        elif self.code[cur:cur + 5] == "while" and self.code[cur +
                                                             5] in c.k_end:
            cur = self.create_while(block, cur)

        elif self.code[cur:cur+4] == "hold" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur:cur+4] == "load" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur:cur+4] == "disp" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur:cur+4] == "grid" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur] in c.e_start:
            j = findend.expression(self, cur)

            j += 1
            while self.code[j] in " \t":
                j += 1
            eq_loc = j

            if self.code[eq_loc] == "=":  # and self.code[eq_loc+1] != "=":

                j = eq_loc + 1
                while self.code[j] in " \t":
                    j += 1
                if self.code[j] == "@":
                    cur = self.create_lambda_assign(block, cur, eq_loc)
                else:
                    cur = self.create_assign(block, cur, eq_loc)

            else:
                end = findend.expression(self, cur)
                if self.disp:
                    print "%4d   Statement    " % cur,
                    print "%-20s" % "codeblock.codeblock",
                    print repr(self.code[cur:end + 1])

                statement = mc.collection.Statement(block,
                                                    cur=cur,
                                                    code=self.code[cur:end +
                                                                   1])

                cur = self.create_expression(statement, cur, end=end)

        cur += 1

        if len(self.code) - cur < 3:
            break
    block.is_end_terminated = is_end_terminated
    block.code = self.code[start:cur + 1]
    return cur
Exemple #7
0
def codeblock(self, parent, start):
    '''
If-ifelse-else branch

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int: Index to end of codeblock

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a; 'b'; 3")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Statement     codeblock.codeblock  'a'
       0     Expression  expression.create    'a'
       0     Var         variables.variable   'a'
       3   Statement     codeblock.codeblock  "'b'"
       3     String  misc.string          "'b'"
       8   Statement     codeblock.codeblock  '3'
       8     Expression  expression.create    '3'
       8     Int         misc.number          '3'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Block      code_block   TYPE
    1  1| Statement  code_block   TYPE
    1  1| | Var        unknown      TYPE    a
    1  4| Statement  code_block   TYPE
    1  4| | String     string       string
    1  9| Statement  code_block   TYPE
    1  9| | Int        int          int
    '''

    cur = start
    block = mc.collection.Block(parent, cur=cur)

    if self.disp:
        print "%4d Codeblock  " % cur,
        print "%-20s" % "codeblock.codeblock"

    while True:

        if self.code[cur] in " \t;":
            pass

        elif self.code[cur] == "\n":
            if len(self.code)-cur < 3:
                break

        #%%PARFOR token
        elif self.code[cur:cur+8] == "%%PARFOR":
            cur = self.create_pragma_parfor(block, cur)
            
        elif self.code[cur] == "%":
            cur = self.create_comment(block, cur)

        elif self.code[cur:cur+3] == "___":
            cur = self.create_verbatim(block, cur)

        elif self.code[cur] == "[":

            # Divide between statement and assignment
            eq_loc = findend.matrix(self, cur)+1

            while self.code[eq_loc] in " \t":
                eq_loc += 1

            if self.code[eq_loc] == "=" and self.code[eq_loc+1] != "=":

                cur = self.create_assigns(block, cur, eq_loc)

            else:

                statement = mc.collection.Statement(block, cur=cur)

                end = findend.expression(self, cur)
                if self.disp:
                    print "%4d   Statement    " % cur,
                    print "%-20s" % "codeblock.codeblock",
                    print repr(self.code[cur:end+1])

                statement.code = self.code[cur:end+1]

                cur = self.create_expression(
                        statement, cur, end=end)


        elif self.code[cur] == "'":

            end = findend.string(self, cur)
            if self.disp:
                print "%4d   Statement    " % cur,
                print "%-20s" % "codeblock.codeblock",
                print repr(self.code[cur:end+1])

            statement = mc.collection.Statement(block, cur=cur,
                    code=self.code[cur:end+1])

            cur = self.create_string(statement, cur)

        elif self.code[cur:cur+4] == "case" and self.code[cur+4] in c.k_end:
            break

        elif self.code[cur:cur+5] == "catch" and self.code[cur+5] in c.k_end:
            break

        elif self.code[cur:cur+3] == "end" and self.code[cur+3] in c.k_end:
            cur += 3
            break

        elif self.code[cur:cur+4] == "else" and self.code[cur+4] in c.k_end:
            break

        elif self.code[cur:cur+6] == "elseif" and self.code[cur+6] in c.k_end:
            break

        elif self.code[cur:cur+6] == "parfor" and self.code[cur+6] in c.k_end:
            cur = self.create_parfor(block, cur)

        elif self.code[cur:cur+3] == "for" and self.code[cur+3] in c.k_end:
            cur = self.create_for(block, cur)

        elif self.code[cur:cur+8] == "function" and\
                self.code[cur+8] in c.k_end + "[":
            cur -= 1
            break

        elif self.code[cur:cur+2] == "if" and self.code[cur+2] in c.k_end:
            cur = self.create_if(block, cur)

        elif self.code[cur:cur+9] == "otherwise" and self.code[cur+9] in c.k_end:
            break

        elif self.code[cur:cur+6] == "switch" and self.code[cur+6] in c.k_end:
            cur = self.create_switch(block, cur)

        elif self.code[cur:cur+3] == "try" and self.code[cur+3] in c.k_end:
            cur = self.create_try(block, cur)

        elif self.code[cur:cur+5] == "while" and self.code[cur+5] in c.k_end:
            cur = self.create_while(block, cur)

        elif self.code[cur:cur+4] == "hold" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur:cur+4] == "grid" and \
            self.code[cur+4] not in c.letters+c.digits+"_":
            cur = self.create_reserved(block, cur)

        elif self.code[cur] in c.e_start:
            j = findend.expression(self, cur)

            j += 1
            while self.code[j] in " \t":
                j += 1
            eq_loc = j

            if self.code[eq_loc] == "=": # and self.code[eq_loc+1] != "=":

                j = eq_loc +1
                while self.code[j] in " \t":
                    j += 1
                if self.code[j] == "@":
                    cur = self.create_lambda_assign(block, cur, eq_loc)
                else:
                    cur = self.create_assign(block, cur, eq_loc)

            else:
                end = findend.expression(self, cur)
                if self.disp:
                    print "%4d   Statement    " % cur,
                    print "%-20s" % "codeblock.codeblock",
                    print repr(self.code[cur:end+1])

                statement = mc.collection.Statement(block, cur=cur,
                        code=self.code[cur:end+1])

                cur = self.create_expression(statement,
                        cur, end=end)

        cur += 1

        if len(self.code)-cur<3:
            break

    block.code = self.code[start:cur+1]
    return cur
Exemple #8
0
def function(self, parent, cur):
    """
Explicit functions

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int : Index to end of function

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "function f(); end")
    loading unnamed
         Program     functions.program
       0 Function        functions.function   'function f()'
      12 Codeblock   codeblock.codeblock 
    >>> builder.configure(suggest=False)
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Funcs      program      TYPE    unnamed
    1  1| Func       func_returns TYPE    f
    1  1| | Declares   func_returns TYPE
    1  1| | Returns    func_returns TYPE
    1 11| | Params     func_returns TYPE
    1 13| | Block      code_block   TYPE
    """

    if self.code[cur:cur+8] != "function":
        self.syntaxerror(cur, "function start")
    if self.code[cur+8] not in c.k_end+"[":
        self.syntaxerror(cur, "function name or return values")

    START = cur
    k = cur + 8

    while self.code[k] in " \t":
        k += 1

    if  self.code[k] not in c.letters+"[":
        self.syntaxerror(k, "function name or return values")
    start = k

    k = findend.expression(self, k)
    end = k

    k += 1
    while self.code[k] in " \t":
        k += 1

    # with return values
    if self.code[k] == "=":

        k += 1
        while self.code[k] in " \t.":
            if self.code[k:k+3] == "...":
                k = findend.dots(self, k)+1
            else:
                k += 1

        l = k
        if  self.code[l] not in c.letters:
            self.syntaxerror(l, "function name")

        while self.code[l+1] in c.letters+c.digits+"_":
            l += 1

        m = l+1

        while self.code[m] in " \t":
            m += 1

        if self.code[m] == "(":
            m = findend.paren(self, m)
        else:
            m = l

        if self.disp:
            print "%4d Function       " % cur,
            print "%-20s" % "functions.function",
            print repr(self.code[START:m+1])

        name = self.code[k:l+1]
        func = mc.collection.Func(parent, name, cur=cur)
        mc.collection.Declares(func, code="")
        returns = mc.collection.Returns(func, code=self.code[start:end+1])

        # multi-return
        if self.code[start] == "[":
            if identify.space_delimited(self, start):
                L = iterate.space_list(self, start)
            else:
                L = iterate.comma_list(self, start)
            end = START
            for array in L:
                for s,e in array:
                    end = s

                    if self.disp:
                        print "%4d   Return       " % cur,
                        print "%-20s" % "functions.function",
                        print repr(self.code[s:e+1])

                    if not any([a in c.letters+c.digits+"_@" \
                            for a in self.code[s:e+1]]):
                        self.syntaxerror(s, "return value")

                    mc.collection.Var(returns, self.code[s:e+1], cur=s,
                            code=self.code[s:e+1])

        # single return
        else:
            end = findend.expression(self, start)

            if self.disp:
                print "%4d   Return       " % cur,
                print repr(self.code[start:end+1])

            mc.collection.Var(returns, self.code[start:end+1], cur=start,
                    code=self.code[start:end+1])


        cur = l+1
        while self.code[cur] in " \t":
            cur += 1

    # No returns
    else:
        m = k
        if self.code[m] == "(":
            m = findend.paren(self, m)
        else:
            m = end


        if self.disp:
            print "%4d Function       " % cur,
            print "%-20s" % "functions.function",
            print repr(self.code[START:m+1])

        end = start+1
        while self.code[end] in c.letters+"_":
            end += 1

        name = self.code[start:end]
        func = mc.collection.Func(parent, name, cur=cur)

        mc.collection.Declares(func)
        returns = mc.collection.Returns(func)

        cur = end

    # Parameters
    params = mc.collection.Params(func, cur=cur)
    if self.code[cur] == "(":

        end = findend.paren(self, cur)
        params.code = self.code[cur+1:end]

        L = iterate.comma_list(self, cur)
        for array in L:
            for s,e in array:

                if self.disp:
                    print "%4d   Param        " % cur,
                    print "%-20s" % "functions.function",
                    print repr(self.code[s:e+1])

                var = mc.collection.Var(params, self.code[s:e+1], cur=s,
                        code=self.code[s:e+1])

        cur = end

    cur += 1

    cur = self.create_codeblock(func, cur)

    # Postfix
    for var in returns:
        var.create_declare()

    end = cur
    func.code = self.code[START:end+1]

    mc.collection.Header(func.program[4], func.name)

    return cur
Exemple #9
0
def lambda_func(self, node, cur):
    """
Anonymous function content. Support function of `lambda_assign`.

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int : Index to end of function line
    """

    if  self.code[cur] != "@":
        self.syntaxerror(cur, "anonymous function indicator (@)")

    end = cur +1
    while self.code[end] in " \t":
        end += 1

    if  self.code[end] != "(":
        self.syntaxerror(end, "anonymous function argument list")

    end = findend.paren(self, end)

    end += 1
    while self.code[end] in " \t":
        end += 1

    end = findend.expression(self, end)

    if self.disp:
        print "%4d   Lambda       " % cur,
        print "%-20s" % "functions.lambda_func",
        print repr(self.code[cur:end+1])

    if node.cls == "Assign":
        name = node[0].name
    else:
        name = "lambda"

    funcs = node.program[1]
    name = "_%s" % (name)
    if name in funcs.names:
        i = 0
        while name+"%d" % i in funcs.names:
            i += 1
        name = name + "%d" % i

    func = mc.collection.Func(funcs, name, cur=cur, code=self.code[cur:end+1])

    declares = mc.collection.Declares(func)
    returns = mc.collection.Returns(func)
    params = mc.collection.Params(func)

    k = cur+1
    while self.code[k] in " \t":
        k += 1

    if  self.code[k] != "(":
        self.syntaxerror(k, "anonymous function argument list")

    cur = self.create_list(params, k)

    cur += 1
    while self.code[cur] in " \t":
        cur += 1

    block = mc.collection.Block(func)
    assign = mc.collection.Assign(block)
    var = mc.collection.Var(assign, "_retval")

    cur = self.create_expression(assign, cur, end=end)

    for n in assign[1].flatten():
        if (n.cls in ("Get", "Cget", "Var", "Fvar", "Fget",
            "Sget")) and n.name in node.func[0].names + node.func[2].names:

            n.create_declare()


    var = mc.collection.Var(returns, "_retval")
    var.create_declare()

    lamb = mc.collection.Lambda(node, name)

    lamb.reference = func

    return cur
Exemple #10
0
def multi(self, parent, cur, eq_loc):
    """
Assignment with multiple return

Args:
    self (Builder): Code constructor.
    parent (Node): Parent node
    cur (int): Current position in code
    eq_loc (int): position of the assignment marker ('='-sign)

Returns:
	int: Index to end of assignment

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "[a,b] = c")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Assigns     assign.multi         '[a,b] = c'
       1     Var         variables.assign     'a'
       3     Var         variables.assign     'b'
       8     Expression  expression.create    'c'
       8     Var         variables.variable   'c'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
     1  1Block      code_block   TYPE
     1  1| Assigns    unknown      TYPE    c
     1  2| | Var        unknown      TYPE    a
     1  4| | Var        unknown      TYPE    b
     1  9| | Var        unknown      TYPE    c
    """

    if self.code[cur] != "[":
        self.syntaxerror(cur, "multi-assign start")
    if self.code[eq_loc] != "=":
        self.syntaxerror(cur, "assignment sign (=)")

    j = eq_loc + 1
    while self.code[j] in " \t.":
        if self.code[j] == ".":
            j = findend.dots(self, j) + 1
        else:
            j += 1
    end = findend.expression(self, j)

    if self.disp:
        print "%4d   Assigns    " %\
                cur,
        print "%-20s" % "assign.multi",
        print repr(self.code[cur:end + 1])

    if identify.space_delimited(self, cur):
        l = iterate.space_list(self, cur)
    else:
        l = iterate.comma_list(self, cur)

    if len(l[0]) == 1:
        return self.create_assign(parent, l[0][0][0], eq_loc)

    assigns = mc.collection.Assigns(parent,
                                    cur=cur,
                                    code=self.code[cur:end + 1])

    for vector in l:
        for start, stop in vector:
            self.create_assign_variable(assigns, start, end=stop)

    cur = eq_loc + 1
    while self.code[cur] in " \t":
        cur += 1

    cur_ = self.create_expression(assigns, cur)

    assigns.name = assigns[-1].name

    return cur_
Exemple #11
0
def single(self, parent, cur, eq_loc):
    """
Assignment with single return.

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code
    eq_loc (int): position of the assignment marker ('='-sign)

Returns:
	int: Index to end of assignment

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a=b")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Assign      assign.single        'a=b'
       0     Var         variables.assign     'a'
       2     Expression  expression.create    'b'
       2     Var         variables.variable   'b'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1 1Block      code_block   TYPE
    1 1| Assign     unknown      TYPE    b
    1 1| | Var        unknown      TYPE    a
    1 3| | Var        unknown      TYPE    b
    """

    if self.code[cur] not in c.letters:
        self.syntaxerror(cur, "assignment start")
    if self.code[eq_loc] != "=":
        self.syntaxerror(cur, "assignment indicator (=)")

    j = eq_loc + 1
    while self.code[j] in " \t":
        j += 1
    end = findend.expression(self, j)

    if self.disp:
        print "%4d   Assign     " %\
                cur,
        print "%-20s" % "assign.single",
        print repr(self.code[cur:end + 1])

    assign = mc.collection.Assign(parent, cur=cur, code=self.code[cur:end + 1])

    cur = self.create_assign_variable(assign, cur, eq_loc)

    cur += 1
    while self.code[cur] in " \t":
        cur += 1

    if self.code[cur] == "]":
        cur += 1
        while self.code[cur] in " \t":
            cur += 1

    if self.code[cur] != "=":
        self.syntaxerror(cur, "assignment indicator (=)")

    k = cur + 1
    while self.code[k] in " \t":
        k += 1

    self.create_expression(assign, k, end)
    assign.name = assign[-1].name

    if len(assign) != 2:
        self.syntaxerror(k, "single assign when multi-assign")

    return end
Exemple #12
0
def create(self, node, start, end=None, start_opr=None):
    """
Create expression in three steps:

    1) In order, split into sub-expressions for each dividing operator
    2) Address prefixes, postfixes, parenthesises, etc.
    3) Identify the remaining singleton

Args:
    self (Builder): Code constructor.
    node (Node): Reference to the parent node
    start (int): current possition in code
    end (int, optional): end of expression. Required for space-delimited expression.
    start_opr (str, optional): At which operator the recursive process is. (For internal use)

Returns:
	int : index to end of the expression

Examples::

    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a*b+c/d")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Statement     codeblock.codeblock  'a*b+c/d'
       0     Expression  expression.create    'a*b+c/d'
       0     Expression  expression.create    'a*b'
       0     Expression  expression.create    'a'
       0     Var         variables.variable   'a'
       2     Expression  expression.create    'b'
       2     Var         variables.variable   'b'
       4     Expression  expression.create    'c/d'
       4     Expression  expression.create    'c'
       4     Var         variables.variable   'c'
       6     Expression  expression.create    'd'
       6     Var         variables.variable   'd'
    >>> builder.configure(suggest=False)
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1 1Block      code_block   TYPE
    1 1| Statement  code_block   TYPE
    1 1| | Plus       expression   TYPE
    1 1| | | Mul        expression   TYPE
    1 1| | | | Var        unknown      TYPE    a
    1 3| | | | Var        unknown      TYPE    b
    1 5| | | Matrixdivisionexpression   TYPE
    1 5| | | | Var        unknown      TYPE    c
    1 7| | | | Var        unknown      TYPE    d
    """

    if self.code[start:start+3] == "...":
        start = findend.dots(self, start)
        start += 1
        while self.code[start] in " \t":
            start += 1

    if self.code[start] == ":":

        if self.disp:

            print "%4d     Expression " % (start),
            print "%-20s" % "expression.create",
            print repr(self.code[start:start+1])

            print "%4d     All        " % (start),
            print "%-20s" % "expression.create",
            print repr(self.code[start:start+1])

        mc.collection.All(node, cur=start, code=self.code[start])
        return start

    if end is None:
        end = findend.expression(self, start)

    if self.disp:
        print "%4d     Expression " % (start),
        print "%-20s" % "expression.create",
        print repr(self.code[start:end+1])

    if  self.code[start] not in c.e_start:
        self.syntaxerror(start, "expression start")


    operators = [
        "||", "&&", "|", "&",
        "~=", "==", ">=", ">", "<=", "<",
        ":", "+", "-",
        ".*", "*", "./", "/", ".\\", "\\",
        ".^", "^"]

    if not (start_opr is None):
        operators = operators[operators.index(start_opr)+1:]

    for opr in operators:
        # Pre-screen
        if opr not in self.code[start:end+1]:
            continue

        starts = [start]
        last = start
        ends = []

        k = start
        while True:

            if self.code[k] == "(":
                k = last = findend.paren(self, k)

            elif self.code[k] == "[":
                k = last = findend.matrix(self, k)

            elif self.code[k] == "{":
                k = last = findend.cell(self, k)

            elif self.code[k] == "'":
                if identify.string(self, k):
                    k = last = findend.string(self, k)
                else:
                    last = k

            elif opr == self.code[k:k+len(opr)]:

                if opr in "+-":
                    # no prefixes and no (scientific) numbers
                    if self.code[last] not in c.letters+c.digits+")]}" or\
                            self.code[k-1] in "dDeE" and self.code[k-2] in\
                            c.digits+"." and self.code[k+1] in c.digits:
                        k += 1
                        continue


                k += len(opr)-1
                while self.code[k+1] in " \t":
                    k += 1

                # no all-operator
                if opr == ":" and self.code[k+1] in ",;\n)]}":
                    k += 1
                    continue

                starts.append(k+1)
                ends.append(last)

            elif self.code[k] in c.letters+c.digits+"_":
                last = k

            k += 1
            if k >= end:
                ends.append(end)
                break

        if len(ends)>1:

            node = retrieve_operator(self, opr)(node)
            node.cur = start
            node.code = self.code[starts[0]:ends[-1]+1]

            for s,e in zip(starts, ends):
                create(self, node, s, e, opr)

            return end


    # All operators removed at this point!

    END = end

    # Prefixes
    while self.code[start] in "-~":

        if self.code[start] == "-":

            node = mc.collection.Neg(node, cur=start, code=self.code[start:end+1])
            start += 1

        if self.code[start] == "~":

            node = mc.collection.Not(node, cur=start, code=self.code[start:end+1])
            start += 1

        while self.code[start] in " \t":
            start += 1

    # Postfixes
    if self.code[end] == "'" and not self.code[start] == "'":
        if self.code[end-1] == ".":
            node = mc.collection.Transpose(node, cur=start,
                    code=self.code[start:end+1])
            end -= 2
        else:
            node = mc.collection.Ctranspose(node, cur=start,
                    code=self.code[start:end+1])
            node.cur = start
            node.code = self.code[start:end+1]
            end -= 1

        while self.code[end] in " \t":
            end -= 1

    # Parenthesis
    if self.code[start] == "(":
        if self.code[end] != ")":
            self.syntaxerror(end, "parenthesis end")

        node = mc.collection.Paren(node, cur=start, code=self.code[start:end+1])

        start += 1
        while self.code[start] in " \t":
            start += 1

        end -= 1
        while self.code[end] in " \t":
            end -= 1

        return create(self, node, start, end)

    # Reserved keywords
    elif self.code[start:start+3] == "end": # and self.code[start+3] in " \t" + c.e_end:
        node = mc.collection.End(node, cur=start, code=self.code[start:start+3])

    elif self.code[start:start+6] == "return" and self.code[start+6] in " ,;\n":
        node = mc.collection.Return(node, cur=start, code=self.code[start:start+6])

    elif self.code[start:start+5] == "break" and self.code[start+5] in " ,;\n":
        node = mc.collection.Break(node, cur=start, code=self.code[start:start+5])


    # Rest
    elif self.code[start] == "'":
        if self.code[end] != "'":
            self.syntaxerror(end, "string end")

        if "\n" in self.code[start:end]:
            self.syntaxerror(end, "non line-feed characters in string")

        mc.collection.String(node, self.code[start+1:end], cur=start,
                code=self.code[start:end+1])

    elif self.code[start] in c.digits or\
            self.code[start] == "." and self.code[start+1] in c.digits:
        cur = self.create_number(node, start)

    elif self.code[start] == "[":
        cur = self.create_matrix(node, start)

    elif self.code[start] == "{":
        cur = self.create_cell(node, start)

    else:
        if self.code[start] not in c.letters+"@":
            self.syntaxerror(start, "variable name")

        cur = self.create_variable(node, start)

    return END
Exemple #13
0
def lambda_func(self, node, cur):
    """
Anonymous function content. Support function of `lambda_assign`.

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int : Index to end of function line
    """

    if self.code[cur] != "@":
        self.syntaxerror(cur, "anonymous function indicator (@)")

    end = cur + 1
    while self.code[end] in " \t":
        end += 1

    if self.code[end] != "(":
        self.syntaxerror(end, "anonymous function argument list")

    end = findend.paren(self, end)

    end += 1
    while self.code[end] in " \t":
        end += 1

    end = findend.expression(self, end)

    if self.disp:
        print "%4d   Lambda       " % cur,
        print "%-20s" % "functions.lambda_func",
        print repr(self.code[cur:end + 1])

    if node.cls == "Assign":
        name = node[0].name
    else:
        name = "lambda"

    funcs = node.program[1]
    name = "_%s" % (name)
    if name in funcs.names:
        i = 0
        while name + "%d" % i in funcs.names:
            i += 1
        name = name + "%d" % i

    func = mc.collection.Func(funcs,
                              name,
                              cur=cur,
                              code=self.code[cur:end + 1])

    declares = mc.collection.Declares(func)
    returns = mc.collection.Returns(func)
    params = mc.collection.Params(func)

    k = cur + 1
    while self.code[k] in " \t":
        k += 1

    if self.code[k] != "(":
        self.syntaxerror(k, "anonymous function argument list")

    cur = self.create_list(params, k)

    cur += 1
    while self.code[cur] in " \t":
        cur += 1

    block = mc.collection.Block(func)
    assign = mc.collection.Assign(block)
    var = mc.collection.Var(assign, "_retval")

    cur = self.create_expression(assign, cur, end=end)

    for n in assign[1].flatten():
        if (n.cls in ("Get", "Cget", "Var", "Fvar", "Fget", "Sget")
            ) and n.name in node.func[0].names + node.func[2].names:

            n.create_declare()

    var = mc.collection.Var(returns, "_retval")
    var.create_declare()

    lamb = mc.collection.Lambda(node, name)

    lamb.reference = func

    return cur
Exemple #14
0
def function(self, parent, cur):
    """
Explicit functions

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code

Returns:
	int : Index to end of function

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "function f(); end")
    loading unnamed
         Program     functions.program
       0 Function        functions.function   'function f()'
      12 Codeblock   codeblock.codeblock 
    >>> builder.configure(suggest=False)
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1  1Funcs      program      TYPE    unnamed
    1  1| Func       func_returns TYPE    f
    1  1| | Declares   func_returns TYPE
    1  1| | Returns    func_returns TYPE
    1 11| | Params     func_returns TYPE
    1 13| | Block      code_block   TYPE
    """

    if self.code[cur:cur + 8] != "function":
        self.syntaxerror(cur, "function start")
    if self.code[cur + 8] not in c.k_end + "[":
        self.syntaxerror(cur, "function name or return values")

    START = cur
    k = cur + 8

    while self.code[k] in " \t":
        k += 1

    if self.code[k] not in c.letters + "[":
        self.syntaxerror(k, "function name or return values")
    start = k

    k = findend.expression(self, k)
    end = k

    k += 1
    while self.code[k] in " \t":
        k += 1

    # with return values
    if self.code[k] == "=":

        k += 1
        while self.code[k] in " \t.":
            if self.code[k:k + 3] == "...":
                k = findend.dots(self, k) + 1
            else:
                k += 1

        l = k
        if self.code[l] not in c.letters:
            self.syntaxerror(l, "function name")

        while self.code[l + 1] in c.letters + c.digits + "_":
            l += 1

        m = l + 1

        while self.code[m] in " \t":
            m += 1

        if self.code[m] == "(":
            m = findend.paren(self, m)
        else:
            m = l

        if self.disp:
            print "%4d Function       " % cur,
            print "%-20s" % "functions.function",
            print repr(self.code[START:m + 1])

        name = self.code[k:l + 1]
        func = mc.collection.Func(parent, name, cur=cur)
        mc.collection.Declares(func, code="")
        returns = mc.collection.Returns(func, code=self.code[start:end + 1])

        # multi-return
        if self.code[start] == "[":
            if identify.space_delimited(self, start):
                L = iterate.space_list(self, start)
            else:
                L = iterate.comma_list(self, start)
            end = START
            for array in L:
                for s, e in array:
                    end = s

                    if self.disp:
                        print "%4d   Return       " % cur,
                        print "%-20s" % "functions.function",
                        print repr(self.code[s:e + 1])

                    if not any([a in c.letters+c.digits+"_@" \
                            for a in self.code[s:e+1]]):
                        self.syntaxerror(s, "return value")

                    mc.collection.Var(returns,
                                      self.code[s:e + 1],
                                      cur=s,
                                      code=self.code[s:e + 1])

        # single return
        else:
            end = findend.expression(self, start)

            if self.disp:
                print "%4d   Return       " % cur,
                print repr(self.code[start:end + 1])

            mc.collection.Var(returns,
                              self.code[start:end + 1],
                              cur=start,
                              code=self.code[start:end + 1])

        cur = l + 1
        while self.code[cur] in " \t":
            cur += 1

    # No returns
    else:
        m = k
        if self.code[m] == "(":
            m = findend.paren(self, m)
        else:
            m = end

        if self.disp:
            print "%4d Function       " % cur,
            print "%-20s" % "functions.function",
            print repr(self.code[START:m + 1])

        end = start + 1
        while self.code[end] in c.letters + "_":
            end += 1

        name = self.code[start:end]
        func = mc.collection.Func(parent, name, cur=cur)

        mc.collection.Declares(func)
        returns = mc.collection.Returns(func)

        cur = end

    # Parameters
    params = mc.collection.Params(func, cur=cur)
    if self.code[cur] == "(":

        end = findend.paren(self, cur)
        params.code = self.code[cur + 1:end]

        L = iterate.comma_list(self, cur)
        for array in L:
            for s, e in array:

                if self.disp:
                    print "%4d   Param        " % cur,
                    print "%-20s" % "functions.function",
                    print repr(self.code[s:e + 1])

                var = mc.collection.Var(params,
                                        self.code[s:e + 1],
                                        cur=s,
                                        code=self.code[s:e + 1])

        cur = end

    cur += 1

    cur = self.create_codeblock(func, cur)

    # Postfix
    for var in returns:
        var.create_declare()

    end = cur
    func.code = self.code[START:end + 1]

    mc.collection.Header(func.program[4], func.name)

    return cur
Exemple #15
0
def single(self, parent, cur, eq_loc):
    """
Assignment with single return.

Args:
    self (Builder): Code constructor
    parent (Node): Parent node
    cur (int): Current position in code
    eq_loc (int): position of the assignment marker ('='-sign)

Returns:
	int: Index to end of assignment

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "a=b")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Assign      assign.single        'a=b'
       0     Var         variables.assign     'a'
       2     Expression  expression.create    'b'
       2     Var         variables.variable   'b'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
    1 1Block      code_block   TYPE
    1 1| Assign     unknown      TYPE    b
    1 1| | Var        unknown      TYPE    a
    1 3| | Var        unknown      TYPE    b
    """

    if self.code[cur] not in c.letters:
        self.syntaxerror(cur, "assignment start")
    if self.code[eq_loc] != "=":
        self.syntaxerror(cur, "assignment indicator (=)")

    j = eq_loc + 1
    while self.code[j] in " \t":
        j += 1
    end = findend.expression(self, j)

    if self.disp:
        print "%4d   Assign     " % cur,
        print "%-20s" % "assign.single",
        print repr(self.code[cur : end + 1])

    assign = mc.collection.Assign(parent, cur=cur, code=self.code[cur : end + 1])

    cur = self.create_assign_variable(assign, cur, eq_loc)

    cur += 1
    while self.code[cur] in " \t":
        cur += 1

    if self.code[cur] == "]":
        cur += 1
        while self.code[cur] in " \t":
            cur += 1

    if self.code[cur] != "=":
        self.syntaxerror(cur, "assignment indicator (=)")

    k = cur + 1
    while self.code[k] in " \t":
        k += 1

    self.create_expression(assign, k, end)
    assign.name = assign[-1].name

    if len(assign) != 2:
        self.syntaxerror(k, "single assign when multi-assign")

    return end
Exemple #16
0
def multi(self, parent, cur, eq_loc):
    """
Assignment with multiple return

Args:
    self (Builder): Code constructor.
    parent (Node): Parent node
    cur (int): Current position in code
    eq_loc (int): position of the assignment marker ('='-sign)

Returns:
	int: Index to end of assignment

Example:
    >>> builder = mc.Builder(True)
    >>> builder.load("unnamed", "[a,b] = c")
    loading unnamed
         Program     functions.program
       0 Main        functions.main
       0 Codeblock   codeblock.codeblock 
       0   Assigns     assign.multi         '[a,b] = c'
       1     Var         variables.assign     'a'
       3     Var         variables.assign     'b'
       8     Expression  expression.create    'c'
       8     Var         variables.variable   'c'
    >>> builder.configure()
    >>> print mc.qtree(builder, core=True) # doctest: +NORMALIZE_WHITESPACE
     1  1Block      code_block   TYPE
     1  1| Assigns    unknown      TYPE    c
     1  2| | Var        unknown      TYPE    a
     1  4| | Var        unknown      TYPE    b
     1  9| | Var        unknown      TYPE    c
    """

    if self.code[cur] != "[":
        self.syntaxerror(cur, "multi-assign start")
    if self.code[eq_loc] != "=":
        self.syntaxerror(cur, "assignment sign (=)")

    j = eq_loc + 1
    while self.code[j] in " \t.":
        if self.code[j] == ".":
            j = findend.dots(self, j) + 1
        else:
            j += 1
    end = findend.expression(self, j)

    if self.disp:
        print "%4d   Assigns    " % cur,
        print "%-20s" % "assign.multi",
        print repr(self.code[cur : end + 1])

    if identify.space_delimited(self, cur):
        l = iterate.space_list(self, cur)
    else:
        l = iterate.comma_list(self, cur)

    if len(l[0]) == 1:
        return self.create_assign(parent, l[0][0][0], eq_loc)

    assigns = mc.collection.Assigns(parent, cur=cur, code=self.code[cur : end + 1])

    for vector in l:
        for start, stop in vector:
            self.create_assign_variable(assigns, start, end=stop)

    cur = eq_loc + 1
    while self.code[cur] in " \t":
        cur += 1

    cur_ = self.create_expression(assigns, cur)

    assigns.name = assigns[-1].name

    return cur_