144 lines
3.1 KiB
Text
144 lines
3.1 KiB
Text
|
|
||
|
class MapParser
|
||
|
rule
|
||
|
|
||
|
commands
|
||
|
: commands command SEMICOLON { puts "GOT A COMMAND" }
|
||
|
| /* none */ { result = 0 }
|
||
|
|
||
|
command
|
||
|
: global_blk
|
||
|
| server_blk
|
||
|
|
||
|
server_blk
|
||
|
: SERVER SEP STRING SEP OBRACE server_opts EBRACE
|
||
|
: SERVER SEP STRING OBRACE server_opts EBRACE
|
||
|
|
||
|
global_blk
|
||
|
: GLOBAL OBRACE global_opts EBRACE
|
||
|
|
||
|
server_opts
|
||
|
: server_opts server_opt SEMICOLON
|
||
|
| /* none */ { result = 0 }
|
||
|
|
||
|
server_opt
|
||
|
: user_opt
|
||
|
| port_opt
|
||
|
| automount_opt
|
||
|
| compress_opt
|
||
|
| reconnect_opt
|
||
|
|
||
|
user_opt
|
||
|
: USER QUOTE STRING QUOTE
|
||
|
|
||
|
port_opt
|
||
|
: PORT INTEGER
|
||
|
|
||
|
automount_opt
|
||
|
: AUTOMOUNT boolean { puts ( "AUTOMOUNT => " + val[1] ) }
|
||
|
|
||
|
compress_opt
|
||
|
: COMPRESS boolean { puts ( "COMPRESS => " + val[1] ) }
|
||
|
|
||
|
reconnect_opt
|
||
|
: RECONNECT boolean { puts ( "RECONNECT => " + val[1] ) }
|
||
|
|
||
|
boolean
|
||
|
: BOOL_TRUE { result = true }
|
||
|
| BOOL_FALSE { 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
|
||
|
tokens.push [:SEP, m]
|
||
|
when m = scanner.scan( /(\s+|\n)/ )
|
||
|
# whitespace and newlines
|
||
|
tokens.push [:SEP, m]
|
||
|
when m = scanner.scan( /;/ )
|
||
|
tokens.push [:SEMICOLON, m]
|
||
|
when m = scanner.scan( /\d+/ )
|
||
|
tokens.push [:NUMBER, m]
|
||
|
when m = scanner.scan( /\{/ )
|
||
|
tokens.push [:OBRACE, m]
|
||
|
when m = scanner.scan( /\}/ )
|
||
|
tokens.push [:EBRACE, 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
|