grammar Il

rule document
    expr ws? (newline ws?)* {
        def value(curr_backend)
            curr_backend.public_send(:document, self)
        end
    }
end

rule expr
    addExpr ws? '@EQ@' ws? addExpr {
        def value(curr_backend)
            curr_backend.public_send(:assignment, self)
        end
    } /
    addExpr
end

rule addExpr
    (multExpr ws? '@+@' ws? addExpr) {
        def value(curr_backend)
            curr_backend.public_send(:plus_expr, self)
        end
    } /
    (multExpr ws? '@-@' ws? addExpr) {
        def value(curr_backend)
            curr_backend.public_send(:minus_expr, self)
        end
    } /
    multExpr  
end

rule multExpr
    ((dottedExpr ws? '@x@' ws? multExpr ) {
        def value(curr_backend)
            curr_backend.public_send(:time_expr, self)
        end
    } /
    divExpr /

    dottedExpr ) 
end

rule dottedExpr
    factor (ws? '@REF@' expr)* {
        def value(curr_backend)
            curr_backend.public_send(:dotted_expr, self)
        end
    }
end

rule factor
    tabRef /
    descriptor  /
    call /
    parenthesed /
    colored /
    ('@-@' ws? factor) {
        def value(curr_backend)
            curr_backend.public_send(:unary_minus, self)
        end
    }/
    whileExpr /
    terminal
end

rule tabRef
    terminal ws? '@REFA@' ws? '{' ws? terminal ws? '}' {
        def value(curr_backend)
            curr_backend.public_send(:tab_ref, self)
        end
    }
end

rule terminal
   (atom '@REF@' terminal) {
        def value(curr_backend)
            curr_backend.public_send(:dotted_terminal, self)
        end
    }  / 
    atom 
end

rule atom
    identifier (':' number)? {
        def value(curr_backend)
            curr_backend.public_send(:atom, self)
        end
    }
end

rule descriptor
    '@TSTART@' ws? identifier ws? '@TEND@' ws? '@DESCSTART@' ws? items ws? '@DESCEND@' {
        def value(curr_backend)
            curr_backend.public_send(:descriptor, self)
        end
    }
end

rule items
    item (ws? item)* {
        def value(curr_backend)
            curr_backend.public_send(:descriptor_items, self)
        end
    }
end

rule item
    '@DESCITEMSTART@' ws? '@TSTART@' ws? identifier ws? '@TEND@' ws? '=' ws? (expr (ws? '@REF@' expr)*) '@DESCITEMEND@' {
        def value(curr_backend)
            curr_backend.public_send(:descriptor_item, self)
        end
    }
end

rule divExpr
    '@DIV@' ws? '@NUM@' ws? '{' ws? addExpr ws? '}' ws? '@DENO@' ws? '{' ws? addExpr ws? '}' ws? '@/DIV@' {
        def value(curr_backend)
            curr_backend.public_send(:div_expr, self)
        end
    }
end

rule call
    terminal ws? '@LPAREN@' ws? args? ws? '@RPAREN@' {
        def value(curr_backend)
            curr_backend.public_send(:call, self)
        end
    }
end

rule args
    expr (ws? ',' ws? expr)* {
        def value(curr_backend)
            curr_backend.public_send(:args, self)
        end
    }
end

rule parenthesed
    '@LPAREN@' ws? expr ws? '@RPAREN@' {
        def value(curr_backend)
            curr_backend.public_send(:parenthesed, self)
        end
    }
end

rule colored
    color ws? '{' ws? expr ws? '}' {
        def value(curr_backend)
            curr_backend.public_send(:colored, self)
        end
    }
end

rule color
    '@COLOR-' colorcode '@' {
        def value(curr_backend)
            curr_backend.public_send(:color, self)
        end
    }
end

rule colorcode
    [a-fA-F0-9]+ {
        def value(curr_backend)
            curr_backend.public_send(:colorcode, self)
        end
    }
end

rule whileExpr
    repeat ws? '@LBRACK@' ws? expr ws? '@RBRACK@' ws? whilecondExpr {
        def value(curr_backend)
            curr_backend.public_send(:while_expr, self)
        end
    }
end

rule repeat
    '@TSTART@repeat@TEND@'
end

rule whilecondExpr
    '@UNDERSCRIPT@{@TSTART@' ws? 'while' ws? text ws? '@TEND@}' {
        def value(curr_backend)
            curr_backend.public_send(:while_cond_expr, self)
        end
    }
end

rule text
    [^@]+ (ws [^@]+)* {
        def value(curr_backend)
            curr_backend.public_send(:text, self)
        end
    }
end

rule identifier
    [a-zA-Z]+ {
        def value(curr_backend)
            curr_backend.public_send(:identifier, self)
        end
    }
end

rule number
   ([1-9] [0-9]*) 
end

rule ws
    [ \t]+
end

rule newline
    [\r\n]
end

end