class MapParser
rule

commands 
	: commands command_blk SEMICOLON { puts "GOT A COMMAND" }
	| /* none */ { puts "no command found" }

command_blk
	: global_blk
	| server_blk

server_blk
	: SERVER STRING OBRACE server_opts EBRACE { puts "[server #{val[1]}]" }

global_blk
	: GLOBAL OBRACE global_opts EBRACE

server_opts 
	: server_opts server_opt SEMICOLON
	| /* none */

server_opt 
	: user_opt { puts "=> user opt" }
	| port_opt { puts "=> port opt" }
	| automount_opt { puts "=> automount opt" }
	| compress_opt { puts "=> compress opt" }
	| reconnect_opt { puts "=> reconnect opt" }
	| server_map_blk { puts "=> server_map blk" }

server_map_blk
	: MAP STRING OBRACE server_map_opts EBRACE

server_map_opts
	: server_map_opts server_map_opt SEMICOLON
	| /* none */
	
server_map_opt
	: remote_opt
	| local_opt
	| user_opt
	| port_opt
	| compress_opt

user_opt 
	: USER STRING { puts "* user = #{val[1]}" }

port_opt 
	: PORT NUMBER { puts "* port = #{val[1]}" }

automount_opt 
	: AUTOMOUNT boolean { puts "* automount = #{@bool_result}" }

compress_opt 
	: COMPRESS boolean { puts "* compress = #{@bool_result}" }

reconnect_opt 
	: RECONNECT boolean { puts ( "* reconnect = #{@bool_result}" ) }

boolean
	: BOOL_TRUE { @bool_result = true }
	| BOOL_FALSE { @bool_result = false }

end

---- header ----

# calc.rb : generated by racc
#
require 'strscan'
#require 'map.rb'

---- inner ----

	def parse( str )
		puts "parse start..."
		tokens = []

		scanner = StringScanner.new( str )
		puts ( "scanner?" + scanner.string )
		
		until scanner.eos?
			puts "scanning.. at #{scanner.pos}"
			case
				when m = scanner.scan( /\/\/.*$/ )
					# comments
				when m = scanner.scan( /(\s+|\n)/ )
					# whitespace and newlines
				when m = scanner.scan( /\{/ )
					tokens.push [:OBRACE, m]
				when m = scanner.scan( /\}/ )
					tokens.push [:EBRACE, m]
				when m = scanner.scan( /;/ )
					tokens.push [:SEMICOLON, m]
				when m = scanner.scan( /\d+/ )
					tokens.push [:NUMBER, m]
				when m = scanner.scan( /user/i )
					tokens.push [:USER, m]
				when m = scanner.scan( /automount/i )
					tokens.push [:AUTOMOUNT, m]
				when m = scanner.scan( /reconnect/i )
					tokens.push [:RECONNECT, m]
				when m = scanner.scan( /compress/i )
					tokens.push [:COMPRESS, m]
				when m = scanner.scan( /port/i )
					tokens.push [:PORT, m]
				when m = scanner.scan( /(true|1|yes)/i )
					tokens.push [:BOOL_TRUE, m]
				when m = scanner.scan( /(false|0|no)/i )
					tokens.push [:BOOL_FALSE, m]
				when m = scanner.scan( /".+?"/i )
					tokens.push [:STRING, m]
				when m = scanner.scan( /map/i )
					tokens.push [:MAP, m]
				when m = scanner.scan( /server/i )
					tokens.push [:SERVER, m]
				when m = scanner.scan( /./ )
					tokens.push [:UNMATCHED, m]
					puts "UNMATCHED #{m} after #{scanner.pre_match}"
			end
		end
		puts "tokenization ok"
		tokens.push [false, false]
		@last_value = yyparse( tokens, :each )
		puts "parse end... "
	end

	def on_error(error_token_id, error_value, value_stack)
			msg = "parse error "
			msg << "after #{value_stack.last} " if value_stack.length > 1
			#msg << "after #{value_stack.last} " unless value_stack.empty?
			msg << "on #{token_to_str(error_token_id)} #{error_value}"
			raise ParseError, msg
	end


---- footer ----

puts "GOO"

bigstr = ""
STDIN.read.split(/\n/).each do |a|
   puts "READING #{a}"
   bigstr = bigstr + a
end

puts "PARSING NOW..."

parser = MapParser.new
begin
	val = parser.parse( bigstr )
	print '= ', val, "\n"
	rescue ParseError
	puts $!
end