diff --git a/grammar.go b/grammar.go index a58d806..48f88e6 100644 --- a/grammar.go +++ b/grammar.go @@ -438,318 +438,318 @@ func (p *StockCodeParser) Init(options ...func(*StockCodeParser) error) error { position, tokenIndex = position5, tokenIndex5 { position13 := position + if buffer[position] != rune('$') { + goto l12 + } + position++ + if !_rules[ruleStockName]() { + goto l12 + } + if buffer[position] != rune('(') { + goto l12 + } + position++ { position14, tokenIndex14 := position, tokenIndex - if buffer[position] != rune('$') { + if !_rules[ruleCNMarket]() { goto l15 } + if !_rules[ruleACode]() { + goto l15 + } + goto l14 + l15: + position, tokenIndex = position14, tokenIndex14 + if !_rules[ruleHKMarket]() { + goto l16 + } + { + position17 := position + { + position18, tokenIndex18 := position, tokenIndex + if buffer[position] != rune('H') { + goto l19 + } + position++ + if buffer[position] != rune('S') { + goto l19 + } + position++ + if buffer[position] != rune('T') { + goto l19 + } + position++ + if buffer[position] != rune('E') { + goto l19 + } + position++ + if buffer[position] != rune('C') { + goto l19 + } + position++ + if buffer[position] != rune('H') { + goto l19 + } + position++ + goto l18 + l19: + position, tokenIndex = position18, tokenIndex18 + if buffer[position] != rune('H') { + goto l16 + } + position++ + if buffer[position] != rune('S') { + goto l16 + } + position++ + if buffer[position] != rune('I') { + goto l16 + } + position++ + } + l18: + add(ruleHSCODE, position17) + } + goto l14 + l16: + position, tokenIndex = position14, tokenIndex14 + if !_rules[ruleUSCode]() { + goto l20 + } + goto l14 + l20: + position, tokenIndex = position14, tokenIndex14 + if !_rules[ruleHKCode]() { + goto l12 + } + } + l14: + if buffer[position] != rune(')') { + goto l12 + } + position++ + if buffer[position] != rune('$') { + goto l12 + } + position++ + add(ruleXLStock, position13) + } + goto l5 + l12: + position, tokenIndex = position5, tokenIndex5 + { + position22 := position + { + position23, tokenIndex23 := position, tokenIndex + if buffer[position] != rune('$') { + goto l24 + } position++ if !_rules[ruleCode]() { - goto l15 + goto l24 } { - position16, tokenIndex16 := position, tokenIndex + position25, tokenIndex25 := position, tokenIndex if !_rules[ruleSuffix]() { - goto l17 + goto l26 } - goto l16 - l17: - position, tokenIndex = position16, tokenIndex16 + goto l25 + l26: + position, tokenIndex = position25, tokenIndex25 { - position18, tokenIndex18 := position, tokenIndex + position27, tokenIndex27 := position, tokenIndex if !_rules[ruleSuffix]() { - goto l18 + goto l27 } - goto l19 - l18: - position, tokenIndex = position18, tokenIndex18 + goto l28 + l27: + position, tokenIndex = position27, tokenIndex27 } - l19: + l28: } - l16: + l25: if buffer[position] != rune('$') { - goto l15 + goto l24 } position++ - goto l14 - l15: - position, tokenIndex = position14, tokenIndex14 + goto l23 + l24: + position, tokenIndex = position23, tokenIndex23 if buffer[position] != rune('$') { - goto l20 + goto l29 } position++ if !_rules[ruleCode]() { - goto l20 + goto l29 } if !_rules[ruleSuffix]() { - goto l20 + goto l29 } - goto l14 - l20: - position, tokenIndex = position14, tokenIndex14 + goto l23 + l29: + position, tokenIndex = position23, tokenIndex23 if buffer[position] != rune('(') { - goto l21 + goto l30 } position++ { - position22, tokenIndex22 := position, tokenIndex + position31, tokenIndex31 := position, tokenIndex if buffer[position] != rune('N') { - goto l23 + goto l32 } position++ if buffer[position] != rune('Y') { - goto l23 + goto l32 } position++ if buffer[position] != rune('S') { - goto l23 + goto l32 } position++ if buffer[position] != rune('E') { - goto l23 + goto l32 } position++ - goto l22 - l23: - position, tokenIndex = position22, tokenIndex22 + goto l31 + l32: + position, tokenIndex = position31, tokenIndex31 if buffer[position] != rune('N') { - goto l21 + goto l30 } position++ if buffer[position] != rune('A') { - goto l21 + goto l30 } position++ if buffer[position] != rune('S') { - goto l21 + goto l30 } position++ if buffer[position] != rune('D') { - goto l21 + goto l30 } position++ if buffer[position] != rune('A') { - goto l21 + goto l30 } position++ if buffer[position] != rune('Q') { - goto l21 + goto l30 } position++ } - l22: + l31: { - position24, tokenIndex24 := position, tokenIndex + position33, tokenIndex33 := position, tokenIndex if buffer[position] != rune(':') { - goto l25 + goto l34 } position++ - goto l24 - l25: - position, tokenIndex = position24, tokenIndex24 + goto l33 + l34: + position, tokenIndex = position33, tokenIndex33 if buffer[position] != rune(':') { - goto l21 + goto l30 } position++ } - l24: - l26: + l33: + l35: { - position27, tokenIndex27 := position, tokenIndex + position36, tokenIndex36 := position, tokenIndex { - position28 := position + position37 := position { - position29, tokenIndex29 := position, tokenIndex + position38, tokenIndex38 := position, tokenIndex if buffer[position] != rune(' ') { - goto l30 + goto l39 } position++ - goto l29 - l30: - position, tokenIndex = position29, tokenIndex29 + goto l38 + l39: + position, tokenIndex = position38, tokenIndex38 if buffer[position] != rune('\t') { - goto l27 + goto l36 } position++ } - l29: - add(ruleSP, position28) + l38: + add(ruleSP, position37) } - goto l26 - l27: - position, tokenIndex = position27, tokenIndex27 + goto l35 + l36: + position, tokenIndex = position36, tokenIndex36 } if !_rules[ruleUSCode]() { - goto l21 + goto l30 } if buffer[position] != rune(')') { - goto l21 + goto l30 } position++ - goto l14 - l21: - position, tokenIndex = position14, tokenIndex14 + goto l23 + l30: + position, tokenIndex = position23, tokenIndex23 { switch buffer[position] { case '(': if buffer[position] != rune('(') { - goto l12 + goto l21 } position++ if !_rules[ruleMarket]() { - goto l12 + goto l21 } if buffer[position] != rune(':') { - goto l12 + goto l21 } position++ if !_rules[ruleCode]() { - goto l12 + goto l21 } if buffer[position] != rune(')') { - goto l12 + goto l21 } position++ case '$': if buffer[position] != rune('$') { - goto l12 + goto l21 } position++ if !_rules[ruleUSCode]() { - goto l12 + goto l21 } default: if buffer[position] != rune(' ') { - goto l12 + goto l21 } position++ - l32: + l41: { - position33, tokenIndex33 := position, tokenIndex + position42, tokenIndex42 := position, tokenIndex if buffer[position] != rune(' ') { - goto l33 + goto l42 } position++ - goto l32 - l33: - position, tokenIndex = position33, tokenIndex33 + goto l41 + l42: + position, tokenIndex = position42, tokenIndex42 } if !_rules[ruleCode]() { - goto l12 + goto l21 } if !_rules[ruleSuffix]() { - goto l12 + goto l21 } } } } - l14: - add(ruleStock, position13) - } - goto l5 - l12: - position, tokenIndex = position5, tokenIndex5 - { - position35 := position - if buffer[position] != rune('$') { - goto l34 - } - position++ - if !_rules[ruleStockName]() { - goto l34 - } - if buffer[position] != rune('(') { - goto l34 - } - position++ - { - position36, tokenIndex36 := position, tokenIndex - if !_rules[ruleCNMarket]() { - goto l37 - } - if !_rules[ruleACode]() { - goto l37 - } - goto l36 - l37: - position, tokenIndex = position36, tokenIndex36 - if !_rules[ruleHKMarket]() { - goto l38 - } - { - position39 := position - { - position40, tokenIndex40 := position, tokenIndex - if buffer[position] != rune('H') { - goto l41 - } - position++ - if buffer[position] != rune('S') { - goto l41 - } - position++ - if buffer[position] != rune('T') { - goto l41 - } - position++ - if buffer[position] != rune('E') { - goto l41 - } - position++ - if buffer[position] != rune('C') { - goto l41 - } - position++ - if buffer[position] != rune('H') { - goto l41 - } - position++ - goto l40 - l41: - position, tokenIndex = position40, tokenIndex40 - if buffer[position] != rune('H') { - goto l38 - } - position++ - if buffer[position] != rune('S') { - goto l38 - } - position++ - if buffer[position] != rune('I') { - goto l38 - } - position++ - } - l40: - add(ruleHSCODE, position39) - } - goto l36 - l38: - position, tokenIndex = position36, tokenIndex36 - if !_rules[ruleUSCode]() { - goto l42 - } - goto l36 - l42: - position, tokenIndex = position36, tokenIndex36 - if !_rules[ruleHKCode]() { - goto l34 - } - } - l36: - if buffer[position] != rune(')') { - goto l34 - } - position++ - if buffer[position] != rune('$') { - goto l34 - } - position++ - add(ruleXLStock, position35) + l23: + add(ruleStock, position22) } goto l5 - l34: + l21: position, tokenIndex = position5, tokenIndex5 { position43 := position @@ -782,7 +782,7 @@ func (p *StockCodeParser) Init(options ...func(*StockCodeParser) error) error { position, tokenIndex = position0, tokenIndex0 return false }, - /* 1 Line <- <(FTStock / Stock / XLStock / OTHER)> */ + /* 1 Line <- <(FTStock / XLStock / Stock / OTHER)> */ nil, /* 2 OTHER <- <.> */ nil, @@ -792,68 +792,49 @@ func (p *StockCodeParser) Init(options ...func(*StockCodeParser) error) error { nil, /* 5 FTStock <- <('$' (StockName / (StockName '-' Letter+)) '(' Code '.' Market ')' '$')> */ nil, - /* 6 StockName <- <(!((&('\'') [\'-\']) | (&(')') ')') | (&('(') '(')) .)+> */ + /* 6 StockName <- <(!('"' / ((&('"') '"') | (&(')') ')') | (&('(') '('))) .)*> */ func() bool { - position50, tokenIndex50 := position, tokenIndex { position51 := position - { - position54, tokenIndex54 := position, tokenIndex - { - switch buffer[position] { - case '\'': - if c := buffer[position]; c < rune('\'') || c > rune('\'') { - goto l54 - } - position++ - case ')': - if buffer[position] != rune(')') { - goto l54 - } - position++ - default: - if buffer[position] != rune('(') { - goto l54 - } - position++ - } - } - - goto l50 - l54: - position, tokenIndex = position54, tokenIndex54 - } - if !matchDot() { - goto l50 - } l52: { position53, tokenIndex53 := position, tokenIndex { - position56, tokenIndex56 := position, tokenIndex + position54, tokenIndex54 := position, tokenIndex { - switch buffer[position] { - case '\'': - if c := buffer[position]; c < rune('\'') || c > rune('\'') { - goto l56 - } - position++ - case ')': - if buffer[position] != rune(')') { - goto l56 - } - position++ - default: - if buffer[position] != rune('(') { - goto l56 + position55, tokenIndex55 := position, tokenIndex + if buffer[position] != rune('"') { + goto l56 + } + position++ + goto l55 + l56: + position, tokenIndex = position55, tokenIndex55 + { + switch buffer[position] { + case '"': + if buffer[position] != rune('"') { + goto l54 + } + position++ + case ')': + if buffer[position] != rune(')') { + goto l54 + } + position++ + default: + if buffer[position] != rune('(') { + goto l54 + } + position++ } - position++ } - } + } + l55: goto l53 - l56: - position, tokenIndex = position56, tokenIndex56 + l54: + position, tokenIndex = position54, tokenIndex54 } if !matchDot() { goto l53 @@ -865,9 +846,6 @@ func (p *StockCodeParser) Init(options ...func(*StockCodeParser) error) error { add(ruleStockName, position51) } return true - l50: - position, tokenIndex = position50, tokenIndex50 - return false }, /* 7 Code <- <(USCode / HKCode / ACode)> */ func() bool { diff --git a/grammar.peg b/grammar.peg index fbcaa91..3df8154 100644 --- a/grammar.peg +++ b/grammar.peg @@ -6,7 +6,7 @@ type StockCodeParser Peg { } Item <- Line* !. -Line <- FTStock / Stock / XLStock / OTHER +Line <- FTStock / XLStock / Stock / OTHER # Any other characters, to ignore OTHER <- (.) @@ -33,7 +33,7 @@ Stock <- ( ) XLStock <- ( - # $阿里巴巴(BABA)$ $中国平安(SH601318)$ $腾讯控股(00700)$ $百度集团-SW(09988)$ $恒生科技指数(HKHSTECH)$ $恒生指数(HKHSI)$ + # $阿里巴巴(BABA)$ $中国平安(SH601318)$ $腾讯控股(00700)$ $百度集团-SW(09988)$ $恒生科技指数(HKHSTECH)$ $恒生指数(HKHSI)$ $CoinBase Global(COIN)$ '$' StockName '(' (CNMarket ACode / HKMarket HSCODE / USCode / HKCode) ')' '$' ) @@ -42,7 +42,7 @@ FTStock <- ( '$' (StockName / StockName '-' Letter+) '(' Code '.' Market ')' '$' ) -StockName <- [^()'-']+ +StockName <- [^"()"]* Code <- (USCode / HKCode / ACode) diff --git a/parser.go b/parser.go index 7ddea20..1a7243e 100644 --- a/parser.go +++ b/parser.go @@ -52,7 +52,6 @@ func (p *parser) consumeNode(node *node32, cb func(node, market, match string) s code := "" market := "" match := "" - if node.pegRule == ruleStock { code, market, match = p.parseStock(node) } else if node.pegRule == ruleXLStock { diff --git a/parser_test.go b/parser_test.go index 361ea96..0cf4f26 100644 --- a/parser_test.go +++ b/parser_test.go @@ -42,7 +42,7 @@ func TestParse(t *testing.T) { assert_matches_code(t, `阿里巴巴 $BABA.US 发布财报`, "阿里巴巴 $BABA 发布财报") - assert_matches_code(t, `吉利交付 $00175.HK 股票, 哈哈 $603200.SH 哈哈`, `吉利交付 $00175.HK 股票, 哈哈 $上海洗霸(SH603200)$ 哈哈`) + assert_matches_code(t, `吉利交付 $00175.HK 股票, 哈哈`, `吉利交付 $00175.HK 股票, 哈哈`) assert_matches_code(t, `理想汽車 $2015.HK 升不足 1%,阿里巴巴 $BABA.US 升 1.06%。`, "理想汽車 (HK:2015) 升不足 1%,阿里巴巴 (US:BABA) 升 1.06%。") @@ -57,6 +57,10 @@ func TestXueqiuLaohuFutu(t *testing.T) { assert_matches_code(t, `$HSTECH.HK your grandpa is still your grandpa! 又高又硬`, `$恒生科技指数(HKHSTECH)$ your grandpa is still your grandpa! 又高又硬`) + assert_matches_code(t, `$COIN.US 开户现货交易了!`, `$CoinBase Global(COIN)$ 开户现货交易了!`) + + assert_matches_code(t, `$603200.SH 哈哈`, " $上海洗霸 (SH603200)$ 哈哈") + // 富途 assert_matches_code(t, `$BABA.US 不错的哈哈哈 $00700.HK 看好 $002241.SZ 也不错`, "$阿里巴巴 (BABA.US)$ 不错的哈哈哈 $腾讯控股 (00700.HK)$ 看好 $歌尔股份 (002241.SZ)$ 也不错") }