https://github.com/yuanbohan/yacc-example
simple examples to illustrate how to use goyacc
https://github.com/yuanbohan/yacc-example
bnf goyacc yacc
Last synced: 5 months ago
JSON representation
simple examples to illustrate how to use goyacc
- Host: GitHub
- URL: https://github.com/yuanbohan/yacc-example
- Owner: yuanbohan
- License: apache-2.0
- Created: 2022-12-03T08:11:40.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-12-28T07:05:56.000Z (over 3 years ago)
- Last Synced: 2025-02-01T10:24:18.538Z (over 1 year ago)
- Topics: bnf, goyacc, yacc
- Language: Yacc
- Homepage:
- Size: 12.7 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
goyacc examples
------
help you to understand how to use goyacc to write your own parser.
- [if/then/else](./if)
- [calculator](./calculator)
- [json](./json)
## Install
```shell
go install golang.org/x/tools/cmd/goyacc@latest
```
## Usage
```shell
goyacc -h
Usage of goyacc:
-l disable line directives
-o string
parser output (default "y.go")
-p string
name prefix to use in generated code (default "yy")
-v string
create parsing tables (default "y.output")
```
## Steps
- write your lexer
```go
// The parser uses the type Lex as a lexer. It must provide
// the methods Lex(*SymType) int and Error(string).
type Lex struct {
line []byte
peek rune
}
// The parser calls this method to get each new token. This
// implementation returns operators and NUM.
func (x *yyLex) Lex(yylval *yySymType) int {
...
}
// The parser calls this method on a parse error.
func (x *yyLex) Error(s string) {
....
}
```
- write your parser (*.y file)
- generate parser (*.go file) by goyacc
## parser Grammer (*.y file)
use Backus Naur Form (BNF)
- `%token`
- `%type`
the name in %type MUST be defined in %union, and %type connects the type defined in %union with symbols
- `%union`
- `func (x *yyLex) Lex(yylval *yySymType) int {}`
- return. the type of the token. integer.
- real value. stored in yylval
- rule
`$$`: symbol on the left side of colon
`$1` `$2` ...: symbol on the right side of colon
`{ ... }` : action invoked
```
...
expr:
NUM
| expr '+' NUM {
$$ = $1 + $3
}
...
$$ : expr (outer)
$1 : expr (inner)
$3 : NUM
```
- final call
```
func yyParse(yylex yyLexer) int {
return yyNewParser().Parse(yylex)
}
```
yylex is your lex struct which implemented the yyLexer interface
## parser Example
```
%union{
num int // union will be a yySymType struct, and all fields in union will be copied into struct
}
%type top expr // indicate parser to use num field (which is (yylval *yySymType) in goyacc)
%token '+' '-' '*' '/' // will not use yylval. Only indicate parser to use the token as ASCII code
%token NUM // indicate parser to use yylval.num
%%
top:
expr {
fmt.Println($$)
}
expr:
NUM
| expr '+' NUM {
$$ = $1 + $3
}
| expr '-' NUM {
$$ = $1 - $3
}
| expr '*' NUM {
$$ = $1 * $3
}
| expr '/' NUM {
$$ = $1 / $3
}
%%
```
## Resources
* https://zh.wikipedia.org/wiki/LALR%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90%E5%99%A8
* https://cloud.tencent.com/developer/article/1744609
* https://mp.weixin.qq.com/s/qSbftFcRfigqEl_2-bfw3A
* https://about.sourcegraph.com/blog/go/gophercon-2018-how-to-write-a-parser-in-go
* https://silcnitc.github.io/yacc.html
* https://github.com/sougou/parser_tutorial
* https://github.com/u2takey/learn-yacc
* https://github.com/golang/tools/tree/master/cmd/goyacc/testdata/expr