MST

星途 面试题库

面试题:Go语言词法单元之关键字与操作符的词法处理

Go语言有哪些关键字?在词法分析阶段,关键字和操作符是如何被区分和解析的?如果让你实现一个简单的词法分析器来识别关键字和操作符,你会如何设计?
40.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Go语言关键字

Go语言有25个关键字:

break      default      func     interface   select
case       defer        go       map         struct
chan       else         goto     package     switch
const      fallthrough  if       range       type
continue   for          import   return      var

词法分析阶段关键字和操作符区分解析

在词法分析阶段,词法分析器按字符流顺序读取输入源程序。它依据预先定义的规则,通过状态转移方式识别记号(token)。对于关键字和操作符:

  • 关键字:词法分析器有一张关键字表。当从输入流读取字符并形成一个标识符形式的字符串时,会将该字符串与关键字表进行匹配。如果匹配成功,则识别为关键字;否则为普通标识符。
  • 操作符:操作符有固定的字符模式,词法分析器根据操作符的字符序列模式来识别。例如,单个字符的操作符(如 +-*/),以及多个字符组成的操作符(如 +=++== 等)。当读取到这些特定字符组合时,就识别为相应的操作符。

简单词法分析器设计实现

设计一个简单词法分析器识别关键字和操作符,可以按以下步骤:

  1. 定义记号类型
type TokenType int

const (
    TokenEOF TokenType = iota
    TokenKeyword
    TokenOperator
    TokenIdentifier
    TokenError
)
  1. 定义记号结构体
type Token struct {
    Type  TokenType
    Value string
}
  1. 初始化关键字表
var keywordMap = map[string]bool{
    "break":      true,
    "default":    true,
    "func":       true,
    // 其它关键字
}
  1. 实现词法分析函数
func Lexer(input string) ([]Token, error) {
    var tokens []Token
    i := 0
    for i < len(input) {
        switch {
        case isWhitespace(input[i]):
            i++
        case isLetter(input[i]):
            start := i
            for i < len(input) && (isLetter(input[i]) || isDigit(input[i])) {
                i++
            }
            tokenStr := input[start:i]
            if keywordMap[tokenStr] {
                tokens = append(tokens, Token{Type: TokenKeyword, Value: tokenStr})
            } else {
                tokens = append(tokens, Token{Type: TokenIdentifier, Value: tokenStr})
            }
        case isOperatorChar(input[i]):
            start := i
            for i < len(input) && isOperatorChar(input[i+1]) && isOperator(input[start:i+2]) {
                i++
            }
            tokens = append(tokens, Token{Type: TokenOperator, Value: input[start:i+1]})
            i++
        default:
            return nil, fmt.Errorf("unexpected character: %c", input[i])
        }
    }
    tokens = append(tokens, Token{Type: TokenEOF, Value: ""})
    return tokens, nil
}

func isWhitespace(c byte) bool {
    return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}

func isLetter(c byte) bool {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

func isDigit(c byte) bool {
    return c >= '0' && c <= '9'
}

func isOperatorChar(c byte) bool {
    return strings.ContainsAny(string(c), "+-*/%&|^<>!=")
}

func isOperator(s string) bool {
    operators := []string{"+", "-", "*", "/", "%", "&", "|", "^", "<", ">", "!", "=",
        "++", "--", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<", ">>", "==", "!=", "<=", ">="}
    for _, op := range operators {
        if op == s {
            return true
        }
    }
    return false
}

通过上述设计,词法分析器可以将输入字符串解析为关键字、操作符等记号序列。