func (p *Parser) line(scratch [][]lex.Token) (word, cond string, operands [][]lex.Token, ok bool) {
next:
	// Skip newlines.
	var tok lex.ScanToken
	for {
		tok = p.nextToken()
		// We save the line number here so error messages from this instruction
		// are labeled with this line. Otherwise we complain after we've absorbed
		// the terminating newline and the line numbers are off by one in errors.
		p.lineNum = p.lex.Line()
		switch tok {
		case '\n', ';':
			continue
		case scanner.EOF:
			return "", "", nil, false
		}
		break
	}
	// First item must be an identifier.
	if tok != scanner.Ident {
		p.errorf("expected identifier, found %q", p.lex.Text())
		return "", "", nil, false // Might as well stop now.
	}
	word, cond = p.lex.Text(), ""
	operands = scratch[:0]
	// Zero or more comma-separated operands, one per loop.
	nesting := 0
	colon := -1
	for tok != '\n' && tok != ';' {
		// Process one operand.
		var items []lex.Token
		if cap(operands) > len(operands) {
			// Reuse scratch items slice.
			items = operands[:cap(operands)][len(operands)][:0]
		} else {
			items = make([]lex.Token, 0, 3)
		}
		for {
			tok = p.nextToken()
			if len(operands) == 0 && len(items) == 0 {
				if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
					// Suffixes: ARM conditionals or x86 modifiers.
					tok = p.nextToken()
					str := p.lex.Text()
					if tok != scanner.Ident {
						p.errorf("instruction suffix expected identifier, found %s", str)
					}
					cond = cond + "." + str
					continue
				}
				if tok == ':' {
					// Labels.
					p.pendingLabels = append(p.pendingLabels, word)
					goto next
				}
			}
			if tok == scanner.EOF {
				p.errorf("unexpected EOF")
				return "", "", nil, false
			}
			// Split operands on comma. Also, the old syntax on x86 for a "register pair"
			// was AX:DX, for which the new syntax is DX, AX. Note the reordering.
			if tok == '\n' || tok == ';' || (nesting == 0 && (tok == ',' || tok == ':')) {
				if tok == ':' {
					// Remember this location so we can swap the operands below.
					if colon >= 0 {
						p.errorf("invalid ':' in operand")
						return word, cond, operands, true
					}
					colon = len(operands)
				}
				break
			}
			if tok == '(' || tok == '[' {
				nesting++
			}
			if tok == ')' || tok == ']' {
				nesting--
			}
			items = append(items, lex.Make(tok, p.lex.Text()))
		}
		if len(items) > 0 {
			operands = append(operands, items)
			if colon >= 0 && len(operands) == colon+2 {
				// AX:DX becomes DX, AX.
				operands[colon], operands[colon+1] = operands[colon+1], operands[colon]
				colon = -1
			}
		} else if len(operands) > 0 || tok == ',' || colon >= 0 {
			// Had a separator with nothing after.
			p.errorf("missing operand")
		}
	}
	return word, cond, operands, true
}
// line consumes a single assembly line from p.lex of the form
//
//   {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
//
// It adds any labels to p.pendingLabels and returns the word, cond,
// operand list, and true. If there is an error or EOF, it returns
// ok=false.
//
// line may reuse the memory from scratch.
line consumes a single assembly line from p.lex of the form



It adds any labels to p.pendingLabels and returns the word, cond,
operand list, and true. If there is an error or EOF, it returns
ok=false.

line may reuse the memory from scratch.
// line consumes a single assembly line from p . lex of the form // // { label : } WORD [ . cond ] [ arg { arg } ] ( ' ; ' | ' \ n ' ) // // It adds any labels to p . pendingLabels and returns the word cond // operand list and true . If there is an error or EOF it returns // ok = false . // // line may reuse the memory from scratch .
func (p *Parser) line(scratch [][]lex.Token) (word, cond string, operands [][]lex.Token, ok bool) {
next:
	var tok lex.ScanToken
	for {
		tok = p.nextToken()
		p.lineNum = p.lex.Line()
		switch tok {
		case '\n', ';':
			continue
		case scanner.EOF:
			return "", "", nil, false
		}
		break
	}
	if tok != scanner.Ident {
		p.errorf("expected identifier, found %q", p.lex.Text())
		return "", "", nil, false 
	}
	word, cond = p.lex.Text(), ""
	operands = scratch[:0]
	nesting := 0
	colon := -1
	for tok != '\n' && tok != ';' {
		var items []lex.Token
		if cap(operands) > len(operands) {
			items = operands[:cap(operands)][len(operands)][:0]
		} else {
			items = make([]lex.Token, 0, 3)
		}
		for {
			tok = p.nextToken()
			if len(operands) == 0 && len(items) == 0 {
				if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
					tok = p.nextToken()
					str := p.lex.Text()
					if tok != scanner.Ident {
						p.errorf("instruction suffix expected identifier, found %s", str)
					}
					cond = cond + "." + str
					continue
				}
				if tok == ':' {
					p.pendingLabels = append(p.pendingLabels, word)
					goto next
				}
			}
			if tok == scanner.EOF {
				p.errorf("unexpected EOF")
				return "", "", nil, false
			}
			if tok == '\n' || tok == ';' || (nesting == 0 && (tok == ',' || tok == ':')) {
				if tok == ':' {
					if colon >= 0 {
						p.errorf("invalid ':' in operand")
						return word, cond, operands, true
					}
					colon = len(operands)
				}
				break
			}
			if tok == '(' || tok == '[' {
				nesting++
			}
			if tok == ')' || tok == ']' {
				nesting--
			}
			items = append(items, lex.Make(tok, p.lex.Text()))
		}
		if len(items) > 0 {
			operands = append(operands, items)
			if colon >= 0 && len(operands) == colon+2 {
				operands[colon], operands[colon+1] = operands[colon+1], operands[colon]
				colon = -1
			}
		} else if len(operands) > 0 || tok == ',' || colon >= 0 {
			p.errorf("missing operand")
		}
	}
	return word, cond, operands, true
}
func ( p * Parser ) line ( scratch [ ] [ ] lex . Token ) ( word , cond string , operands [ ] [ ] lex . Token , ok bool ) { next : var tok lex . ScanToken for { tok = p . nextToken ( ) p . lineNum = p . lex . Line ( ) switch tok { case '\n' , ';' : continue case scanner . EOF : return " " , " " , nil , false } break } if tok != scanner . Ident { p . errorf ( " " , p . lex . Text ( ) ) return " " , " " , nil , false } word , cond = p . lex . Text ( ) , " " operands = scratch [ : 0 ] nesting := 0 colon := - 1 for tok != '\n' && tok != ';' { var items [ ] lex . Token if cap ( operands ) > len ( operands ) { items = operands [ : cap ( operands ) ] [ len ( operands ) ] [ : 0 ] } else { items = make ( [ ] lex . Token , 0 , 3 ) } for { tok = p . nextToken ( ) if len ( operands ) == 0 && len ( items ) == 0 { if p . arch . InFamily ( sys . ARM , sys . ARM64 , sys . AMD64 , sys . I386 ) && tok == '.' { tok = p . nextToken ( ) str := p . lex . Text ( ) if tok != scanner . Ident { p . errorf ( " " , str ) } cond = cond + " " + str continue } if tok == ':' { p . pendingLabels = append ( p . pendingLabels , word ) goto next } } if tok == scanner . EOF { p . errorf ( " " ) return " " , " " , nil , false } if tok == '\n' || tok == ';' || ( nesting == 0 && ( tok == ',' || tok == ':' ) ) { if tok == ':' { if colon >= 0 { p . errorf ( " " ) return word , cond , operands , true } colon = len ( operands ) } break } if tok == '(' || tok == '[' { nesting ++ } if tok == ')' || tok == ']' { nesting -- } items = append ( items , lex . Make ( tok , p . lex . Text ( ) ) ) } if len ( items ) > 0 { operands = append ( operands , items ) if colon >= 0 && len ( operands ) == colon + 2 { operands [ colon ] , operands [ colon + 1 ] = operands [ colon + 1 ] , operands [ colon ] colon = - 1 } } else if len ( operands ) > 0 || tok == ',' || colon >= 0 { p . errorf ( " " ) } } return word , cond , operands , true }
line consumes a single assembly line from p.lex of the form
line consumes a single assembly line from p . lex of the form
// Skip newlines. // We save the line number here so error messages from this instruction // are labeled with this line. Otherwise we complain after we've absorbed // the terminating newline and the line numbers are off by one in errors. // First item must be an identifier. // Might as well stop now. // Zero or more comma-separated operands, one per loop. // Process one operand. // Reuse scratch items slice. // Suffixes: ARM conditionals or x86 modifiers. // Labels. // Split operands on comma. Also, the old syntax on x86 for a "register pair" // was AX:DX, for which the new syntax is DX, AX. Note the reordering. // Remember this location so we can swap the operands below. // AX:DX becomes DX, AX. // Had a separator with nothing after.