搜索
bottom↓
回复: 5

编译器学习之词法分析

[复制链接]

出0入0汤圆

发表于 2019-12-1 11:24:20 | 显示全部楼层 |阅读模式
根据《编译器设计之路》中的neopascal实现,书中是用c++实现的。我计划改为go语言版,以下是用go实现的词法分析部分。https://github.com/kekemuyu/neopascal
  1. package main

  2. import (
  3.         "fmt"
  4.         "io/ioutil"
  5.         "strconv"

  6.         log "github.com/donnie4w/go-logger/logger"

  7.         "strings"
  8. )

  9. type CToken struct {
  10.         m_iKind     int
  11.         m_szContent string
  12.         m_iRow      int
  13. }

  14. var (
  15.         m_szLexTbl     [50][130]int
  16.         m_szSource     string
  17.         m_szFileName   string
  18.         m_KeywordTbl   map[string]int
  19.         m_szBuffer     string
  20.         m_iRow         int
  21.         m_iPos         int
  22.         m_iNonterminal int
  23.         m_pTokenList   []CToken
  24. )

  25. func init() {
  26.         LexInit()
  27. }

  28. func LexInit() {
  29.         m_pTokenList = make([]CToken, 0)
  30.         m_KeywordTbl = make(map[string]int)
  31.         SetLexTbl(FileToString("lex.txt"))
  32.         SetKeywords(FileToString("KEYWORDS.txt"))
  33.         // for i := 0; i < 50; i++ {
  34.         //         fmt.Println(m_szLexTbl[i])
  35.         // }

  36.         // fmt.Println(m_KeywordTbl)
  37. }

  38. func main() {

  39.         GetToken(FileToString("test.p"))
  40.         log.Debug(m_pTokenList)
  41. }

  42. func FileToString(filename string) string {
  43.         bs, err := ioutil.ReadFile(filename)
  44.         if err != nil {
  45.                 fmt.Println(err)
  46.                 return ""
  47.         }
  48.         return string(bs)

  49. }
  50. func SetLexTbl(szStr string) {

  51.         iTmp := 0
  52.         // szs := strings.TrimSpace(szStr)
  53.         szs := strings.Replace(szStr, "\r\n", "", -1)

  54.         for iRow := 0; iRow <= 36; iRow++ {
  55.                 for iCol := 0; iCol <= 128; iCol++ {

  56.                         t, _ := strconv.Atoi(szs[iTmp:(iTmp + 3)])
  57.                         // fmt.Println(iTmp, iTmp+3, szs[iTmp:(iTmp+3)])

  58.                         m_szLexTbl[iRow][iCol] = t
  59.                         iTmp = iTmp + 3
  60.                 }
  61.         }

  62. }

  63. func SetKeywords(szSource string) {
  64.         var szTmp string
  65.         cnt := 0

  66.         for i := 0; i < len(szSource); i++ {

  67.                 if szSource[i] != '\n' {

  68.                         szTmp += string(szSource[i])
  69.                 } else {

  70.                         if szTmp != "" {

  71.                                 m_KeywordTbl[szTmp] = cnt
  72.                                 szTmp = ""
  73.                                 cnt++
  74.                         }
  75.                 }
  76.         }
  77.         if szTmp != "" {

  78.                 m_KeywordTbl[szTmp] = cnt
  79.         }

  80. }

  81. func GetToken(zsStr string) bool {
  82.         bTag := true
  83.         m_iPos = 0

  84.         zss := zsStr + ""

  85.         m_iRow = 1
  86.         TmpPos := 0

  87.         for (m_iPos < len(zss)) && (bTag) {

  88.                 if string(zss[m_iPos]) == "\n" && TmpPos != m_iPos {

  89.                         m_iRow++
  90.                         TmpPos = m_iRow
  91.                 }
  92.                 m_szBuffer += string(zss[m_iPos])

  93.                 col := zss[m_iPos]
  94.                 if zss[m_iPos] >= 128 {
  95.                         col = 128
  96.                 }

  97.                 bTag = Process(m_szLexTbl[m_iNonterminal][col])
  98.                 if !bTag {
  99.                         fmt.Println(m_iRow, ":", "词法分析错误,请检查单词")
  100.                         return false
  101.                 }
  102.                 m_iPos++
  103.         }
  104.         return bTag
  105. }

  106. func Process(iTag int) bool {
  107.         iTmp := 0

  108.         if iTag == -99 {

  109.                 return false
  110.         }
  111.         if iTag < 0 {
  112.                 // log.Debug(m_szBuffer)
  113.                 m_szBuffer = m_szBuffer[:len(m_szBuffer)-1]
  114.                 m_iPos--
  115.                 m_szBuffer = strings.TrimSpace(m_szBuffer)
  116.                 // log.Debug(m_szBuffer)
  117.                 if iTag == -1 {

  118.                         m_szBuffer = strings.ToUpper(m_szBuffer)

  119.                         if SearchKeyword(m_szBuffer) {
  120.                                 EmitToken(iTmp+40, "", m_iRow)
  121.                         } else {
  122.                                 if m_szBuffer == "TRUE" || m_szBuffer == "FALSE" {
  123.                                         EmitToken(3, m_szBuffer, m_iRow)
  124.                                 } else {
  125.                                         EmitToken(1, m_szBuffer, m_iRow)
  126.                                 }
  127.                         }
  128.                 }
  129.                 if iTag >= -6 && iTag <= -2 {
  130.                         EmitToken(-iTag, m_szBuffer, m_iRow)
  131.                 }
  132.                 if iTag >= -15 && iTag <= -7 {
  133.                         EmitToken(-iTag, m_szBuffer, m_iRow)
  134.                 }
  135.                 if iTag >= -28 && iTag <= -16 {
  136.                         EmitToken(-iTag, m_szBuffer, m_iRow)
  137.                 }
  138.                 if iTag == -42 {
  139.                         m_szBuffer := m_szBuffer[:len(m_szBuffer)-1]
  140.                         m_iPos--
  141.                         EmitToken(3, m_szBuffer, m_iRow)
  142.                 }
  143.                 m_szBuffer = ""
  144.                 m_iNonterminal = 0
  145.         } else {

  146.                 m_iNonterminal = iTag

  147.         }
  148.         return true

  149. }

  150. func SearchKeyword(szKey string) bool {
  151.         if _, ok := m_KeywordTbl[szKey]; ok != true {
  152.                 return false
  153.         } else {
  154.                 return true
  155.         }

  156. }

  157. func EmitToken(iKind int, iContent string, iRow int) {
  158.         ct := CToken{
  159.                 m_iKind:     iKind,
  160.                 m_szContent: iContent,
  161.                 m_iRow:      iRow,
  162.         }
  163.         m_pTokenList = append(m_pTokenList, ct)

  164. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出10入0汤圆

发表于 2019-12-1 12:37:32 来自手机 | 显示全部楼层
点赞,而且 go 语言写出 MFC 风格的我也是第一次见。

出0入0汤圆

 楼主| 发表于 2019-12-1 14:47:22 | 显示全部楼层
yoz 发表于 2019-12-1 12:37
点赞,而且 go 语言写出 MFC 风格的我也是第一次见。

是的,很难看,因为是照搬的c++代码还没go化,后续会用gostyle模块化。

出0入0汤圆

发表于 2019-12-1 18:09:14 | 显示全部楼层
不明觉厉

出0入0汤圆

发表于 2019-12-1 19:05:44 | 显示全部楼层
本帖最后由 RAMILE 于 2019-12-1 19:08 编辑

lz 你咋不试试 rust  ,现在rust被吹上天了

出0入0汤圆

 楼主| 发表于 2019-12-1 20:34:09 | 显示全部楼层
本帖最后由 FireBrain 于 2019-12-1 20:35 编辑
RAMILE 发表于 2019-12-1 19:05
lz 你咋不试试 rust  ,现在rust被吹上天了


我喜欢简单的语言,尝试过rust,被rust的语言语法搞得头大,放弃了.最近发现一个新的类似go的语言vlang,没有gc,可能会尝试用这个.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 09:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表