// Copyright (c) 2018, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package syntax

import 

var (
	litLeftBrace  = &Lit{Value: "{"}
	litComma      = &Lit{Value: ","}
	litDots       = &Lit{Value: ".."}
	litRightBrace = &Lit{Value: "}"}
)

// SplitBraces parses brace expansions within a word's literal parts. If any
// valid brace expansions are found, they are replaced with BraceExp nodes, and
// the function returns true. Otherwise, the word is left untouched and the
// function returns false.
//
// For example, a literal word "foo{bar,baz}" will result in a word containing
// the literal "foo", and a brace expansion with the elements "bar" and "baz".
//
// It does not return an error; malformed brace expansions are simply skipped.
// For example, the literal word "a{b" is left unchanged.
func ( *Word) bool {
	 := false
	 := &Word{}
	 := 
	var  *BraceExp
	 := []*BraceExp{}

	 := func() *BraceExp {
		 := 
		 = [:len()-1]
		if len() == 0 {
			 = nil
			 = 
		} else {
			 = [len()-1]
			 = .Elems[len(.Elems)-1]
		}
		return 
	}
	 := func( *Lit) {
		.Parts = append(.Parts, )
	}

	for ,  := range .Parts {
		,  := .(*Lit)
		if ! {
			.Parts = append(.Parts, )
			continue
		}
		 := 0
		for  := 0;  < len(.Value); ++ {
			 := func() {
				if  ==  {
					return // empty lit
				}
				 := *
				.Value = .Value[:]
				(&)
			}
			switch .Value[] {
			case '{':
				()
				 = &Word{}
				 = &BraceExp{Elems: []*Word{}}
				 = append(, )
			case ',':
				if  == nil {
					continue
				}
				()
				 = &Word{}
				.Elems = append(.Elems, )
			case '.':
				if  == nil {
					continue
				}
				if +1 >= len(.Value) || .Value[+1] != '.' {
					continue
				}
				()
				.Sequence = true
				 = &Word{}
				.Elems = append(.Elems, )
				++
			case '}':
				if  == nil {
					continue
				}
				 = true
				()
				 := ()
				if len(.Elems) == 1 {
					// return {x} to a non-brace
					(litLeftBrace)
					.Parts = append(.Parts, .Elems[0].Parts...)
					(litRightBrace)
					break
				}
				if !.Sequence {
					.Parts = append(.Parts, )
					break
				}
				var  [2]bool
				 := false
				for ,  := range .Elems[:2] {
					 := .Lit()
					if ,  := strconv.Atoi();  == nil {
					} else if len() == 1 &&
						'a' <= [0] && [0] <= 'z' {
						[] = true
					} else {
						 = true
					}
				}
				if len(.Elems) == 3 {
					// increment must be a number
					 := .Elems[2].Lit()
					if ,  := strconv.Atoi();  != nil {
						 = true
					}
				}
				// are start and end both chars or
				// non-chars?
				if [0] != [1] {
					 = true
				}
				if ! {
					.Parts = append(.Parts, )
					break
				}
				// return broken {x..y[..incr]} to a non-brace
				(litLeftBrace)
				for ,  := range .Elems {
					if  > 0 {
						(litDots)
					}
					.Parts = append(.Parts, .Parts...)
				}
				(litRightBrace)
			default:
				continue
			}
			 =  + 1
		}
		if  == 0 {
			()
		} else {
			 := *
			.Value = .Value[:]
			(&)
		}
	}
	if ! {
		return false
	}
	// open braces that were never closed fall back to non-braces
	for  !=  {
		 := ()
		(litLeftBrace)
		for ,  := range .Elems {
			if  > 0 {
				if .Sequence {
					(litDots)
				} else {
					(litComma)
				}
			}
			.Parts = append(.Parts, .Parts...)
		}
	}
	* = *
	return true
}