- Go语言QQ群: 102319854, 1055927514
- 凹语言(凹读音"Wa")(The Wa Programming Language): https://github.com/wa-lang/wa
创建wc.h文件, 包含要统计的变量和yylex词法解析函数:
extern int chars; extern int words; extern int lines;
创建wc.c文件, 保护变量的定义并初始化为0值:
#include "wc.h" int chars = 0; int words = 0; int lines = 0;
最重要的词法分析函数的实现由flex工具生成:
extern int yylex(void);
创建wc.l文件:
%option noyywrap %{ #include "wc.h" %} %% [a-zA-Z]+ { words++; chars += strlen(yytext); } \n { chars++; lines++; } . { chars++; } %%
通过以下命令生成lex.yy.c文件(其中包含yylex函数的实现):
$ flex --prefix=yy --header-file=lex.yy.h wc.l
然后在Go语言中调用词法分析器并输出结果:
package main //#include "lex.yy.h" //#include "wc.h" import "C" import "fmt" func main() { C.yylex() fmt.Printf("%8d%8d%8d\n", C.lines, C.words, C.chars) }
通过以下的命令运行:
$ cat wc.l | go run .
19 47 355
flex生成的代码导出了yyin和yyout全局变量,可以用于指定打开的输入流文件(否则从标准输入读取):
extern FILE *yyin, *yyout; `` 不过以上的是C语言文件接口,在Go语言中使用比较麻烦。此外flex还生成了以下三个函数: ```c YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
然后调整Go语言函数:
package main //#include "lex.yy.h" //#include "wc.h" import "C" import ( "flag" "fmt" "io/ioutil" "log" "os" ) var ( flagInput = flag.String("f", "", "set input file") ) func main() { flag.Parse() var ( content []byte err error ) if *flagInput == "" { // cat wc.go | go run . content, err = ioutil.ReadAll(os.Stdin) if err != nil { log.Fatal(err) } } else { // go run . -f wc.go content, err = ioutil.ReadFile(*flagInput) if err != nil { log.Fatal(err) } } C.yy_scan_bytes( (*C.char)(C.CBytes(content)), C.yy_size_t(len(content)), ) C.yylex() fmt.Printf("%8d%8d%8d\n", C.lines, C.words, C.chars) }
在调用C.yylex函数之前调用C.yy_scan_bytes函数用Go语言的切片初始化词法扫描的缓冲区。