Moved things around
This commit is contained in:
32
mmql/engine/parsers/amount.go
Normal file
32
mmql/engine/parsers/amount.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
engine "github.com/tgckpg/mmqlengine/mmql/engine"
|
||||
stmtd "github.com/tgckpg/mmqlengine/mmql/statements"
|
||||
)
|
||||
|
||||
/*
|
||||
EXPECT: [Number] [Units]
|
||||
OR
|
||||
EXPECT: [FUNCTION]( ...params )
|
||||
*/
|
||||
|
||||
func AmountStatement( lexer *engine.Lexer ) ( istmt stmtd.IStatement, err error ) {
|
||||
stmt := stmtd.AmountStatement{}
|
||||
|
||||
val, err := lexer.ReadDecimal()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
stmt.SetValue( val )
|
||||
|
||||
unit, err := lexer.ReadAlpha()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
stmt.SetUnit( unit )
|
||||
|
||||
istmt = stmt
|
||||
return
|
||||
}
|
50
mmql/engine/parsers/amount_test.go
Normal file
50
mmql/engine/parsers/amount_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
engine "github.com/tgckpg/mmqlengine/mmql/engine"
|
||||
stmtd "github.com/tgckpg/mmqlengine/mmql/statements"
|
||||
)
|
||||
|
||||
type _p struct {
|
||||
amount float64
|
||||
unit string
|
||||
}
|
||||
|
||||
func TestAmountStatement( t *testing.T ) {
|
||||
lexer := engine.Lexer{}
|
||||
supportedStmts := map[string] func( *engine.Lexer ) ( stmtd.IStatement, error ) {
|
||||
"AMOUNT": AmountStatement,
|
||||
}
|
||||
lexer.SupportedStmts = &supportedStmts
|
||||
|
||||
read_oks := map[string] _p {
|
||||
"1 SHARES OF QQQ": _p{ 1, "SHARES" },
|
||||
"1 QQQ": _p{ 1, "QQQ" },
|
||||
"1 UNIT OF QQQ": _p{ 1, "UNIT" },
|
||||
}
|
||||
|
||||
readAmount := engine.LexerExpect{
|
||||
Statements: true,
|
||||
Keywords: false,
|
||||
Brackets: false,
|
||||
Quotes: false,
|
||||
Key: "AMOUNT",
|
||||
}
|
||||
|
||||
for k := range read_oks {
|
||||
lexer.SetReader( strings.NewReader( k ) )
|
||||
stmt, err := lexer.ReadStatement( &readAmount )
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
}
|
||||
|
||||
aStmt := any( stmt ).( stmtd.AmountStatement )
|
||||
p, _ := read_oks[ k ]
|
||||
if aStmt.Unit() != p.unit {
|
||||
t.Errorf( "Expected \"%s\", got \"%s\" instead", p.unit, aStmt.Unit() )
|
||||
}
|
||||
}
|
||||
}
|
96
mmql/engine/parsers/buy.go
Normal file
96
mmql/engine/parsers/buy.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
engine "github.com/tgckpg/mmqlengine/mmql/engine"
|
||||
stmtd "github.com/tgckpg/mmqlengine/mmql/statements"
|
||||
)
|
||||
|
||||
/*
|
||||
EXPECT: BUY
|
||||
THEN EXPECT: [AmountStatement] OF [FinancialInstrumentStatement]
|
||||
THEN EXPECT: FOR [AmountStatement]
|
||||
THEN EXPECT: FROM [ExchangeType]
|
||||
THEN OPT EXPECT: [ExchangeType]
|
||||
THEN OPT EXPECT: [AND|OR]
|
||||
THEN EXPECT: [ActionExpression]
|
||||
THEN OPT EXPECT: FOR EVERY
|
||||
THEN EXPECT: [AmountType] OF [FinancialInstrumentType]
|
||||
THEN EXPECT: [SOLD|BOUGHT] FROM [ExchangeType]
|
||||
*/
|
||||
|
||||
func BuyStatement( lexer *engine.Lexer ) ( istmt stmtd.IStatement, err error ) {
|
||||
orderStmt := stmtd.OrderStatement{}
|
||||
orderStmt.Action = "BUY"
|
||||
|
||||
// AmountStatement
|
||||
readAmount := engine.LexerExpect{
|
||||
Statements: true,
|
||||
Keywords: false,
|
||||
Brackets: false,
|
||||
Quotes: false,
|
||||
Key: "AMOUNT",
|
||||
}
|
||||
|
||||
_amountStmt, err := lexer.ReadStatement( &readAmount )
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
amountStmt := any( _amountStmt ).( stmtd.AmountStatement )
|
||||
orderStmt.SetAmount( &amountStmt )
|
||||
|
||||
var fiStmt stmtd.FinancialInstrumentStatement
|
||||
|
||||
// OF
|
||||
err = lexer.ReadKeyword( "OF" )
|
||||
if err != nil {
|
||||
// try read FOR
|
||||
err = lexer.ReadKeyword( "FOR" )
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// BUY 1 QQQ
|
||||
fiStmt := stmtd.FinancialInstrumentStatement{}
|
||||
fiStmt.Name = amountStmt.Unit()
|
||||
|
||||
// Equivalent to BUY 1 UNIT OF QQQ
|
||||
amountStmt.SetUnit( "UNITS" )
|
||||
} else {
|
||||
// BUY 1 UNIT OF QQQ
|
||||
readFI := engine.LexerExpect{
|
||||
Statements: true,
|
||||
Keywords: false,
|
||||
Brackets: false,
|
||||
Quotes: false,
|
||||
Key: "FINANCIAL_INSTRUMENT",
|
||||
}
|
||||
|
||||
_fiStmt, _err := lexer.ReadStatement( &readFI )
|
||||
if _err != nil {
|
||||
err = _err
|
||||
return
|
||||
}
|
||||
fiStmt = any( _fiStmt ).( stmtd.FinancialInstrumentStatement )
|
||||
|
||||
// FOR
|
||||
err = lexer.ReadKeyword( "FOR" )
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
orderStmt.SetFinancialInstrument( &fiStmt )
|
||||
|
||||
// FOR [AmountStatement]
|
||||
_forStmt, err := lexer.ReadStatement( &readAmount )
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
forStmt := any( _forStmt ).( stmtd.AmountStatement )
|
||||
orderStmt.SetFor( &forStmt )
|
||||
|
||||
istmt = orderStmt
|
||||
return
|
||||
}
|
57
mmql/engine/parsers/buy_test.go
Normal file
57
mmql/engine/parsers/buy_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
"testing"
|
||||
engine "github.com/tgckpg/mmqlengine/mmql/engine"
|
||||
stmtd "github.com/tgckpg/mmqlengine/mmql/statements"
|
||||
)
|
||||
|
||||
func TestBuyStatement( t *testing.T ) {
|
||||
lexer := engine.Lexer{}
|
||||
supportedStmts := map[string] func( *engine.Lexer ) ( stmtd.IStatement, error ) {
|
||||
"BUY": BuyStatement,
|
||||
"AMOUNT": AmountStatement,
|
||||
"FINANCIAL_INSTRUMENT": FinancialInstrumentStatement,
|
||||
}
|
||||
lexer.SupportedStmts = &supportedStmts
|
||||
|
||||
var stmt stmtd.OrderStatement
|
||||
_stmt, err := lexer.Parse( "BUY 1 SHARES OF QQQ FOR 10 USD FROM \"MyBrokerAccount\"" )
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
} else {
|
||||
stmt = any( _stmt ).( stmtd.OrderStatement )
|
||||
if stmt.Amount().Unit() != "SHARES" {
|
||||
t.Errorf( "Expected 1 SHARES Amount, got \"%s\" Amount", stmt.Amount().Unit() )
|
||||
}
|
||||
}
|
||||
|
||||
_stmt, err = lexer.Parse( "BUY 1 QQQ FOR MARKET_PRICE() FROM \"MyBrokerAccount\"" )
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
} else {
|
||||
stmt = any( _stmt ).( stmtd.OrderStatement )
|
||||
if stmt.Amount().Unit() != "UNITS" {
|
||||
t.Errorf( "Expected 1 UNITS Amount, got \"%s\" Amount", stmt.Amount().Unit() )
|
||||
}
|
||||
}
|
||||
|
||||
_, err = lexer.Parse( "BUY 1 QQQ FOR 10 USD FROM \"MyBrokerAccount\"" )
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
}
|
||||
|
||||
_, err = lexer.Parse( `
|
||||
BUY 1 SHARES OF BTC_ETF
|
||||
FOR 10 USD
|
||||
FROM "MyBrokerAccount"
|
||||
WITH LIMIT OF PURCHASING_POWER( "MyBrokerAccount", "QQQ" )
|
||||
FOR EVERY
|
||||
1 BTC OF USD_BTC SOLD
|
||||
FROM "CoinBase"
|
||||
` )
|
||||
if err != nil {
|
||||
t.Error( err )
|
||||
}
|
||||
}
|
26
mmql/engine/parsers/financial_instrument.go
Normal file
26
mmql/engine/parsers/financial_instrument.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
engine "github.com/tgckpg/mmqlengine/mmql/engine"
|
||||
stmtd "github.com/tgckpg/mmqlengine/mmql/statements"
|
||||
)
|
||||
|
||||
/*
|
||||
EXPECT: [NAME]
|
||||
OR
|
||||
EXPECT: [FUNCTION]( ...params )
|
||||
*/
|
||||
|
||||
func FinancialInstrumentStatement( lexer *engine.Lexer ) ( istmt stmtd.IStatement, err error ) {
|
||||
stmt := stmtd.FinancialInstrumentStatement{}
|
||||
|
||||
name, err := lexer.ReadAlpha()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
stmt.Name = name
|
||||
|
||||
istmt = stmt
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user