Nestharus
o-o
- Reaction score
- 84
released:
parser http://www.thehelper.net/forums/showthread.php?t=152352
Cmd http://www.thehelper.net/forums/showthread.php?t=152356
So this is the current one-
http://www.thehelper.net/forums/showthread.php?t=140936
I don't like it... for example, it's many isType and getType methods irritate me and the fact that it couples up the parser and the command manager just seems like an extremely poor design to me >.<..
So, I've been working on a 2 part project-
parser (highly customizable) (done)
command framework (support for different shells and etc)
The parser includes a string stack object that will automatically split a string up into a stack given a delimhttp://www.thehelper.net/forums/forumdisplay.php?f=109iter, a typeof to automatically infer the data type of a given string ('' is treated as ascii and rest are inferred based upon the values). For the most part, types fit into other types. For example, an integer can be treated as a real or a string (follows this hierarchy on data types).
names can also be printed given a type id
The typeof method automatically infers types (as I said above)
Obviously I'm still going to be doing some more stuff, but this is how I believe a Parser should be designed ; |. CommandParser is designed in such a way that I refuse to use it, lol.
also, I'm going to do different build strings for the StringStack struct (single argument builds for ripping specific types out of the string and etc).
example of use (with just the parser) (I know I have a ton of extra locals, lol) (uses default delimiter on the StringStack creation)
ripper code
for single argument commands (provides more flexibility)
and how you might use the above
[ljass]local string arg = StringType.rip(GetEventPlayerChatString(), StringType.ASCII)[/ljass]
parser http://www.thehelper.net/forums/showthread.php?t=152352
Cmd http://www.thehelper.net/forums/showthread.php?t=152356
So this is the current one-
http://www.thehelper.net/forums/showthread.php?t=140936
I don't like it... for example, it's many isType and getType methods irritate me and the fact that it couples up the parser and the command manager just seems like an extremely poor design to me >.<..
So, I've been working on a 2 part project-
parser (highly customizable) (done)
command framework (support for different shells and etc)
The parser includes a string stack object that will automatically split a string up into a stack given a delimhttp://www.thehelper.net/forums/forumdisplay.php?f=109iter, a typeof to automatically infer the data type of a given string ('' is treated as ascii and rest are inferred based upon the values). For the most part, types fit into other types. For example, an integer can be treated as a real or a string (follows this hierarchy on data types).
JASS:
names can also be printed given a type id
JASS:
The typeof method automatically infers types (as I said above)
JASS:
/////
public static method typeof takes string val returns integer
local integer length
local string char
local integer curType = NULL
local string boolChecker
local boolean foundDecimal
//make sure not null
if (val != null) then
set curType = BOOLEAN
//check to see if boolean
set boolChecker = StringCase(val, false)
if (boolChecker != "true" and boolChecker != "false") then
set length = StringLength(val)
set curType = ASCII
//check to see if ascii integer
if ((length != 3 and length != 6) or (SubString(val, 0, 1) != "039;" or SubString(val, length-1, length) != "039;")) then
set curType = INTEGER
//if curType can't be determined at this point, have to parse it
set foundDecimal = false
loop
exitwhen length == 0
set char = SubString(val, length-1, length)
if (char != "0" and char != "1" and char != "2" and char != "3" and char != "4" and char != "5" and char != "6" and char != "7" and char != "8" and char != "9") then
if (char == "." and not foundDecimal) then
set curType = REAL
set foundDecimal = true
else
return STRING //no more parsing necessary
endif
endif
set length = length - 1
endloop
endif
endif
endif
return curType
endmethod
Obviously I'm still going to be doing some more stuff, but this is how I believe a Parser should be designed ; |. CommandParser is designed in such a way that I refuse to use it, lol.
also, I'm going to do different build strings for the StringStack struct (single argument builds for ripping specific types out of the string and etc).
example of use (with just the parser) (I know I have a ton of extra locals, lol) (uses default delimiter on the StringStack creation)
JASS:
struct tester extends array
private static trigger t = CreateTrigger()
private static string array typeName
private static method test takes nothing returns boolean
//call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, SubString(GetEventPlayerChatString(), 0, 1))
//call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, SubString(GetEventPlayerChatString(), StringLength(GetEventPlayerChatString())-1, StringLength(GetEventPlayerChatString())))
local StringStack stringStack = StringStack.create(GetEventPlayerChatString())
local StringStack node = stringStack
local integer stringType
local boolean b
local integer a
local integer i
local real r
local string s
local string bs
local string as
local string is
local string rs
local string ss
local string value
loop
exitwhen node == 0
set value = node.value
set stringType = StringType.typeof(value)
if (stringType == StringType.NULL) then
set s = value
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + s)
elseif (stringType == StringType.BOOLEAN) then
set b = StringType.S2B(value)
set bs = StringType.B2S(b)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + bs)
elseif (stringType == StringType.ASCII) then
set a = StringType.S2A(value)
set as = StringType.A2S(a)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + as)
elseif (stringType == StringType.INTEGER) then
set i = S2I(value)
set is = I2S(i)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + is)
elseif (stringType == StringType.REAL) then
set r = S2R(value)
set rs = R2S(r)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + rs)
elseif (stringType == StringType.STRING) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + value)
endif
//set node = node.next
set node = node.pop()
endloop
//call stringStack.destroy()
return false
endmethod
private static method onInit takes nothing returns nothing
call TriggerRegisterPlayerChatEvent(t, Player(0), "", false)
call TriggerAddCondition(t, Condition(function thistype.test))
endmethod
endstruct
ripper code
for single argument commands (provides more flexibility)
JASS:
////
//rips out a single argument given a type
//slow but extremely flexible
public static method rip takes string val, integer typeToRip returns string
local string arg = ""
local integer length
local integer count
local string char
local integer argLength
local integer boolCount
local boolean foundDecimal
if (val != null) then
set length = StringLength(val)
set count = 0
//rip null, which is easy, lol
if (typeToRip == StringType.NULL) then
set arg = null
//rip boolean, which tries to piece together straight** chars that could build boolean
elseif (typeToRip == StringType.BOOLEAN) then
set boolCount = 0
loop
exitwhen count == length
set char = SubString(val, count, count+1)
if (boolCount == 0) then
if (char == boolChars[trueChar]) then
set boolCount = trueChar+1
set arg = char
elseif (char == boolChars[falseChar]) then
set boolCount = falseChar+1
set arg = char
endif
elseif (char == boolChars[boolCount]) then
set arg = arg + char
set boolCount = boolCount + 1
exitwhen arg == "true" or arg == "false"
else
set boolCount = 0
set arg = ""
endif
set count = count + 1
endloop
if (arg != "true" and arg != "false") then
set arg = null
endif
//rip out an ascii value, which rips out the first 3 to 6 possible chars it comes across
elseif (typeToRip == StringType.ASCII) then
set foundDecimal = false //found ' ?
set argLength = 0
loop
exitwhen count == length or argLength == 6
set char = SubString(val, count, count+1)
set argLength = StringLength(arg)
//find start
if (argLength == 0 or argLength == 5 and char == "039;") then
set arg = arg + "039;"
elseif (argLength > 0 and argLength < 5) then
if (argLength == 2 and char == "039;") then
set foundDecimal = true
endif
set arg = arg + char
endif
set count = count + 1
endloop
set argLength = StringLength(arg)
//if maxed ascii and no final "'", check for previous one
if (argLength == 5 and foundDecimal) then
set arg = SubString(arg, 0, 2) + "039;"
elseif (argLength != 6 or (argLength != 3 and SubString(arg, argLength-1, argLength) != "039;")) then
set arg = null
endif
//rips out a plain old integer
elseif (typeToRip == StringType.INTEGER) then
loop
exitwhen count == length
set char = SubString(val, count, count+1)
if (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
set arg = arg + char
endif
set count = count + 1
endloop
if (arg == "") then
set arg = null
endif
//rips out a real
elseif (typeToRip == StringType.REAL) then
set foundDecimal = false
loop
exitwhen count == length
set char = SubString(val, count, count+1)
if (char == "." and not foundDecimal) then
set foundDecimal = true
set arg = arg + char
elseif (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
set arg = arg + char
endif
set count = count + 1
endloop
if (arg == "") then
set arg = null
endif
else
set arg = val
endif
endif
return arg
endmethod
and how you might use the above
[ljass]local string arg = StringType.rip(GetEventPlayerChatString(), StringType.ASCII)[/ljass]