编译器学习之词法分析

kekemuyu · · 621 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

根据《编译器设计之路》中的neopascal实现,书中是用c++实现的。我计划改为go语言版,以下是用go实现的词法分析部分。 https://github.com/kekemuyu/neopascal ```go package main import ( "fmt" "io/ioutil" "strconv" log "github.com/donnie4w/go-logger/logger" "strings" ) type CToken struct { m_iKind int m_szContent string m_iRow int } var ( m_szLexTbl [50][130]int m_szSource string m_szFileName string m_KeywordTbl map[string]int m_szBuffer string m_iRow int m_iPos int m_iNonterminal int m_pTokenList []CToken ) func init() { LexInit() } func LexInit() { m_pTokenList = make([]CToken, 0) m_KeywordTbl = make(map[string]int) SetLexTbl(FileToString("lex.txt")) SetKeywords(FileToString("KEYWORDS.txt")) // for i := 0; i < 50; i++ { // fmt.Println(m_szLexTbl[i]) // } // fmt.Println(m_KeywordTbl) } func main() { GetToken(FileToString("test.p")) log.Debug(m_pTokenList) } func FileToString(filename string) string { bs, err := ioutil.ReadFile(filename) if err != nil { fmt.Println(err) return "" } return string(bs) } func SetLexTbl(szStr string) { iTmp := 0 // szs := strings.TrimSpace(szStr) szs := strings.Replace(szStr, "\r\n", "", -1) for iRow := 0; iRow <= 36; iRow++ { for iCol := 0; iCol <= 128; iCol++ { t, _ := strconv.Atoi(szs[iTmp:(iTmp + 3)]) // fmt.Println(iTmp, iTmp+3, szs[iTmp:(iTmp+3)]) m_szLexTbl[iRow][iCol] = t iTmp = iTmp + 3 } } } func SetKeywords(szSource string) { var szTmp string cnt := 0 for i := 0; i < len(szSource); i++ { if szSource[i] != '\n' { szTmp += string(szSource[i]) } else { if szTmp != "" { m_KeywordTbl[szTmp] = cnt szTmp = "" cnt++ } } } if szTmp != "" { m_KeywordTbl[szTmp] = cnt } } func GetToken(zsStr string) bool { bTag := true m_iPos = 0 zss := zsStr + "" m_iRow = 1 TmpPos := 0 for (m_iPos < len(zss)) && (bTag) { if string(zss[m_iPos]) == "\n" && TmpPos != m_iPos { m_iRow++ TmpPos = m_iRow } m_szBuffer += string(zss[m_iPos]) col := zss[m_iPos] if zss[m_iPos] >= 128 { col = 128 } bTag = Process(m_szLexTbl[m_iNonterminal][col]) if !bTag { fmt.Println(m_iRow, ":", "词法分析错误,请检查单词") return false } m_iPos++ } return bTag } func Process(iTag int) bool { iTmp := 0 if iTag == -99 { return false } if iTag < 0 { // log.Debug(m_szBuffer) m_szBuffer = m_szBuffer[:len(m_szBuffer)-1] m_iPos-- m_szBuffer = strings.TrimSpace(m_szBuffer) // log.Debug(m_szBuffer) if iTag == -1 { m_szBuffer = strings.ToUpper(m_szBuffer) if SearchKeyword(m_szBuffer) { EmitToken(iTmp+40, "", m_iRow) } else { if m_szBuffer == "TRUE" || m_szBuffer == "FALSE" { EmitToken(3, m_szBuffer, m_iRow) } else { EmitToken(1, m_szBuffer, m_iRow) } } } if iTag >= -6 && iTag <= -2 { EmitToken(-iTag, m_szBuffer, m_iRow) } if iTag >= -15 && iTag <= -7 { EmitToken(-iTag, m_szBuffer, m_iRow) } if iTag >= -28 && iTag <= -16 { EmitToken(-iTag, m_szBuffer, m_iRow) } if iTag == -42 { m_szBuffer := m_szBuffer[:len(m_szBuffer)-1] m_iPos-- EmitToken(3, m_szBuffer, m_iRow) } m_szBuffer = "" m_iNonterminal = 0 } else { m_iNonterminal = iTag } return true } func SearchKeyword(szKey string) bool { if _, ok := m_KeywordTbl[szKey]; ok != true { return false } else { return true } } func EmitToken(iKind int, iContent string, iRow int) { ct := CToken{ m_iKind: iKind, m_szContent: iContent, m_iRow: iRow, } m_pTokenList = append(m_pTokenList, ct) } ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

621 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传