options_parser.bmx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. SuperStrict
  2. Import brl.map
  3. Import "stringbuffer_core.bmx"
  4. Global compilerOptions:TValues
  5. Function EvalOption:Int(line:String)
  6. If Not line Then
  7. Return True
  8. End If
  9. Local tok:TOptTokenizer = New TOptTokenizer.Create(line.ToLower())
  10. Local parser:TOptParser = New TOptParser.Create(tok, compilerOptions)
  11. Return parser.Eval()
  12. End Function
  13. Type TOptParser
  14. Field tokenizer:TOptTokenizer
  15. Field token:TOptToken
  16. Field values:TValues
  17. Method Create:TOptParser(tokenizer:TOptTokenizer, values:TValues)
  18. Self.tokenizer = tokenizer
  19. Self.values = values
  20. Return Self
  21. End Method
  22. Method Eval:Int()
  23. NextToke
  24. Local expr:TExpr = Parse()
  25. Return expr.Eval()
  26. End Method
  27. Method NextToke()
  28. token = tokenizer.NextToken()
  29. End Method
  30. Method Parse:TExpr()
  31. Return ParseOrExpr()
  32. End Method
  33. Method ParseOrExpr:TExpr()
  34. Local expr:TExpr = ParseAndExpr()
  35. Repeat
  36. If token.tokType = TOK_OR Then
  37. NextToke
  38. Local rhs:TExpr = ParseAndExpr()
  39. expr = New TBinaryExpr.Create(TOK_OR, expr, rhs)
  40. Else
  41. Return expr
  42. End If
  43. Forever
  44. Return expr
  45. End Method
  46. Method ParseAndExpr:TExpr()
  47. Local expr:TExpr = ParseCompareExpr()
  48. Repeat
  49. If token.tokType = TOK_AND Then
  50. NextToke
  51. Local rhs:TExpr = ParseNotExpr()
  52. expr = New TBinaryExpr.Create(TOK_AND, expr, rhs)
  53. Else
  54. Return expr
  55. End If
  56. Forever
  57. End Method
  58. Method ParseCompareExpr:TExpr()
  59. Local expr:TExpr = ParseNotExpr()
  60. Repeat
  61. If token.tokType = TOK_LT Or token.tokType = TOK_GT Or token.tokType = TOK_EQ Then
  62. NextToke
  63. Local rhs:TExpr = ParseNotExpr()
  64. expr = New TBinaryCompareExpr.Create(token.tokType, expr, rhs)
  65. Else
  66. Return expr
  67. End If
  68. Forever
  69. End Method
  70. Method ParseNotExpr:TExpr()
  71. If token.tokType = TOK_NOT Then
  72. NextToke
  73. Local expr:TExpr = ParseNotExpr()
  74. Return New TNotExpr.Create(expr)
  75. End If
  76. Return ParsePrimaryExpr()
  77. End Method
  78. Method ParsePrimaryExpr:TExpr()
  79. Local expr:TExpr
  80. Select token.tokType
  81. Case TOK_LPAREN
  82. NextToke
  83. expr = Parse()
  84. If token.tokType <> TOK_RPAREN Then
  85. Throw "Expected ')'"
  86. End If
  87. Case TOK_IDENT
  88. Local value:Int = values.Value(token.value)
  89. expr = New TIdentExpr.Create(token.value, value)
  90. NextToke
  91. Case TOK_RPAREN
  92. Throw "Unexpected ')'"
  93. End Select
  94. Return expr
  95. End Method
  96. End Type
  97. Type TOptToken
  98. Field tokType:Int
  99. Field value:String
  100. Method Create:TOptToken(tokType:Int, value:String)
  101. Self.tokType = tokType
  102. Self.value = value
  103. Return Self
  104. End Method
  105. End Type
  106. Type TOptTokenizer
  107. Field line:String
  108. Field pos:Int
  109. Method Create:TOptTokenizer(line:String)
  110. Self.line = line
  111. Return Self
  112. End Method
  113. Method NextToken:TOptToken()
  114. While True
  115. If pos = line.length
  116. Return New TOptToken.Create(TOK_EOL, Null)
  117. End If
  118. Local char:Int = line[pos]
  119. pos :+ 1
  120. If char = Asc("(") Then
  121. Return New TOptToken.Create(TOK_LPAREN, "(")
  122. Else If char = Asc(")") Then
  123. Return New TOptToken.Create(TOK_RPAREN, ")")
  124. Else If char = Asc("<") Then
  125. Return New TOptToken.Create(TOK_LT, "<")
  126. Else If char = Asc(">") Then
  127. Return New TOptToken.Create(TOK_GT, ">")
  128. Else If char = Asc("=") Then
  129. Return New TOptToken.Create(TOK_EQ, "=")
  130. Else If IsAlphaNumeric(char) Then
  131. Return NextIdentToken(char)
  132. Else If Not IsWhitespace(char) Then
  133. Throw "Unexpected character : " + Chr(char)
  134. End If
  135. Wend
  136. End Method
  137. Method NextIdentToken:TOptToken(char:Int)
  138. Local sb:TStringBuffer = TStringBuffer.Create(Chr(char))
  139. While True
  140. char = Peek()
  141. If Not IsAlphaNumeric(char) Then
  142. Exit
  143. End If
  144. pos :+ 1
  145. sb.Append(Chr(char))
  146. Wend
  147. Local token:String = sb.ToString().ToLower()
  148. Select token
  149. Case "not"
  150. Return New TOptToken.Create(TOK_NOT, token)
  151. Case "and"
  152. Return New TOptToken.Create(TOK_AND, token)
  153. Case "or"
  154. Return New TOptToken.Create(TOK_OR, token)
  155. Default
  156. Return New TOptToken.Create(TOK_IDENT, token)
  157. End Select
  158. End Method
  159. Method IsAlphaNumeric:Int(char:Int)
  160. Return (char >= Asc("A") And char <= Asc("Z")) Or (char >= Asc("a") And char <= Asc("z")) Or (char >= Asc("0") And char <= Asc("9")) Or char = Asc("_")
  161. End Method
  162. Method IsWhitespace:Int(char:Int)
  163. Return char = Asc(" ") Or char = Asc("~t")
  164. End Method
  165. Method Peek:Int()
  166. If pos < line.length Then
  167. Return line[pos]
  168. End If
  169. Return 0
  170. End Method
  171. End Type
  172. Type TExpr
  173. Method Eval:Int() Abstract
  174. End Type
  175. Type TNotExpr Extends TExpr
  176. Field expr:TExpr
  177. Method Create:TNotExpr(expr:TExpr)
  178. Self.expr = expr
  179. Return Self
  180. End Method
  181. Method Eval:Int()
  182. If Not expr Then
  183. Throw "Missing expression"
  184. End If
  185. Return Not expr.Eval()
  186. End Method
  187. End Type
  188. Type TBinaryExpr Extends TExpr
  189. Field op:Int
  190. Field lhs:TExpr
  191. Field rhs:TExpr
  192. Method Create:TBinaryExpr(op:Int, lhs:TExpr, rhs:TExpr)
  193. Self.op = op
  194. Self.rhs = rhs
  195. Self.lhs = lhs
  196. Return Self
  197. End Method
  198. Method Eval:Int()
  199. If Not lhs Or Not rhs Then
  200. Throw "Missing expression"
  201. End If
  202. Select op
  203. Case TOK_OR
  204. Return lhs.Eval() Or rhs.Eval()
  205. Case TOK_AND
  206. Return lhs.Eval() And rhs.Eval()
  207. End Select
  208. End Method
  209. End Type
  210. Type TBinaryCompareExpr Extends TBinaryExpr
  211. Method Eval:Int()
  212. If Not lhs Or Not rhs Then
  213. Throw "Missing expression"
  214. End If
  215. Select op
  216. Case TOK_LT
  217. Return lhs.Eval() < rhs.Eval()
  218. Case TOK_GT
  219. Return lhs.Eval() > rhs.Eval()
  220. Case TOK_EQ
  221. Return lhs.Eval() = rhs.Eval()
  222. End Select
  223. End Method
  224. End Type
  225. Type TIdentExpr Extends TExpr
  226. Field ident:String
  227. Field value:Int
  228. Method Create:TIdentExpr(ident:String, value:Int)
  229. Self.ident = ident
  230. Self.value = value
  231. Return Self
  232. End Method
  233. Method Eval:Int()
  234. Return value
  235. End Method
  236. End Type
  237. Type TInt
  238. Field value:Int
  239. Method Create:TInt(value:Int)
  240. Self.value = value
  241. Return Self
  242. End Method
  243. End Type
  244. Type TValues
  245. Field values:TMap = New TMap
  246. Method Add(key:String, value:Int)
  247. values.Insert(key, New TInt.Create(value))
  248. End Method
  249. Method Value:Int(key:String)
  250. Local obj:Object = values.ValueForKey(key)
  251. If obj Then
  252. Return TInt(obj).value
  253. End If
  254. Return 0
  255. End Method
  256. End Type
  257. Const TOK_IDENT:Int = 0
  258. Const TOK_NOT:Int = 1
  259. Const TOK_AND:Int = 2
  260. Const TOK_OR:Int = 3
  261. Const TOK_LPAREN:Int = 4
  262. Const TOK_RPAREN:Int = 5
  263. Const TOK_EOL:Int = 6
  264. Const TOK_LT:Int = 7
  265. Const TOK_GT:Int = 8
  266. Const TOK_EQ:Int = 9