123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- SuperStrict
- Import brl.map
- Import "stringbuffer_core.bmx"
- Global compilerOptions:TValues
- Function EvalOption:Int(line:String)
- If Not line Then
- Return True
- End If
- Local tok:TOptTokenizer = New TOptTokenizer.Create(line.ToLower())
- Local parser:TOptParser = New TOptParser.Create(tok, compilerOptions)
- Return parser.Eval()
- End Function
- Type TOptParser
- Field tokenizer:TOptTokenizer
- Field token:TOptToken
-
- Field values:TValues
-
- Method Create:TOptParser(tokenizer:TOptTokenizer, values:TValues)
- Self.tokenizer = tokenizer
- Self.values = values
- Return Self
- End Method
- Method Eval:Int()
- NextToke
- Local expr:TExpr = Parse()
- Return expr.Eval()
- End Method
- Method NextToke()
- token = tokenizer.NextToken()
- End Method
- Method Parse:TExpr()
- Return ParseOrExpr()
- End Method
-
- Method ParseOrExpr:TExpr()
- Local expr:TExpr = ParseAndExpr()
- Repeat
- If token.tokType = TOK_OR Then
- NextToke
- Local rhs:TExpr = ParseAndExpr()
- expr = New TBinaryExpr.Create(TOK_OR, expr, rhs)
- Else
- Return expr
- End If
- Forever
- Return expr
- End Method
-
- Method ParseAndExpr:TExpr()
- Local expr:TExpr = ParseCompareExpr()
- Repeat
- If token.tokType = TOK_AND Then
- NextToke
- Local rhs:TExpr = ParseNotExpr()
- expr = New TBinaryExpr.Create(TOK_AND, expr, rhs)
- Else
- Return expr
- End If
- Forever
- End Method
- Method ParseCompareExpr:TExpr()
- Local expr:TExpr = ParseNotExpr()
- Repeat
- If token.tokType = TOK_LT Or token.tokType = TOK_GT Or token.tokType = TOK_EQ Then
- NextToke
- Local rhs:TExpr = ParseNotExpr()
- expr = New TBinaryCompareExpr.Create(token.tokType, expr, rhs)
- Else
- Return expr
- End If
- Forever
- End Method
-
- Method ParseNotExpr:TExpr()
- If token.tokType = TOK_NOT Then
- NextToke
- Local expr:TExpr = ParseNotExpr()
- Return New TNotExpr.Create(expr)
- End If
-
- Return ParsePrimaryExpr()
- End Method
-
- Method ParsePrimaryExpr:TExpr()
- Local expr:TExpr
-
- Select token.tokType
- Case TOK_LPAREN
- NextToke
- expr = Parse()
- If token.tokType <> TOK_RPAREN Then
- Throw "Expected ')'"
- End If
- Case TOK_IDENT
- Local value:Int = values.Value(token.value)
- expr = New TIdentExpr.Create(token.value, value)
- NextToke
- Case TOK_RPAREN
- Throw "Unexpected ')'"
- End Select
-
- Return expr
- End Method
-
- End Type
- Type TOptToken
- Field tokType:Int
- Field value:String
-
- Method Create:TOptToken(tokType:Int, value:String)
- Self.tokType = tokType
- Self.value = value
- Return Self
- End Method
-
- End Type
- Type TOptTokenizer
-
- Field line:String
- Field pos:Int
- Method Create:TOptTokenizer(line:String)
- Self.line = line
- Return Self
- End Method
- Method NextToken:TOptToken()
- While True
- If pos = line.length
- Return New TOptToken.Create(TOK_EOL, Null)
- End If
-
- Local char:Int = line[pos]
-
- pos :+ 1
-
- If char = Asc("(") Then
- Return New TOptToken.Create(TOK_LPAREN, "(")
- Else If char = Asc(")") Then
- Return New TOptToken.Create(TOK_RPAREN, ")")
- Else If char = Asc("<") Then
- Return New TOptToken.Create(TOK_LT, "<")
- Else If char = Asc(">") Then
- Return New TOptToken.Create(TOK_GT, ">")
- Else If char = Asc("=") Then
- Return New TOptToken.Create(TOK_EQ, "=")
- Else If IsAlphaNumeric(char) Then
- Return NextIdentToken(char)
- Else If Not IsWhitespace(char) Then
- Throw "Unexpected character : " + Chr(char)
- End If
- Wend
- End Method
-
- Method NextIdentToken:TOptToken(char:Int)
- Local sb:TStringBuffer = TStringBuffer.Create(Chr(char))
-
- While True
- char = Peek()
- If Not IsAlphaNumeric(char) Then
- Exit
- End If
-
- pos :+ 1
- sb.Append(Chr(char))
- Wend
-
- Local token:String = sb.ToString().ToLower()
-
- Select token
- Case "not"
- Return New TOptToken.Create(TOK_NOT, token)
- Case "and"
- Return New TOptToken.Create(TOK_AND, token)
- Case "or"
- Return New TOptToken.Create(TOK_OR, token)
- Default
- Return New TOptToken.Create(TOK_IDENT, token)
- End Select
- End Method
-
- Method IsAlphaNumeric:Int(char:Int)
- 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("_")
- End Method
-
- Method IsWhitespace:Int(char:Int)
- Return char = Asc(" ") Or char = Asc("~t")
- End Method
-
- Method Peek:Int()
- If pos < line.length Then
- Return line[pos]
- End If
-
- Return 0
- End Method
-
- End Type
- Type TExpr
- Method Eval:Int() Abstract
- End Type
- Type TNotExpr Extends TExpr
- Field expr:TExpr
-
- Method Create:TNotExpr(expr:TExpr)
- Self.expr = expr
- Return Self
- End Method
-
- Method Eval:Int()
- If Not expr Then
- Throw "Missing expression"
- End If
- Return Not expr.Eval()
- End Method
-
- End Type
- Type TBinaryExpr Extends TExpr
- Field op:Int
- Field lhs:TExpr
- Field rhs:TExpr
- Method Create:TBinaryExpr(op:Int, lhs:TExpr, rhs:TExpr)
- Self.op = op
- Self.rhs = rhs
- Self.lhs = lhs
- Return Self
- End Method
-
- Method Eval:Int()
- If Not lhs Or Not rhs Then
- Throw "Missing expression"
- End If
- Select op
- Case TOK_OR
- Return lhs.Eval() Or rhs.Eval()
- Case TOK_AND
- Return lhs.Eval() And rhs.Eval()
- End Select
- End Method
-
- End Type
- Type TBinaryCompareExpr Extends TBinaryExpr
-
- Method Eval:Int()
- If Not lhs Or Not rhs Then
- Throw "Missing expression"
- End If
- Select op
- Case TOK_LT
- Return lhs.Eval() < rhs.Eval()
- Case TOK_GT
- Return lhs.Eval() > rhs.Eval()
- Case TOK_EQ
- Return lhs.Eval() = rhs.Eval()
- End Select
- End Method
-
- End Type
- Type TIdentExpr Extends TExpr
- Field ident:String
- Field value:Int
- Method Create:TIdentExpr(ident:String, value:Int)
- Self.ident = ident
- Self.value = value
- Return Self
- End Method
-
- Method Eval:Int()
- Return value
- End Method
-
- End Type
- Type TInt
- Field value:Int
- Method Create:TInt(value:Int)
- Self.value = value
- Return Self
- End Method
- End Type
- Type TValues
- Field values:TMap = New TMap
-
- Method Add(key:String, value:Int)
- values.Insert(key, New TInt.Create(value))
- End Method
-
- Method Value:Int(key:String)
- Local obj:Object = values.ValueForKey(key)
- If obj Then
- Return TInt(obj).value
- End If
- Return 0
- End Method
-
- End Type
- Const TOK_IDENT:Int = 0
- Const TOK_NOT:Int = 1
- Const TOK_AND:Int = 2
- Const TOK_OR:Int = 3
- Const TOK_LPAREN:Int = 4
- Const TOK_RPAREN:Int = 5
- Const TOK_EOL:Int = 6
- Const TOK_LT:Int = 7
- Const TOK_GT:Int = 8
- Const TOK_EQ:Int = 9
|