go tool yacc 中最简单的解析器
Simplest of parsers in go tool yacc
使用这个命令:
go tool yacc -p Verb -o verb.go boilerplate.y
正在尝试构建此 yacc 文件:
// boilerplate.y
%{
package main
import (
"bufio"
"fmt"
"os"
"unicode"
)
%}
%%
.|\n ECHO;
%%
func main() {
fi := bufio.NewReader(os.NewFile(0, "stdin"))
s, err := fi.ReadString('\n')
if err != nil {
fmt.Println('error', err)
}
VerbParse(&VerbLex{s: s})
}
错误:bad syntax on first rule: boilerplate.y:16
成功让这个例子工作:
https://github.com/golang-samples/yacc/blob/master/simple/calc.y
尝试构建我自己的并完成 lex & yacc 书。资源似乎仅限于不存在。
您的规格 rule
不正确。
规范文件具有以下声明:
declarations
%%
rules
%%
programs
其中 rule
定义为:
A : BODY ;
其中A是一个非终结符,而BODY是由tokens(终结符)、非终结符和文字。 :
和 ;
是规则声明语法的必需组件。
因此规则:
.|\n ECHO;
语法不正确。
因为您只是想回显输入,所以下面是一个基于 calc.y
的非常简单的实现(文件 echo.y):
规则
%%
in : /* empty */
| in input '\n'
{ fmt.Printf("Read character: %s\n", ) }
;
input : CHARACTER
| input CHARACTER
{ $$ = + }
;
程序
%%
type InputLex struct {
// contains one complete input string (with the trailing \n)
s string
// used to keep track of parser position along the above imput string
pos int
}
func (l *InputLex) Lex(lval *InputSymType) int {
var c rune = ' '
// skip through all the spaces, both at the ends and in between
for c == ' ' {
if l.pos == len(l.s) {
return 0
}
c = rune(l.s[l.pos])
l.pos += 1
}
// only look for input characters that are either digits or lower case
// to do more specific parsing, you'll define more tokens and have a
// more complex parsing logic here, choosing which token to return
// based on parsed input
if unicode.IsDigit(c) || unicode.IsLower(c) {
lval.val = string(c)
return CHARACTER
}
// do not return any token in case of unrecognized grammer
// this results in syntax error
return int(c)
}
func (l *InputLex) Error(s string) {
fmt.Printf("syntax error: %s\n", s)
}
func main() {
// same as in calc.y
}
func readline(fi *bufio.Reader) (string, bool) {
// same as in calc.y
}
要编译和 运行 这个程序,请在命令提示符处执行以下操作:
go tool yacc -o echo.go -p Input echo.y
go run echo.go
如您所见,您必须在 Lex
方法中定义自己的解析规则。结构 InputLex
旨在在解析输入时保存值。 InputSymType
是自动生成的,由规范 declaration
部分中声明的 %union
定义。
据我所知,没有办法直接使用 JISON 或正则表达式来使用 go 的 yacc
工具进行匹配。您可能需要看看其他一些库。
可以在此处找到更多详细信息:http://dinosaur.compilertools.net/yacc/
完整的工作代码在这里:https://play.golang.org/p/u1QxwRKLCl
所有yacc语法文件都应该有3个部分
- 声明
- 规则
- 程序
在声明中,您可能有%token, %type, %start
,表示标记列表,非终结符列表和语法中的开始符号。
规则的形式是A:Body {action codes}
程序需要实现函数 lexer 或 getToken
看例子https://github.com/acekingke/yaccgo/blob/main/examples/e.y
很容易理解,解析字符串“nnn...”即可
使用这个命令:
go tool yacc -p Verb -o verb.go boilerplate.y
正在尝试构建此 yacc 文件:
// boilerplate.y
%{
package main
import (
"bufio"
"fmt"
"os"
"unicode"
)
%}
%%
.|\n ECHO;
%%
func main() {
fi := bufio.NewReader(os.NewFile(0, "stdin"))
s, err := fi.ReadString('\n')
if err != nil {
fmt.Println('error', err)
}
VerbParse(&VerbLex{s: s})
}
错误:bad syntax on first rule: boilerplate.y:16
成功让这个例子工作:
https://github.com/golang-samples/yacc/blob/master/simple/calc.y
尝试构建我自己的并完成 lex & yacc 书。资源似乎仅限于不存在。
您的规格 rule
不正确。
规范文件具有以下声明:
declarations
%%
rules
%%
programs
其中 rule
定义为:
A : BODY ;
其中A是一个非终结符,而BODY是由tokens(终结符)、非终结符和文字。 :
和 ;
是规则声明语法的必需组件。
因此规则:
.|\n ECHO;
语法不正确。
因为您只是想回显输入,所以下面是一个基于 calc.y
的非常简单的实现(文件 echo.y):
规则
%%
in : /* empty */
| in input '\n'
{ fmt.Printf("Read character: %s\n", ) }
;
input : CHARACTER
| input CHARACTER
{ $$ = + }
;
程序
%%
type InputLex struct {
// contains one complete input string (with the trailing \n)
s string
// used to keep track of parser position along the above imput string
pos int
}
func (l *InputLex) Lex(lval *InputSymType) int {
var c rune = ' '
// skip through all the spaces, both at the ends and in between
for c == ' ' {
if l.pos == len(l.s) {
return 0
}
c = rune(l.s[l.pos])
l.pos += 1
}
// only look for input characters that are either digits or lower case
// to do more specific parsing, you'll define more tokens and have a
// more complex parsing logic here, choosing which token to return
// based on parsed input
if unicode.IsDigit(c) || unicode.IsLower(c) {
lval.val = string(c)
return CHARACTER
}
// do not return any token in case of unrecognized grammer
// this results in syntax error
return int(c)
}
func (l *InputLex) Error(s string) {
fmt.Printf("syntax error: %s\n", s)
}
func main() {
// same as in calc.y
}
func readline(fi *bufio.Reader) (string, bool) {
// same as in calc.y
}
要编译和 运行 这个程序,请在命令提示符处执行以下操作:
go tool yacc -o echo.go -p Input echo.y
go run echo.go
如您所见,您必须在 Lex
方法中定义自己的解析规则。结构 InputLex
旨在在解析输入时保存值。 InputSymType
是自动生成的,由规范 declaration
部分中声明的 %union
定义。
据我所知,没有办法直接使用 JISON 或正则表达式来使用 go 的 yacc
工具进行匹配。您可能需要看看其他一些库。
可以在此处找到更多详细信息:http://dinosaur.compilertools.net/yacc/
完整的工作代码在这里:https://play.golang.org/p/u1QxwRKLCl
所有yacc语法文件都应该有3个部分
- 声明
- 规则
- 程序
在声明中,您可能有%token, %type, %start
,表示标记列表,非终结符列表和语法中的开始符号。
规则的形式是A:Body {action codes}
程序需要实现函数 lexer 或 getToken
看例子https://github.com/acekingke/yaccgo/blob/main/examples/e.y
很容易理解,解析字符串“nnn...”即可