%{ package parser import ( "github.com/mattn/kinako/ast" ) %} %type compstmt %type stmts %type stmt %type expr %type exprs %union{ compstmt []ast.Stmt stmts []ast.Stmt stmt ast.Stmt expr ast.Expr exprs []ast.Expr tok ast.Token term ast.Token terms ast.Token opt_terms ast.Token } %token IDENT NUMBER STRING EQEQ NEQ GE LE OROR ANDAND POW %right '=' %right '?' ':' %left OROR %left ANDAND %left IDENT %nonassoc EQEQ NEQ ',' %left '>' GE '<' LE SHIFTLEFT SHIFTRIGHT %left '+' '-' PLUSPLUS MINUSMINUS %left '*' '/' '%' %right UNARY %% compstmt : opt_terms { $$ = nil } | stmts opt_terms { $$ = $1 } stmts : opt_terms stmt { $$ = []ast.Stmt{$2} if l, ok := yylex.(*Lexer); ok { l.stmts = $$ } } | stmts terms stmt { if $3 != nil { $$ = append($1, $3) if l, ok := yylex.(*Lexer); ok { l.stmts = $$ } } } stmt : expr '=' expr { $$ = &ast.LetStmt{Lhs: $1, Operator: "=", Rhs: $3} } | expr { $$ = &ast.ExprStmt{Expr: $1} } expr : IDENT { $$ = &ast.IdentExpr{Lit: $1.Lit} } | NUMBER { $$ = &ast.NumberExpr{Lit: $1.Lit} } | '-' expr %prec UNARY { $$ = &ast.UnaryExpr{Operator: "-", Expr: $2} } | '!' expr %prec UNARY { $$ = &ast.UnaryExpr{Operator: "!", Expr: $2} } | '^' expr %prec UNARY { $$ = &ast.UnaryExpr{Operator: "^", Expr: $2} } | STRING { $$ = &ast.StringExpr{Lit: $1.Lit} } | expr '?' expr ':' expr { $$ = &ast.TernaryOpExpr{Expr: $1, Lhs: $3, Rhs: $5} } | '(' expr ')' { $$ = &ast.ParenExpr{SubExpr: $2} } | expr '+' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "+", Rhs: $3} } | expr '-' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "-", Rhs: $3} } | expr '*' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "*", Rhs: $3} } | expr '/' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "/", Rhs: $3} } | expr '%' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "%", Rhs: $3} } | expr EQEQ expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "==", Rhs: $3} } | expr NEQ expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "!=", Rhs: $3} } | expr '>' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">", Rhs: $3} } | expr GE expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} } | expr '<' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<", Rhs: $3} } | expr LE expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} } | expr '|' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "|", Rhs: $3} } | expr OROR expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "||", Rhs: $3} } | expr '&' expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&", Rhs: $3} } | expr ANDAND expr { $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&&", Rhs: $3} } | IDENT '(' exprs ')' { $$ = &ast.CallExpr{Name: $1.Lit, SubExprs: $3} } exprs : { $$ = nil } | expr { $$ = []ast.Expr{$1} } | exprs ',' expr { $$ = append($1, $3) } opt_terms : /* none */ | terms ; terms : term { } | terms term { } ; term : ';' { } | '\n' { } ; %%