`
superisaac
  • 浏览: 64360 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

goyacc初体验

阅读更多
google 的go语言里呆了goyacc工具,使用方法基本类似于贝尔实验室的yacc工具. 所以熟悉了解yacc工具的人应该比较容易掌握。不过网上几乎没有找到详细的step by step。 虽然yacc方面的资料比较多, 但是具体细节上goyacc还是有些不同的。所幸在源代码里有一个sample。具体位置是~/go/src/cmd/goyacc/units.y.   算是比较详细。于是照猫画虎,经过代码裁剪,我自己写了个简单的表达式计算器goexpr。
一个.y文件中, 由^%{ 和 ^%}包括的部分, 是嵌入代码。 %%中间的部分则是要解析的LALR(1)文法,其定义是非常直接的。
于yacc不同的是, goyacc没有配套的lex/flex程序, 需要手工写一个方法 Lex()来得到所有的token. 还要写一个方法Error作为出错时的回调函数。除此之外都是顺水顺风的比较简单的东西。
使用方法
goyacc goexpr.y && 6g y.go && 6l -o goexpr y.6
如果是x86架构,则把6换成8即可

代码如下
%{
	package main
	import (
		"fmt"
		"os"
		"io/ioutil"
		"flag"
		"bufio"
		)
	var fi *bufio.Reader
	var peekrune int
	var data []byte
	var linep int = 0
	var finalval float = 0
%}

%union
{
	vvar   string;
	numval float;
}

%token NUMBER
%token OP

%%
expr: 
         expr1
| expr '+' expr1
{
	$$.numval = $1.numval + $3.numval
	finalval = $$.numval
}
| expr '-' expr1
{
	$$.numval = $1.numval - $3.numval
	finalval = $$.numval
}

expr1:
         NUMBER
|        expr1 '*' NUMBER
{
	$$.numval = $1.numval * $3.numval
	finalval = $$.numval
}
|       expr1 '/' NUMBER
{
	$$.numval = $1.numval / 
		$3.numval
	finalval = $$.numval
}

%%

func getrune() int {
	if linep >= len(data) {
		return 0
	}
	c := data[linep]
	
	return int(c)
}

func next() {
	linep++
}

func getnumber(c int) int {
	var n int = 0
	for ;c>='0' && c <= '9'; {
		n += (c - '0')
		next()
		c = getrune()
	}
	yylval.numval = float(n)
	return NUMBER
	
}

func readblank() {
	var c int
	for c = getrune(); c == ' '; {
		next()
		c = getrune()
	}
}

func Lex() int {
	var c int
	readblank()
	c = getrune()
	if c >= '0' && c <= '9' {
		return getnumber(c)
	}
	switch c {
	case '+', '-', '*', '/':
		yylval.vvar = string(c)
		next()
		return c
	}
	return c
}

func Error(s string, v ...) {
	fmt.Printf("ERROR:%s\n", s)
	
}

func main() {
	if flag.NArg() == 0 {
		fmt.Printf("Usage goexpr <expr file>\n")
		os.Exit(1)
	}
	file := flag.Arg(0)
	f, err := os.Open(file, os.O_RDONLY, 0)
	if err != nil {
		fmt.Printf("Error opening %v: %v", file, err)
		os.Exit(2)
	}
	data, err = ioutil.ReadAll(f)
	if err != nil {
		fmt.Printf("Error reading file %v, %v\n", file, err)
		os.Exit(3)
	}

	Parse()   // Parse the data
	fmt.Printf("result = %g\n", finalval)
}



这段代码中, 如果 $3.numval 写成和上面一行, 这样
$$.numval = $1.numval / $3.numval
就会报错。
引用
y.go:61: syntax error: unexpected $
, 从源代码中看到,似乎"/" 被当成了单行注释的开始, 疑似bug, 待会儿汇报。
分享到:
评论

相关推荐

    bison_flex_1:非常基本的野牛和flex示例

    goyacc1:简单的goyacc示例(Go) goyacc2:简单的goyacc example2(Go) goyacc3:另一个带有解析器和表达式的goyacc示例(Go) 先决条件 Binson&Flex 走 去得到-u golang.org/x/tools/cmd/goyacc 怎么跑 make...

    用Go编写PHP解析器-Golang开发

    用Go编写PHP解析器该项目使用goyacc和golex库将PHP源解析为AST。 它可以用来编写静态分析,重构,指标,代码样式格式化工具。 在线尝试:用Go语言编写的dem PHP解析器该项目使用goyacc和ragel工具创建PHP解析器。 它...

    PostgreSQL样式解析器从CockroachDB拆分而来-Golang开发

    为了使事情变得容易,我做了以下事情:复制所有的pkg / sql / parser,pkg / sql / lex并简化依赖关系简化Makefile以仅生成goyacc的东西在解析器和lex中添加goyacc生成的文件以进行获取轻松工作,请参阅.gitignore...

    postgresql-parser:PostgreSQL解析器

    在解析器和lex中添加goyacc生成的文件,以使go get轻松工作,请参阅.gitignore文件 修剪etcd依赖项,请参阅go.mod 重命名除某些pkg/sql/parser测试外的所有测试文件 将所有必需的导入添加到供应商 取下panic满足...

    sessions:会话类型解释器实现

    expr.y 是一种玩具示例语言的 goyacc 实现,可以作为解析器未来实现的基础。 在这一点上,大多是废代码。 会话程序的有趣代码在escapes.go 中。 Escapes.go 包含对 Capecchi 等人的微积分限制版本的解释器。 2014 ...

    builddatabase:从头开始构建分布式SQL数据库

    [语法分析与goyacc用法] [解析整个语句的执行流程] [案例:为TiDB添加一个语句] [思考:如何支持json /协议缓冲区] 第四章MySQL协议支持 [协议概述] [如何用wireshark来辅助调试] [要求格式] [回应格式] [准备...

    golang design pattern go 设计模式实现.zip

    Go可以实现词法分析和语法解析,如使用解析库如`go-yacc`或`goyacc`。 17. **迭代器模式**:提供一种方法顺序访问聚合对象的元素,而又不暴露其底层表示。Go的range关键字可以实现迭代器模式。 18. **中介者模式**...

    monkey-programming-language:使用golang创建的编程语言“ Monkey”

    在 Go 语言中,可以使用自底向上的解析方法,如递归下降解析,或者使用第三方库如 GoGLexer 和 GoYacc 来辅助构建这些组件。 2. **类型系统**:Monkey 的类型系统可能包括基本类型(如整型、浮点型、布尔型和字符串...

    go-ast-book:《 Go语法树入门-开启自制编程语言和编译器之旅》(开源免费图书Go语言进阶掌握抽象语法树Go语言AST凹语言)

    Go语法树入门-开启自制编程语言和编译器之旅! Go语言QQ群:102319854,1055927514 ...凹语言(凹读音“ Wa”)(Wa编程语言): : 蚂蚁金服招聘云原生方向和编程语言方向职位(杭州/ P7):云原生方向要求熟悉k8s配套...

Global site tag (gtag.js) - Google Analytics