Skip to content

Instantly share code, notes, and snippets.

@randrews
Created August 23, 2009 00:38
Show Gist options
  • Save randrews/173065 to your computer and use it in GitHub Desktop.
Save randrews/173065 to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
# The original thing required rubygems and json_pure for some reason, even though it defines its own json parser.
# I think I had some trouble getting gems to work, which is why I wrote my own in the first place.
# --RBA 2009-08-22
# require 'rubygems'
# require 'json_pure'
def readWord (stream=STDIN,first=nil)
return false if stream.eof?
state=:start
str=''
str+=first if first!=nil
stream.each_byte{|char|
char=char.chr
if state==:start #####################################
next unless char =~/[\w]/
str+=char
state=:scan
elsif state==:scan #####################################
unless char=~/[\-\w]/
stream.ungetc(char[0])
return str
end
str+=char
end
}
end
def readJson (stream=STDIN)
return false if stream.eof?
state=:start
stack=[]
str=''
delim=''
stream.each_byte{|char|
char=char.chr
if state==:start #####################################
next if char!='[' && char!='{'
str+=char
stack<<char
state=:scan
elsif state==:scan #####################################
str+=char
stack<<char if char=='[' || char=='{'
stack.pop if (char==']' && stack[-1]=='[') || (char=='}' && stack[-1]=='{')
if stack.empty?
return str
end
if char=="'" || char=="\""
state=:string
delim=char
end
elsif state==:string #####################################
str+=char
state=:slash if char=='\\'
state=:scan if char==delim
elsif state==:slash #####################################
str+=char
state=:string
end #####################################
}
return false
end
def white? (char)
char==" " || char=="\t" || char==$/
end
def parseJson(stream=STDIN)
return false if stream.eof?
state=:start
stream.each_byte{|byte|
char=byte.chr
if state==:start
next if white?(char)
if char=="\#"
state=:comment
else
return readValue(stream, char)
end
elsif state==:comment
next if char!=$/
state=:start
end
}
end
def readValue(stream, first=nil)
char=nil
if first
char=first
else
char=stream.getc
end
#print '-',char,'-',$/
if char==nil
return nil
elsif char=='"'
return readString(stream,char)
elsif char=='['
return readArray(stream,char)
elsif char=='{'
return readObject(stream,char)
elsif char=~/[.0-9\-]/
return readNumber(stream,char)
elsif char =~ /[a-zA-Z_]/
return readWord(stream, char)
end
end
def readNumber(stream, first=nil)
str=''
state=:start
if first
str+=first
state=:digit
end
stream.each_byte{|b|
char=b.chr
if state==:start
next if white?(char)
str+=char
state=:digit
elsif state==:digit
unless char=~/[0-9\.]/
stream.ungetc(char[0])
if(str[0]=='-')
return str.to_f
else
return str.to_i
end
end
str+=char
end
}
end
def readArray(stream, first=nil)
state=:start
state=:opened if first=='['
obj=[]
stream.each_byte{|b|
char=b.chr
if state==:start
next if char!='['
state=:opened
elsif state==:opened
next if white?(char)
obj<<readValue(stream, char)
state=:after
elsif state==:after
return obj if char==']'
next if char!=','
state=:opened
end
}
end
def readObject(stream, first=nil)
state=:start
state=:opened if first=='{'
obj={}
key=nil
val=nil
stream.each_byte{|b|
char=b.chr
if state==:start
next if char!='{'
state=:opened
elsif state==:opened
next if char!='"'
key=readString(stream, char)
state=:gotkey
elsif state==:gotkey
next if char!=':'
state=:readval
elsif state==:readval
next if white?(char)
val=readValue(stream,char)
obj[key]=val
state=:after
elsif state==:after
return obj if char=='}'
next if char!=','
state=:opened
end
}
return "foo!"
end
def readString(stream,first=nil)
state=:start
str=''
state=:string if first=='"'
stream.each_byte{|b|
char=b.chr
if state==:start
next if char!='"'
state=:string
elsif state==:string
return str if char=='"'
str+=char
state=:slash if char=="\\"
elsif state==:slash
str+=char
state==:string
end
}
end
def readMessage(stream=STDIN)
return nil if stream.eof?
command=readWord(stream)
params=parseJson(stream)
unless command && params
return nil
end
return {:command=>command, :params=>params}
end
cmd=readMessage(DATA)
while(cmd)
print cmd[:command],"\n"
cmd[:params].each_pair{|k,v|
print "\t",k,"=",v,"\n"
}
cmd=readMessage(DATA)
end
# Some test data embedded in the file. This was a separate file, I put it in here to make it easier to make a Gist out of
# --RBA 2009-08-22
__END__
create {"name":"main",
"type":"window",
"messages":"none",
"title":"Universal Greeting Facilitator"}
create {"name":"lbl",
"type":"label",
"messages":"none",
"text":"Hello, World!"}
create {"name":"exitbtn",
"type":"button",
"messages":"pressed",
"label":"Done"}
layout {"name":"main",
"layout":"grid",
"rows":"2",
"columns":"1"}
place {"name":"lbl",
"parent":"main",
"row":"0",
"column":"0"}
place {"name":"exitbtn",
"parent":"main",
"row":"1",
"column":"0"}
tell {"name":"main",
"action":"show"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment