func lexOperand(x *lex8.Lexer) *lex8.Token { if !isOperandChar(x.Rune()) { panic("incorrect operand start") } for { x.Next() if x.Ended() || !isOperandChar(x.Rune()) { break } } ret := x.MakeToken(Operand) if isKeyword(ret.Lit) { ret.Type = Keyword } return ret }
func lexIdent(x *lex8.Lexer) *lex8.Token { r := x.Rune() if !isLetter(r) { panic("must start with letter") } for { x.Next() r := x.Rune() if !isLetter(r) && !lex8.IsDigit(r) { break } } ret := x.MakeToken(Ident) return ret }
func lexAsm8(x *lex8.Lexer) *lex8.Token { r := x.Rune() if x.IsWhite(r) { panic("incorrect token start") } switch r { case '\n': x.Next() return x.MakeToken(Endl) case '{': x.Next() return x.MakeToken(Lbrace) case '}': x.Next() return x.MakeToken(Rbrace) case '/': x.Next() return lex8.LexComment(x) case '"': return lex8.LexString(x, String, '"') } if isOperandChar(r) { return lexOperand(x) } x.Errorf("illegal char %q", r) x.Next() return x.MakeToken(lex8.Illegal) }
func lexG8(x *lex8.Lexer) *lex8.Token { r := x.Rune() if x.IsWhite(r) { panic("incorrect token start") } switch r { case '\n': x.Next() return x.MakeToken(Endl) case '"': return lex8.LexString(x, String, '"') case '\'': return lex8.LexString(x, Char, '\'') } if lex8.IsDigit(r) { return lexNumber(x) } else if isLetter(r) { return lexIdent(x) } // always make progress at this point x.Next() t := lexOperator(x, r) if t != nil { return t } x.Errorf("illegal char %q", r) return x.MakeToken(lex8.Illegal) }
func lexOperator(x *lex8.Lexer, r rune) *lex8.Token { switch r { case ';': return x.MakeToken(Semi) case '{', '}', '(', ')', '[', ']', ',': /* do nothing */ case '/': r2 := x.Rune() if r2 == '/' || r2 == '*' { return lex8.LexComment(x) } else if r2 == '=' { x.Next() } case '+', '-', '&', '|': r2 := x.Rune() if r2 == r || r2 == '=' { x.Next() } case '*', '%', '^', '=', '!', ':': r2 := x.Rune() if r2 == '=' { x.Next() } case '.': r2 := x.Rune() if r2 == '.' { x.Next() r3 := x.Rune() if r3 != '.' { x.Errorf("expect ..., but see ..") return x.MakeToken(Operator) } x.Next() } case '>', '<': r2 := x.Rune() if r2 == r { x.Next() r3 := x.Rune() if r3 == '=' { x.Next() } } else if r2 == '=' { x.Next() } default: return nil } return x.MakeToken(Operator) }
func lexNumber(x *lex8.Lexer) *lex8.Token { // TODO: lex floating point as well start := x.Rune() if !lex8.IsDigit(start) { panic("not starting with a number") } x.Next() r := x.Rune() if start == '0' && r == 'x' { x.Next() for lex8.IsHexDigit(x.Rune()) { x.Next() } } else { for lex8.IsDigit(x.Rune()) { x.Next() } } return x.MakeToken(Int) }