Skip to content
This repository
tree: 395dea38e7
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 118 lines (101 sloc) 4.22 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
class Fbp
    matchPort: new RegExp "([A-Z\.]+)"
    matchComponent: new RegExp "([A-Za-z]+)\\(([A-Za-z0-9\/\.]+|)\\)"
    matchInitial: new RegExp "\'(.+)\'"
    matchConnection: new RegExp "\-\>"
    matchSeparator: new RegExp "[\\s,\\n]"

    constructor: ->
        @lastElement = null
        @currentElement = null
        @currentNode = {}
        @currentEdge = {}
        @currentLine = 1
        @nodes = {}
        @edges = []

    parse: (string) ->
        currentString = ""
        for char, index in string
            @currentLine++ if char is "\n"

            # Commenting support. Ignore everything from # to newline
            if char is '#' and @currentElement isnt "initial"
                @currentElement = "comment"
                continue
            if @currentElement is "comment"
                if char is "\n"
                    @currentElement = null
                continue

            if char is "'"
                if @currentElement is "initial"
                    # End of initial data
                    @currentElement = null
                else
                    # Start of initial data
                    @currentElement = "initial"

            checkTerminator = @matchSeparator.exec(char)
            checkTerminator = null if @currentElement is "initial"
            currentString += char unless checkTerminator
            continue unless checkTerminator or index is string.length - 1

            connection = @matchConnection.exec currentString
            if connection
                throw new Error "Port or initial expected, got #{currentString} on line #{@currentLine}" unless @lastElement is "initial" or @lastElement is "port"
                @lastElement = "connection"
                @handleConnection connection
                currentString = ""
            initial = @matchInitial.exec currentString
            if initial
                throw new Error "Newline expected, got #{currentString} on line #{@currentLine}" unless @lastElement is null
                @lastElement = "initial"
                @handleInitial initial
                currentString = ""
            component = @matchComponent.exec currentString
            if component
                throw new Error "Port or newline expected, got #{currentString} on line #{@currentLine}" unless @lastElement is "port" or @lastElement is null
                @lastElement = "component"
                @handleComponent component
                currentString = ""
            port = @matchPort.exec currentString
            if port
                throw new Error "Connection or component expected, got #{currentString} on line #{@currentLine}" unless @lastElement is "connection" or @lastElement is "component"
                @lastElement = "port"
                @handlePort port
                currentString = ""

            if char is "\n"
                @lastElement = null

        json =
            properties:
                name: ""
            processes: @nodes
            connections: @edges

    handleConnection: ->
        @currentEdge.src.process = @currentNode.name if @currentNode.name

    handleInitial: (initial) ->
        @currentNode =
            data: initial[1]

        @currentEdge =
            data: @currentNode.data
            tgt: {}
        delete @currentEdge.src if @currentEdge.src

    handleComponent: (component) ->
        @currentNode =
            name: component[1]
            component: component[2]

        @nodes[@currentNode.name] = @currentNode unless @nodes[@currentNode.name]

        if @currentEdge.tgt and @currentEdge.tgt.port
            @currentEdge.tgt.process = @currentNode.name
            @edges.push @currentEdge
            @currentEdge =
                src: {}
                tgt: {}
            return
        unless @currentEdge.src
            @currentEdge =
                src:
                    process: @currentNode.name
                tgt: {}
    
    handlePort: (port) ->
        if @currentEdge.data or @currentEdge.src.port
            @currentEdge.tgt =
                port: port[1].toLowerCase()
            return
        @currentEdge.src.port = port[1].toLowerCase()

exports.Fbp = Fbp
Something went wrong with that request. Please try again.