2015-06-04 1 views
3

Вчера я спросил this question о разделении строки в python. С тех пор я решил сделать этот проект в Го вместо этого. У меня есть следующее:Как включить операторов в мой вывод, когда я разделяю строку?

input := "house-width + 3 - y^(5 * house length)" 
s := regexp.MustCompile(" ([+-/*^]) ").Split(input, -1) 
log.Println(s) // [house-width 3 y (5 house length)] 

Как включить операторов в этот выход? например Я хотел бы следующий вывод:

['house-width', '+', '3', '-', 'y', '^', '(5', '*', 'house length)'] 

EDIT: Для уточнения я разделив на пространственно разделенных операторов, а не только оператор. Оператор должен иметь пространство на обоих концах, чтобы отличать его от тире/дефиса. Пожалуйста, обратитесь к моему исходному вопросу python, к которому я привязался, для уточнения, если это необходимо.

+1

Есть ли какой-либо причине вам нужно использовать регулярное выражение против строк. Разделить (ввод, "")? http://golang.org/pkg/strings/#Split – Verran

+0

Этот '' ([+ -/* ^]) "' более функциональен как '' \ s * ([+ \ -/* ^]) \ s * "и знак минус должен быть экранирован. В чем проблема? Включает ли он захват в выходной массив? Во всяком случае, я не уверен, что вы должны разделить на пробелы, а не на самом деле разделитель. – sln

+0

@ sln проблема заключается в том, что то, что у меня есть, не возвращает операторов. Вместо этого он возвращает «['house-width' '3' 'y' '(5' 'house length)']" http://play.golang.org/p/B4zCSLWPjz –

ответ

1

Вы можете получить операнды своего выражения, используя regexp.Split() (как и вы), и вы можете получить операторы (разделители) с помощью regexp.FindAllString().

Делая это, вы будете иметь 2 отдельных []string фрагментов, вы можете объединить эти 2 среза, если вы хотите получить результат в одном []string фрагменте.

input := "house-width + 3 - y^(5 * house length)" 

r := regexp.MustCompile(`\s([+\-/*^])\s`) 

s1 := r.Split(input, -1) 
s2 := r.FindAllString(input, -1) 

fmt.Printf("%q\n", s1) 
fmt.Printf("%q\n", s2) 

all := make([]string, len(s1)+len(s2)) 
for i := range s1 { 
    all[i*2] = s1[i] 
    if i < len(s2) { 
     all[i*2+1] = s2[i] 
    } 
} 
fmt.Printf("%q\n", all) 

Output (попробуйте на Go Playground):

["house-width" "3" "y" "(5" "house length)"] 
[" + " " - " "^" " * "] 
["house-width" " + " "3" " - " "y" "^" "(5" " * " "house length)"] 

Примечание:

Если вы хотите обрезать пробелы из операторов, вы можете использовать функцию strings.TrimSpace() для этого:

for i, v := range s2 { 
    all[i*2+1] = strings.TrimSpace(v) 
} 
fmt.Printf("%q\n", all) 

Выход:

["house-width" "+" "3" "-" "y" "^" "(5" "*" "house length)"] 
1

Если вы планируете разобрать выражение впоследствии вам придется внести некоторые изменения:

  • Include круглые скобки, как лексемы
  • Вы не можете иметь как пробелы и тире являются действительными идентификационными символами, потому что, например, - y между 3 и ^ будет действительным идентификатором.

После этого будет сделано, вы можете использовать использовать простой linear iteration Лекс вашей строки:

package main 

import (
    "bytes" 
    "fmt" 
) 

func main() { 

    input := `house width + 3 - y^(5 * house length)` 
    buffr := bytes.NewBuffer(nil) 
    outpt := make([]string, 0) 

    for _, r := range input { 
     if r == '+' || r == '-' || r == '*' || r == '/' || r == '^' || r == '(' || r == ')' || (r >= '0' && r <= '9') { 
      bs := bytes.TrimSpace(buffr.Bytes()) 
      if len(bs) > 0 { 
       outpt = append(outpt, (string)(bs)) 
      } 
      outpt = append(outpt, (string)(r)) 
      buffr.Reset() 
     } else { 
      buffr.WriteRune(r) 
     } 
    } 

    fmt.Printf("%#v\n", outpt) 

} 

После lexed, использовать Дейкстры shunting-yard algorithm построить AST или непосредственно оценить выражение.

+0

«У вас не может быть пробелов и дефис» Вот почему я раскалываюсь на оператор, разделенный пробелом. –

0

Я думаю, что FindAll() может быть путем.

Expanded регулярное выражение:

\s*       # Trim preceding whitespace 
(       # (1 start), Operator/Non-Operator chars 
     (?:       # Cluster group 
      \w -       # word dash 
     | - \w       # or, dash word 
     | [^+\-/*^]      # or, a non-operator char 
    )+       # End cluster, do 1 to many times 
    |        # or, 
     [+\-/*^]      # A single simple math operator 
)        # (1 end) 
\s*       # Trim trailing whitespace 

Go фрагмент кода:

http://play.golang.org/p/bHZ21B6Tzi

package main 

import (
"log" 
"regexp" 
) 
func main() { 
    in := []byte("house-width + 3 - y^(5 * house length)") 
    rr := regexp.MustCompile("\\s*((?:\\w-|-\\w|[^+\\-/*^])+|[+\\-/*^])\\s*") 
    s := r.FindAll(in, -1) 
    for _, ss:=range s{ 
     log.Println(string(ss)) 
    } 
} 

Выход:

house-width 
+ 
3 
- 
y 
^ 
(5 
* 
house length) 
Смежные вопросы