github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/asm/lexer.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:34</date>
    10  //</624450077330509824>
    11  
    12  
    13  package asm
    14  
    15  import (
    16  	"fmt"
    17  	"os"
    18  	"strings"
    19  	"unicode"
    20  	"unicode/utf8"
    21  )
    22  
    23  //statefn在
    24  //lexer解析
    25  //当前状态。
    26  type stateFn func(*lexer) stateFn
    27  
    28  //当lexer发现
    29  //一种新的可分割代币。这些都送过去了
    30  //词汇的标记通道
    31  type token struct {
    32  	typ    tokenType
    33  	lineno int
    34  	text   string
    35  }
    36  
    37  //tokentype是lexer的不同类型
    38  //能够解析并返回。
    39  type tokenType int
    40  
    41  const (
    42  eof              tokenType = iota //文件结束
    43  lineStart                         //行开始时发出
    44  lineEnd                           //行结束时发出
    45  invalidStatement                  //任何无效的语句
    46  element                           //元素分析期间的任何元素
    47  label                             //找到标签时发出标签
    48  labelDef                          //找到新标签时发出标签定义
    49  number                            //找到数字时发出数字
    50  stringValue                       //当找到字符串时,将发出StringValue
    51  
    52  Numbers            = "1234567890"                                           //表示任何十进制数的字符
    53  HexadecimalNumbers = Numbers + "aAbBcCdDeEfF"                               //表示任何十六进制的字符
    54  Alpha              = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" //表示字母数字的字符
    55  )
    56  
    57  //字符串实现字符串
    58  func (it tokenType) String() string {
    59  	if int(it) > len(stringtokenTypes) {
    60  		return "invalid"
    61  	}
    62  	return stringtokenTypes[it]
    63  }
    64  
    65  var stringtokenTypes = []string{
    66  	eof:              "EOF",
    67  	invalidStatement: "invalid statement",
    68  	element:          "element",
    69  	lineEnd:          "end of line",
    70  	lineStart:        "new line",
    71  	label:            "label",
    72  	labelDef:         "label definition",
    73  	number:           "number",
    74  	stringValue:      "string",
    75  }
    76  
    77  //lexer是解析的基本构造
    78  //源代码并将其转换为令牌。
    79  //标记由编译器解释。
    80  type lexer struct {
    81  input string //输入包含程序的源代码
    82  
    83  tokens chan token //令牌用于将令牌传递给侦听器
    84  state  stateFn    //当前状态函数
    85  
    86  lineno            int //源文件中的当前行号
    87  start, pos, width int //词法和返回值的位置
    88  
    89  debug bool //触发调试输出的标志
    90  }
    91  
    92  //lex使用给定的源按名称对程序进行lex。它返回一个
    93  //传递令牌的通道。
    94  func Lex(name string, source []byte, debug bool) <-chan token {
    95  	ch := make(chan token)
    96  	l := &lexer{
    97  		input:  string(source),
    98  		tokens: ch,
    99  		state:  lexLine,
   100  		debug:  debug,
   101  	}
   102  	go func() {
   103  		l.emit(lineStart)
   104  		for l.state != nil {
   105  			l.state = l.state(l)
   106  		}
   107  		l.emit(eof)
   108  		close(l.tokens)
   109  	}()
   110  
   111  	return ch
   112  }
   113  
   114  //next返回程序源中的下一个rune。
   115  func (l *lexer) next() (rune rune) {
   116  	if l.pos >= len(l.input) {
   117  		l.width = 0
   118  		return 0
   119  	}
   120  	rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
   121  	l.pos += l.width
   122  	return rune
   123  }
   124  
   125  //备份备份最后一个已分析的元素(多字符)
   126  func (l *lexer) backup() {
   127  	l.pos -= l.width
   128  }
   129  
   130  //Peek返回下一个符文,但不前进搜索者
   131  func (l *lexer) peek() rune {
   132  	r := l.next()
   133  	l.backup()
   134  	return r
   135  }
   136  
   137  //忽略推进搜索者并忽略值
   138  func (l *lexer) ignore() {
   139  	l.start = l.pos
   140  }
   141  
   142  //接受检查给定输入是否与下一个rune匹配
   143  func (l *lexer) accept(valid string) bool {
   144  	if strings.ContainsRune(valid, l.next()) {
   145  		return true
   146  	}
   147  
   148  	l.backup()
   149  
   150  	return false
   151  }
   152  
   153  //acceptrun将继续推进seeker直到有效
   154  //再也见不到了。
   155  func (l *lexer) acceptRun(valid string) {
   156  	for strings.ContainsRune(valid, l.next()) {
   157  	}
   158  	l.backup()
   159  }
   160  
   161  //acceptrununtil是acceptrun的倒数,将继续
   162  //把探索者推进直到找到符文。
   163  func (l *lexer) acceptRunUntil(until rune) bool {
   164  //继续运行,直到找到符文
   165  	for i := l.next(); !strings.ContainsRune(string(until), i); i = l.next() {
   166  		if i == 0 {
   167  			return false
   168  		}
   169  	}
   170  
   171  	return true
   172  }
   173  
   174  //blob返回当前值
   175  func (l *lexer) blob() string {
   176  	return l.input[l.start:l.pos]
   177  }
   178  
   179  //向令牌通道发送新令牌以进行处理
   180  func (l *lexer) emit(t tokenType) {
   181  	token := token{t, l.lineno, l.blob()}
   182  
   183  	if l.debug {
   184  		fmt.Fprintf(os.Stderr, "%04d: (%-20v) %s\n", token.lineno, token.typ, token.text)
   185  	}
   186  
   187  	l.tokens <- token
   188  	l.start = l.pos
   189  }
   190  
   191  //lexline是用于词法处理行的状态函数
   192  func lexLine(l *lexer) stateFn {
   193  	for {
   194  		switch r := l.next(); {
   195  		case r == '\n':
   196  			l.emit(lineEnd)
   197  			l.ignore()
   198  			l.lineno++
   199  
   200  			l.emit(lineStart)
   201  		case r == ';' && l.peek() == ';':
   202  			return lexComment
   203  		case isSpace(r):
   204  			l.ignore()
   205  		case isLetter(r) || r == '_':
   206  			return lexElement
   207  		case isNumber(r):
   208  			return lexNumber
   209  		case r == '@':
   210  			l.ignore()
   211  			return lexLabel
   212  		case r == '"':
   213  			return lexInsideString
   214  		default:
   215  			return nil
   216  		}
   217  	}
   218  }
   219  
   220  //lexcomment分析当前位置直到结束
   221  //并丢弃文本。
   222  func lexComment(l *lexer) stateFn {
   223  	l.acceptRunUntil('\n')
   224  	l.ignore()
   225  
   226  	return lexLine
   227  }
   228  
   229  //lexmlabel解析当前标签,发出并返回
   230  //lex文本状态函数用于推进分析
   231  //过程。
   232  func lexLabel(l *lexer) stateFn {
   233  	l.acceptRun(Alpha + "_")
   234  
   235  	l.emit(label)
   236  
   237  	return lexLine
   238  }
   239  
   240  //lexinsideString对字符串内部进行lexi,直到
   241  //state函数查找右引号。
   242  //它返回lex文本状态函数。
   243  func lexInsideString(l *lexer) stateFn {
   244  	if l.acceptRunUntil('"') {
   245  		l.emit(stringValue)
   246  	}
   247  
   248  	return lexLine
   249  }
   250  
   251  func lexNumber(l *lexer) stateFn {
   252  	acceptance := Numbers
   253  	if l.accept("0") || l.accept("xX") {
   254  		acceptance = HexadecimalNumbers
   255  	}
   256  	l.acceptRun(acceptance)
   257  
   258  	l.emit(number)
   259  
   260  	return lexLine
   261  }
   262  
   263  func lexElement(l *lexer) stateFn {
   264  	l.acceptRun(Alpha + "_" + Numbers)
   265  
   266  	if l.peek() == ':' {
   267  		l.emit(labelDef)
   268  
   269  		l.accept(":")
   270  		l.ignore()
   271  	} else {
   272  		l.emit(element)
   273  	}
   274  	return lexLine
   275  }
   276  
   277  func isLetter(t rune) bool {
   278  	return unicode.IsLetter(t)
   279  }
   280  
   281  func isSpace(t rune) bool {
   282  	return unicode.IsSpace(t)
   283  }
   284  
   285  func isNumber(t rune) bool {
   286  	return unicode.IsNumber(t)
   287  }
   288