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