#!/usr/bin/env python
#
# Simple conversion script from old FFC .form format to UFL format

__authors__ = "Anders Logg"
__date__ = "2008-08-01 -- 2009-03-15"

import sys
import re
from os.path import exists

def help():
    print "Simple conversion script from old FFC .form format to UFL format."
    print ""
    print "Usage: form2ufl <filename>.form"

def error(message=None):
    if not message is None:
        print message
    else:
        help()
    sys.exit(1)

def split_at_closing_brace(s):
    num_left = num_right = 0
    for (i, c) in enumerate(s):
        if c == "(":
            num_left += 1
        elif c == ")":
            num_right += 1
        if num_left == num_right:
            return s[:i + 1], s[i + 1:]
    return s, ""

def replace_transp(match):
    expr1, expr2 = split_at_closing_brace(match.groups()[0])
    return expr1 + ".T" + expr2

def replace_mult(match):
    start, end = split_at_closing_brace(match.groups()[0])
    expr1 = start.split(",")[0][1:].strip()
    expr2 = start.split(",")[1][:-1].strip()
    if "+" in expr1:
        expr1 = "(%s)" % expr1
    if "+" in expr2:
        expr2 = "(%s)" % expr2
    return expr1 + "*" + expr2 + end

def form2ufl(code):

    # List of simple replacements
    simple_replacements = ((r"\.form",                    ".ufl"),
                           (r"\bdot\b",                   "inner"),
                           (r"\bD\b",                     "Dx"),
                           (r"\bmodulus\b",               "abs"),
                           (r'"interval"',                "interval"),
                           (r'"triangle"',                "triangle"),
                           (r'"tetrahedron"',             "tetrahedron"),
                           (r'MeshSize',                  "Constant"),
                           (r'FacetNormal',               "VectorConstant"),
                           (r"Nedelec",                   "N1curl"),
                           (r"VectorQuadratureElement\(", 'VectorElement("Quadrature", '),
                           (r"QuadratureElement\(",       'FiniteElement("Quadrature", '))

    # List of complex replacements
    complex_replacements = ((r"\btransp(.*)", replace_transp),
                            (r"\bmult(.*)",   replace_mult))

    # Iterate over replacemens
    for (a, b) in simple_replacements + complex_replacements:
        code = re.sub(a, b, code)

    return code

def main(args):

    # Check command-line arguments
    if not len(args) == 1:
        error()

    # Get prefix and filenames
    words = args[0].split(".form")
    if not (len(words) == 2 and words[1] == ""):
        error()
    prefix = words[0]
    form_filename = prefix + ".form"
    ufl_filename = prefix + ".ufl"

    # Check if outfile exists
    if exists(ufl_filename):
        error("File already exists: " + ufl_filename)

    print "Converting %s --> %s" % (form_filename, ufl_filename)

    # Read file
    try:
        file = open(form_filename, "r")
        code = file.read()
        file.close()
    except:
        error("Unable to read file: " + form_filename)

    # Convert to UFL
    code = form2ufl(code)

    # Write file
    try:
        file = open(ufl_filename, "w")
        file.write(code)
        file.close()
    except:
        error("Unable to write to file: " + ufl_filename)

if __name__ == "__main__":
    main(sys.argv[1:])
    sys.exit(0)
