Skip to content

Instantly share code, notes, and snippets.

@uiur
Created Apr 8, 2016
Embed
What would you like to do?
go/scanner + goyacc sample
%{
package main
import (
"fmt"
"go/scanner"
"os"
"go/token"
)
type Expression interface{}
type Token struct {
token int
literal string
}
type NumExpr struct {
literal string
}
type BinOpExpr struct {
left Expression
operator rune
right Expression
}
%}
%union {
token Token
expr Expression
}
%type<expr> program
%type<expr> expr
%token<token> NUMBER
%left '+'
%left '*'
%%
program
: expr
{
$$ = $1
yylex.(*Lexer).result = $$
}
expr
: NUMBER
{
$$ = NumExpr{ literal: $1.literal }
}
| expr '+' expr
{
$$ = BinOpExpr{ left: $1, operator: '+', right: $3 }
}
| expr '*' expr
{
$$ = BinOpExpr{ left: $1, operator: '*', right: $3 }
}
%%
type Lexer struct {
scanner.Scanner
result Expression
}
func (l *Lexer) Lex(lval *yySymType) int {
_, tok, lit := l.Scan()
token_number := int(tok)
switch tok {
case token.INT:
token_number = NUMBER
case token.ADD, token.MUL:
token_number = int(tok.String()[0])
default:
return 0
}
lval.token = Token{ token: token_number, literal: lit }
return token_number
}
func (l *Lexer) Error(e string) {
panic(e)
}
func main() {
src := []byte(os.Args[1])
fset := token.NewFileSet()
file := fset.AddFile("", fset.Base(), len(src))
l := new(Lexer)
l.Init(file, src, nil, scanner.ScanComments)
yyParse(l)
fmt.Printf("%#v\n", l.result)
}
@uiur

This comment has been minimized.

Copy link
Owner Author

@uiur uiur commented Apr 8, 2016

go tool yacc -o parser.go parser.go.y; go run parser.go "1+2*3"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment