// WORD [ arg {, arg} ] (';' | '\n') func (p *Parser) line() bool { // Skip newlines. var tok lex.ScanToken for { tok = p.lex.Next() // 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() p.histLineNum = lex.HistLine() switch tok { case '\n', ';': continue case scanner.EOF: return false } break } // First item must be an identifier. if tok != scanner.Ident { p.errorf("expected identifier, found %q", p.lex.Text()) return false // Might as well stop now. } word := p.lex.Text() var cond string operands := make([][]lex.Token, 0, 3) // Zero or more comma-separated operands, one per loop. nesting := 0 colon := -1 for tok != '\n' && tok != ';' { // Process one operand. items := make([]lex.Token, 0, 3) for { tok = p.lex.Next() if len(operands) == 0 && len(items) == 0 { if (p.arch.Thechar == '5' || p.arch.Thechar == '7') && tok == '.' { // ARM conditionals. tok = p.lex.Next() str := p.lex.Text() if tok != scanner.Ident { p.errorf("ARM condition expected identifier, found %s", str) } cond = cond + "." + str continue } if tok == ':' { // Labels. p.pendingLabels = append(p.pendingLabels, word) return true } } if tok == scanner.EOF { p.errorf("unexpected EOF") return 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 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") } } i, present := arch.Pseudos[word] if present { p.pseudo(i, word, operands) return true } i, present = p.arch.Instructions[word] if present { p.instruction(i, word, cond, operands) return true } p.errorf("unrecognized instruction %q", word) return true }
if err != nil { p.errorf("%s", err) } return value } func (p *Parser) atos(str string) string { value, err := strconv.Unquote(str) if err != nil { p.errorf("%s", err) } return value } // EOF represents the end of input. var EOF = lex.Make(scanner.EOF, "EOF") func (p *Parser) next() lex.Token { if !p.more() { return EOF } tok := p.input[p.inputPos] p.inputPos++ return tok } func (p *Parser) back() { if p.inputPos == 0 { p.errorf("internal error: backing up before BOL") } else { p.inputPos--