Created
August 23, 2009 00:38
-
-
Save randrews/173065 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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