github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/asm/lexer.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package asm 26 27 import ( 28 "fmt" 29 "os" 30 "strings" 31 "unicode" 32 "unicode/utf8" 33 ) 34 35 //statefn在 36 //lexer解析 37 //当前状态。 38 type stateFn func(*lexer) stateFn 39 40 //当lexer发现 41 //一种新的可分割代币。这些都送过去了 42 //词汇的标记通道 43 type token struct { 44 typ tokenType 45 lineno int 46 text string 47 } 48 49 //tokentype是lexer的不同类型 50 //能够解析并返回。 51 type tokenType int 52 53 const ( 54 eof tokenType = iota //文件结束 55 lineStart //行开始时发出 56 lineEnd //行结束时发出 57 invalidStatement //任何无效的语句 58 element //元素分析期间的任何元素 59 label //找到标签时发出标签 60 labelDef //找到新标签时发出标签定义 61 number //找到数字时发出数字 62 stringValue //当找到字符串时,将发出StringValue 63 64 Numbers = "1234567890" //表示任何十进制数的字符 65 HexadecimalNumbers = Numbers + "aAbBcCdDeEfF" //表示任何十六进制的字符 66 Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" //表示字母数字的字符 67 ) 68 69 //字符串实现字符串 70 func (it tokenType) String() string { 71 if int(it) > len(stringtokenTypes) { 72 return "invalid" 73 } 74 return stringtokenTypes[it] 75 } 76 77 var stringtokenTypes = []string{ 78 eof: "EOF", 79 invalidStatement: "invalid statement", 80 element: "element", 81 lineEnd: "end of line", 82 lineStart: "new line", 83 label: "label", 84 labelDef: "label definition", 85 number: "number", 86 stringValue: "string", 87 } 88 89 //lexer是解析的基本构造 90 //源代码并将其转换为令牌。 91 //标记由编译器解释。 92 type lexer struct { 93 input string //输入包含程序的源代码 94 95 tokens chan token //令牌用于将令牌传递给侦听器 96 state stateFn // 97 98 lineno int //源文件中的当前行号 99 start, pos, width int //词法和返回值的位置 100 101 debug bool // 102 } 103 104 //lex使用给定的源按名称对程序进行lex。它返回一个 105 //传递令牌的通道。 106 func Lex(name string, source []byte, debug bool) <-chan token { 107 ch := make(chan token) 108 l := &lexer{ 109 input: string(source), 110 tokens: ch, 111 state: lexLine, 112 debug: debug, 113 } 114 go func() { 115 l.emit(lineStart) 116 for l.state != nil { 117 l.state = l.state(l) 118 } 119 l.emit(eof) 120 close(l.tokens) 121 }() 122 123 return ch 124 } 125 126 //next返回程序源中的下一个rune。 127 func (l *lexer) next() (rune rune) { 128 if l.pos >= len(l.input) { 129 l.width = 0 130 return 0 131 } 132 rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) 133 l.pos += l.width 134 return rune 135 } 136 137 //备份备份最后一个已分析的元素(多字符) 138 func (l *lexer) backup() { 139 l.pos -= l.width 140 } 141 142 //Peek返回下一个符文,但不前进搜索者 143 func (l *lexer) peek() rune { 144 r := l.next() 145 l.backup() 146 return r 147 } 148 149 //忽略推进搜索者并忽略值 150 func (l *lexer) ignore() { 151 l.start = l.pos 152 } 153 154 //接受检查给定输入是否与下一个rune匹配 155 func (l *lexer) accept(valid string) bool { 156 if strings.ContainsRune(valid, l.next()) { 157 return true 158 } 159 160 l.backup() 161 162 return false 163 } 164 165 //acceptrun将继续推进seeker直到有效 166 //再也见不到了。 167 func (l *lexer) acceptRun(valid string) { 168 for strings.ContainsRune(valid, l.next()) { 169 } 170 l.backup() 171 } 172 173 //acceptrununtil是acceptrun的倒数,将继续 174 //把探索者推进直到找到符文。 175 func (l *lexer) acceptRunUntil(until rune) bool { 176 //继续运行,直到找到符文 177 for i := l.next(); !strings.ContainsRune(string(until), i); i = l.next() { 178 if i == 0 { 179 return false 180 } 181 } 182 183 return true 184 } 185 186 //blob返回当前值 187 func (l *lexer) blob() string { 188 return l.input[l.start:l.pos] 189 } 190 191 //向令牌通道发送新令牌以进行处理 192 func (l *lexer) emit(t tokenType) { 193 token := token{t, l.lineno, l.blob()} 194 195 if l.debug { 196 fmt.Fprintf(os.Stderr, "%04d: (%-20v) %s\n", token.lineno, token.typ, token.text) 197 } 198 199 l.tokens <- token 200 l.start = l.pos 201 } 202 203 //lexline是用于词法处理行的状态函数 204 func lexLine(l *lexer) stateFn { 205 for { 206 switch r := l.next(); { 207 case r == '\n': 208 l.emit(lineEnd) 209 l.ignore() 210 l.lineno++ 211 212 l.emit(lineStart) 213 case r == ';' && l.peek() == ';': 214 return lexComment 215 case isSpace(r): 216 l.ignore() 217 case isLetter(r) || r == '_': 218 return lexElement 219 case isNumber(r): 220 return lexNumber 221 case r == '@': 222 l.ignore() 223 return lexLabel 224 case r == '"': 225 return lexInsideString 226 default: 227 return nil 228 } 229 } 230 } 231 232 //lexcomment分析当前位置直到结束 233 //并丢弃文本。 234 func lexComment(l *lexer) stateFn { 235 l.acceptRunUntil('\n') 236 l.ignore() 237 238 return lexLine 239 } 240 241 //lexmlabel解析当前标签,发出并返回 242 //lex文本状态函数用于推进分析 243 //过程。 244 func lexLabel(l *lexer) stateFn { 245 l.acceptRun(Alpha + "_") 246 247 l.emit(label) 248 249 return lexLine 250 } 251 252 //lexinsideString对字符串内部进行lexi,直到 253 // 254 //它返回lex文本状态函数。 255 func lexInsideString(l *lexer) stateFn { 256 if l.acceptRunUntil('"') { 257 l.emit(stringValue) 258 } 259 260 return lexLine 261 } 262 263 func lexNumber(l *lexer) stateFn { 264 acceptance := Numbers 265 if l.accept("0") || l.accept("xX") { 266 acceptance = HexadecimalNumbers 267 } 268 l.acceptRun(acceptance) 269 270 l.emit(number) 271 272 return lexLine 273 } 274 275 func lexElement(l *lexer) stateFn { 276 l.acceptRun(Alpha + "_" + Numbers) 277 278 if l.peek() == ':' { 279 l.emit(labelDef) 280 281 l.accept(":") 282 l.ignore() 283 } else { 284 l.emit(element) 285 } 286 return lexLine 287 } 288 289 func isLetter(t rune) bool { 290 return unicode.IsLetter(t) 291 } 292 293 func isSpace(t rune) bool { 294 return unicode.IsSpace(t) 295 } 296 297 func isNumber(t rune) bool { 298 return unicode.IsNumber(t) 299 }