# vim: syntax=ruby class Nagios::Parser

token DEFINE NAME STRING PARAM LCURLY RCURLY VALUE RETURN COMMENT INLINECOMMENT

rule decls: decl { return val if val }

| decls decl {
    if val[1].nil?
        result = val[0]
    else
        if val[0].nil?
            result = val[1]
        else
            result = [ val[0], val[1] ].flatten
        end
    end
}
;

decl: object { result = [val] }

| RETURN { result = nil }
| comment
;

comment: COMMENT RETURN { result = nil }

;

object: DEFINE NAME LCURLY RETURN vars RCURLY {

    result = Nagios::Base.create(val[1],val[4])
}
;

vars: var

| vars var {
    val[1].each {|p,v|
        val[0][p] = v
    }
    result = val[0]
}
;

var: PARAM VALUE icomment returns { result = {val,val} }

;

returns: RETURN

| returns RETURN
;

icomment: # nothing

| INLINECOMMENT
;

end

—-inner

class ::Nagios::Parser::SyntaxError < RuntimeError; end

def parse(src)

@src = src

# state variables
@invar = false
@inobject = false
@done = false

@line = 0
@yydebug = true

do_parse

end

# The lexer. Very simple. def token

@src.sub!(/\A\n/,'')
if $&
    @line += 1
    return [ :RETURN, "\n" ]
end

if @done
    return nil
end
yytext = String.new

# remove comments from this line
@src.sub!(/\A[ \t]*;.*\n/,"\n")
if $&
    return [:INLINECOMMENT, ""]
end

@src.sub!(/\A#.*\n/,"\n")
if $&
    return [:COMMENT, ""]
end

@src.sub!(/#.*/,'')

if @src.length == 0
    @done = true
    return [false, '$']
end

if @invar
    @src.sub!(/\A[ \t]+/,'')
    @src.sub!(/\A([^;\n]+)(\n|;)/,'\2')
    if $1
        yytext += $1
    end
    @invar = false
    return [:VALUE, yytext]
else
    @src.sub!(/\A[\t ]*(\S+)([\t ]*|$)/,'')
    if $1
        yytext = $1
        case yytext
        when 'define'
            #puts "got define"
            return [:DEFINE, yytext]
        when '{'
            #puts "got {"
            @inobject = true
            return [:LCURLY, yytext]
        else
            unless @inobject
                #puts "got type: #{yytext}"
                if yytext =~ /\W/
                    giveback = yytext.dup
                    giveback.sub!(/^\w+/,'')
                    #puts "giveback " + giveback
                    #puts "yytext " + yytext
                    yytext.sub!(/\W.*$/,'')
                    #puts "yytext " + yytext
                    #puts "all [#{giveback} #{yytext} #{orig}]"
                    @src = giveback + @src
                end
                return [:NAME, yytext]
            else
                if yytext == '}'
                    #puts "got closure: #{yytext}"
                    @inobject = false
                    return [:RCURLY, '}']
                end

                unless @invar
                    @invar = true
                    return [:PARAM, $1]
                else
                end
            end
        end
    end
end

end

def next_token

token

end

def yydebug

1

end

def yywrap

0

end

def on_error(token, value, vstack )

msg = ""
unless value.nil?
    msg = "line #{@line}: syntax error at '#{value}'"
else
    msg = "line #{@line}: syntax error at '#{token}'"
end
unless @src.size > 0
    msg = "line #{@line}: Unexpected end of file"
end
if token == '$end'.intern
    puts "okay, this is silly"
else
    raise ::Nagios::Parser::SyntaxError, msg
end

end