November 30, 2020, 01:58:58 AM

Author Topic: [bmx] Parser by CS_TBL [ 1+ years ago ]  (Read 549 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] Parser by CS_TBL [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : Parser
Author : CS_TBL
Posted : 1+ years ago

Description : simple, minimalistic, but handy parser

Code :
Code: BlitzMax
  1. 'Strict
  2. Type Parser
  3.  
  4.         Rem
  5.        
  6. A very basic command/value parser, but often sufficient.
  7.  
  8. A single string holds the script, and that script can be as ugly as uglyness can be, it could
  9. come from textareas, files etc. The idea is that everything can be parsed, without bugging the
  10. user with (runtime-)errors, caused by a bad script. If you create a texture-generator, the
  11. result would be that the texture would look wrong, but never (runtime-)errors, or annoying popups
  12. you need to click away.
  13.  
  14. The syntax for the script is always:
  15. <command><value> <command><value> <command><value> .. ..
  16.  
  17. <Command>
  18. - A single char, anyone of these: QWERTYUIOPASDFGHJKLZXCVBNM`!@#$%^&*()_+[]:;'|,/<>?"
  19. - Exluded are the tilde ~ and both braces { }
  20. - Any other character (including spaces) is wiped out.
  21. - az will become uppercase
  22.  
  23. <Value>
  24. - is any double.
  25. - ugly written values will be souped-up
  26. - if no value is given, value=0
  27.  
  28.  
  29. an example:
  30.  
  31. a0b100c-3d9.9
  32.  
  33. These are 4 commands (a b c and d), and 4 values (1 100 -3 and 9.9).
  34. (values intentially rounded for readablity)
  35.  
  36. The same script could also've been written as:
  37.  
  38. ab1 00c -----3... d9.9----
  39.  
  40. Groundrules for Double souping-up:
  41. - the most right dot will be the decimal dot
  42. - the amount of minus-signs defines whether it's positive or negative
  43.  
  44. So, 10000.00 could be written as 10.000.00, and 3-3 -..-..- 3-3 means -33.33
  45.  
  46. {} are used for commenting .. but very basic again. When the parser sees a { it'll ignore
  47. the next characters until there's a } again.. no support for nesting. Advantage is that with no
  48. further use of commenting in a large script, a single { comments the rest without the need of a
  49. closing }.
  50.  
  51. usage:
  52.  
  53.         MyParser = CreateParser()
  54.  
  55.         MyParser.Parse(MyScript$)
  56.         AmountOfCommands:Int = MyParser.Commands()
  57.         MyCommand$ = MyParser.GetCommand(commandnumber)
  58.         MyValue:Double = MyParser.GetValue(commandnumber)
  59.  
  60.  
  61.  
  62.  
  63.  
  64. made by:
  65.  
  66.         CS_TBL, 2nd xmas-day 2005 :P
  67.  
  68.                
  69.         EndRem
  70.  
  71.         Field bank:TBank
  72.        
  73.         Method Prepare$(s$)
  74.                 Local n$
  75.                 Local c$
  76.                 Local t:Short
  77.                 Local comment:Byte
  78.                
  79.                 ' allow ASCIIs 33..125
  80.                 For t=0 To Len(s$)-1
  81.                         c$=Mid$(s$,t+1,1)
  82.                         If Asc(c$)>32 And Asc(c$)<126 n$=n$+Upper$(c$)
  83.                 Next
  84.                
  85.                 s$=n$
  86.                 n$=""
  87.                 t=0
  88.                 For t=0 To Len(s$)-1
  89.                         c$=Mid$(s$,1+t,1)
  90.                         If c$="{" comment=True
  91.                         If c$="}" comment=False
  92.                        
  93.                         If Not comment
  94.                                 If c$<>"}" n$=n$+c$
  95.                         EndIf
  96.                 Next
  97.                
  98.                 Return n$
  99.         End Method
  100.        
  101.         Method Text2Double:Double(a$)
  102.                 If a$="" Return 0
  103.                 Local l:Short
  104.                 Local az$
  105.                 Local m:Short
  106.                 Local negative:Byte
  107.                 Local found:Byte
  108.                 Local foundpos:Short
  109.                 Local t:Short
  110.        
  111.                 l=Len(a$)
  112.        
  113.                 ' do we have an odd amount of '-' ?
  114.                 az$=Replace$(a$,"-","")
  115.                 m=l-Len(az$)
  116.        
  117.                 ' yes? it's a negative number!
  118.                 If m Mod 2 negative=True
  119.                
  120.        
  121.                 ' scan the value (without - ) For dots
  122.                 For t=Len(az$)-1 To 0 Step -1
  123.                         If Not found
  124.                                 If Mid$(az$,t+1,1)="."
  125.                                         found=True
  126.                                         foundpos=(Len(az$)-1)-t
  127.                                 EndIf
  128.                         EndIf
  129.                 Next
  130.                 ' so we found the most-Right dot, If any..
  131.        
  132.        
  133.                 ' get rid of all the dots Then
  134.                 az$=Replace$(az$,".","")
  135.        
  136.                 l=Len(az$)
  137.        
  138.                 If found ' place 1 dot back
  139.                         az$=Left$(az$,l-foundpos)+"."+Right$(az$,foundpos)
  140.                 EndIf
  141.        
  142.                 If negative
  143.                         az$="-"+az$
  144.                 EndIf
  145.        
  146.                 Return az$.todouble()
  147.                
  148.         End Method
  149.        
  150.         Method Parse(a$)
  151.                 Local t:Short
  152.                 Local valuefound:Byte
  153.                 Local number$
  154.                 Local ch$
  155.                 Local parselen:Short
  156.                 Local bs:Int
  157.                 Local char$
  158.                
  159.                 a$=Prepare$(a$)
  160.                 If a$="" Return
  161.                
  162.                 ResizeBank bank,0
  163.                
  164.                 parselen=Len(a$)
  165.  
  166.                 Repeat
  167.                         char$=Mid$(a$,t+1,1)
  168.                        
  169.                         If Instr("QWERTYUIOPASDFGHJKLZXCVBNM`!@#$%^&*()_+[]:;'|,/<>?"+Chr$(34),char$)
  170.                                 t:+1
  171.                                 valuefound=0
  172.                                 number$=""
  173.                                 Repeat
  174.                                         ch$=Mid$(a$,t+1,1)
  175.                                         If Instr("1234567890-.",ch$)
  176.                                                 number$=number$+ch$
  177.                                                 t:+1
  178.                                         Else
  179.                                                 valuefound=True
  180.                                                 t:-1
  181.                                         EndIf
  182.                                         If t>=parselen valuefound=True
  183.                                 Until valuefound
  184.                                
  185.                                 bs=BankSize(bank)
  186.                                 ResizeBank bank,bs+9
  187.                                 bs:+9
  188.  
  189.                                
  190.                                 PokeByte bank,bs-9,Asc(char$)
  191.                                 PokeDouble bank,bs-8,Text2Double(number$)
  192.                                
  193.                         EndIf
  194.                        
  195.                         t:+1
  196.                        
  197.                 Until t>=parselen
  198.                
  199.                
  200.         End Method
  201.        
  202.         Method Commands:Int()
  203.                 Return BankSize(bank)/9
  204.         End Method
  205.        
  206.         Method GetCommand$(which:Short)
  207.                 Local t:Short
  208.                 If which<0 which=0
  209.                 t=Commands()
  210.                 If which=>t which=t-1
  211.                 Return Chr$(PeekByte(bank,which*9))
  212.         End Method
  213.  
  214.         Method GetValue:Double(which:Short)
  215.                 Local t:Short
  216.                 If which<0 which=0
  217.                 t=Commands()
  218.                 If which=>t which=t-1
  219.                 Return PeekDouble(bank,which*9+1)
  220.         End Method
  221.        
  222. End Type
  223.  
  224. Function CreateParser:Parser()
  225.         Local a:Parser=New Parser
  226.         a.bank=CreateBank(0)
  227.         Return a
  228. End Function
  229.  
  230.  
  231. Rem ' example..
  232.  
  233. Local a:Parser=CreateParser()
  234.  
  235.  
  236. a.Parse " a   34.1 1       b    9 4 c4d5.3   e-99.    3f     30.0 00.  76"
  237.  
  238. For Local t:Byte=0 Until a.Commands()
  239.         DebugLog a.GetCommand(t)
  240.         DebugLog "    "+a.GetValue(t)
  241. Next
  242.  
  243. Notify "^_^"
  244.  
  245.  
  246.  
  247. ' and again..
  248.  
  249. a.Parse "3{1373}}}Blitz{GUI} rules { b()()bs!"
  250.  
  251. For Local t:Byte=0 Until a.Commands()
  252.         DebugLog a.GetCommand(t)
  253.         DebugLog "    "+a.GetValue(t)
  254. Next
  255.  
  256. Notify "^_^"
  257.  
  258. End
  259.  
  260. EndRem


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal