github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/qiuyesuifeng/golex/doc.go (about) 1 // Copyright (c) 2014 The golex Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Golex is a lex/flex like (not fully POSIX lex compatible) utility. 6 // It renders .l formated data (http://flex.sourceforge.net/manual/Format.html#Format) to Go source code. 7 // The .l data can come from a file named in a command line argument. 8 // If no non-opt args are given, golex reads stdin. 9 // 10 // Options: 11 // -DFA print the DFA to stdout and quit 12 // -nodfaopt disable DFA optimization - don't use this for production code 13 // -o fname write to file `fname`, default is `lex.yy.go` 14 // -t write to stdout 15 // -v write some scanner statistics to stderr 16 // -32bit assume unicode rune lexer (partially implemented, disabled) 17 // 18 // To get the latest golex version: 19 // 20 // $ go get -u yougam/libraries/cznic/golex 21 // 22 // Run time library 23 // 24 // Please see http://godoc.org/yougam/libraries/cznic/golex/lex. 25 // 26 // Changelog 27 // 28 // 2014-11-18: Golex now supports %yym - a hook which can be used to mark an 29 // accepting state. 30 // 31 // Implementing POSIX-like longest match 32 // 33 // Consider for example this .l file: 34 // 35 // $ cat main.l 36 // %{ 37 // package main 38 // 39 // import ( 40 // "flag" 41 // "fmt" 42 // ) 43 // 44 // var ( 45 // c byte 46 // src string 47 // in []byte 48 // un []byte 49 // mark int 50 // ) 51 // 52 // func lex() (s string) { 53 // %} 54 // 55 // %yyn next() 56 // %yyc c 57 // %yym fmt.Printf("\tstate accepts: %q\n", in); mark = len(in) 58 // 59 // %% 60 // in = in[:0] 61 // mark = -1 62 // 63 // \0 64 // return "EOF" 65 // 66 // a([bcd]*z([efg]*z)?)? 67 // return fmt.Sprintf("match(%q)", in) 68 // 69 // %% 70 // if mark >= 0 { 71 // if len(in) > mark { 72 // unget(c) 73 // for i := len(in)-1; i >= mark; i-- { 74 // unget(in[i]) 75 // } 76 // next() 77 // } 78 // in = in[:mark] 79 // goto yyAction // Hook: Execute the semantic action of the last matched rule. 80 // } 81 // 82 // switch n := len(in); n { 83 // case 0: // [] z 84 // s = fmt.Sprintf("%q", c) 85 // next() 86 // case 1: // [x] z 87 // s = fmt.Sprintf("%q", in[0]) 88 // default: // [x, y, ...], z 89 // s = fmt.Sprintf("%q", in[0]) 90 // unget(c) // z 91 // for i := n - 1; i > 1; i-- { 92 // unget(in[i]) // ... 93 // } 94 // c = in[1] // y 95 // } 96 // return s 97 // } 98 // 99 // func next() { 100 // if len(un) != 0 { 101 // c = un[len(un)-1] 102 // un = un[:len(un)-1] 103 // return 104 // } 105 // 106 // in = append(in, c) 107 // if len(src) == 0 { 108 // c = 0 109 // return 110 // } 111 // 112 // c = src[0] 113 // fmt.Printf("\tnext: %q\n", c) 114 // src = src[1:] 115 // } 116 // 117 // func unget(b byte) { 118 // un = append(un, b) 119 // } 120 // 121 // func main() { 122 // flag.Parse() 123 // if flag.NArg() > 0 { 124 // src = flag.Arg(0) 125 // } 126 // next() 127 // for { 128 // s := lex() 129 // fmt.Println(s) 130 // if s == "EOF" { 131 // break 132 // } 133 // } 134 // } 135 // $ 136 // 137 // Execution and output: 138 // 139 // $ golex -o main.go main.l && go run main.go abzez0abzefgxy 140 // next: 'a' 141 // next: 'b' 142 // state accepts: "a" 143 // next: 'z' 144 // next: 'e' 145 // state accepts: "abz" 146 // next: 'z' 147 // next: '0' 148 // state accepts: "abzez" 149 // match("abzez") 150 // next: 'a' 151 // '0' 152 // next: 'b' 153 // state accepts: "a" 154 // next: 'z' 155 // next: 'e' 156 // state accepts: "abz" 157 // next: 'f' 158 // next: 'g' 159 // next: 'x' 160 // match("abz") 161 // 'e' 162 // 'f' 163 // 'g' 164 // next: 'y' 165 // 'x' 166 // 'y' 167 // state accepts: "\x00" 168 // EOF 169 // $ 170 // 171 // 2014-11-15: Golex's output is now gofmt'ed, if possible. 172 // 173 // Missing/differing functionality of the current renderer (compared to flex): 174 // - No runtime tokenizer package/environment 175 // (but the freedom to have/write any fitting one's specific task(s)). 176 // - The generated FSM picks the rules in the order of their appearance in the .l source, 177 // but "flex picks the rule that matches the most text". 178 // - And probably more. 179 // Further limitations on the .l source are listed in the cznic/lex package godocs. 180 // 181 // A simple golex program example (make example1 && ./example1): 182 // 183 // %{ 184 // package main 185 // 186 // import ( 187 // "bufio" 188 // "fmt" 189 // "log" 190 // "os" 191 // ) 192 // 193 // var ( 194 // src = bufio.NewReader(os.Stdin) 195 // buf []byte 196 // current byte 197 // ) 198 // 199 // func getc() byte { 200 // if current != 0 { 201 // buf = append(buf, current) 202 // } 203 // current = 0 204 // if b, err := src.ReadByte(); err == nil { 205 // current = b 206 // } 207 // return current 208 // } 209 // 210 // // %yyc is a "macro" to access the "current" character. 211 // // 212 // // %yyn is a "macro" to move to the "next" character. 213 // // 214 // // %yyb is a "macro" to return the begining-of-line status (a bool typed value). 215 // // It is used for patterns like `^re`. 216 // // Example: %yyb prev == 0 || prev == '\n' 217 // // 218 // // %yyt is a "macro" to return the top/current start condition (an int typed value). 219 // // It is used when there are patterns with conditions like `<cond>re`. 220 // // Example: %yyt startCond 221 // 222 // func main() { // This left brace is closed by *1 223 // c := getc() // init 224 // %} 225 // 226 // %yyc c 227 // %yyn c = getc() 228 // 229 // D [0-9]+ 230 // 231 // %% 232 // buf = buf[:0] // Code before the first rule is executed before every scan cycle (state 0 action) 233 // 234 // [ \t\n\r]+ // Ignore whitespace 235 // 236 // {D} fmt.Printf("int %q\n", buf) 237 // 238 // {D}\.{D}?|\.{D} fmt.Printf("float %q\n", buf) 239 // 240 // \0 return // Exit on EOF or any other error 241 // 242 // . fmt.Printf("%q\n", buf) // Printout any other unrecognized stuff 243 // 244 // %% 245 // // The rendered scanner enters top of the user code section when 246 // // lexem recongition fails. In this example it should never happen. 247 // log.Fatal("scanner internal error") 248 // 249 // } // *1 this right brace 250 package main