github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/parser/parser.go.y (about) 1 %{ 2 package parser 3 4 import "github.com/coyove/nj/typ" 5 6 func ss(yylex yyLexer) *Lexer { return yylex.(*Lexer) } 7 %} 8 %type<expr> prog 9 %type<expr> stats 10 %type<expr> declarator 11 %type<expr> declarator_list 12 %type<expr> ident_list 13 %type<expr> expr 14 %type<expr> expr_declarator 15 %type<expr> expr_list 16 %type<expr> expr_assign_list 17 %type<expr> prefix_expr 18 %type<expr> assign_stat 19 %type<expr> for_stat 20 %type<expr> if_stat 21 %type<expr> elseif_stat 22 %type<expr> jmp_stat 23 %type<expr> func_stat 24 %type<expr> func_params 25 %type<token> comma 26 27 %union { 28 token Token 29 expr Node 30 } 31 32 /* Reserved words */ 33 %token<token> TDo TLocal TElseIf TThen TEnd TBreak TContinue TElse TFor TWhile TFunc TIf TReturn TReturnVoid TRepeat TUntil TNot TLabel TGoto TIn TLsh TRsh TURsh TDotDotDot TLParen TLBracket TIs 34 35 /* Literals */ 36 %token<token> TOr TAnd TEqeq TNeq TLte TGte TIdent TNumber TString TIDiv TInv 37 %token<token> TAddEq TSubEq TMulEq TDivEq TIDivEq TModEq TBitAndEq TBitOrEq TBitXorEq TBitLshEq TBitRshEq TBitURshEq 38 %token<token> '{' '[' '(' '=' '>' '<' '+' '-' '*' '/' '%' '^' '#' '.' '&' '|' '~' ':' ')' ',' 39 40 /* Operators */ 41 %right 'T' 42 %right TElse 43 %left ASSIGN 44 %right FUNC 45 %left TOr 46 %left TAnd 47 %left '>' '<' TGte TLte TEqeq TNeq 48 %left '+' '-' '|' '^' 49 %left '*' '/' '%' TIDiv TLsh TRsh TURsh '&' 50 %left TIs 51 %right UNARY /* not # -(unary) */ 52 53 %% 54 55 prog: stats { ss(yylex).Stmts = $1 } 56 57 stats: 58 { $$ = &Prog{} } | 59 stats func_stat { $$ = $1.(*Prog).Append($2) } | 60 stats TDo stats TEnd { $3.(*Prog).DoBlock = true; $$ = $1.(*Prog).Append($3) } | 61 stats jmp_stat { $$ = $1.(*Prog).Append($2) } | 62 stats assign_stat { $$ = $1.(*Prog).Append($2) } | 63 stats for_stat { $$ = $1.(*Prog).Append($2) } | 64 stats if_stat { $$ = $1.(*Prog).Append($2) } | 65 stats ';' { $$ = $1 } 66 67 assign_stat: 68 expr { $$ = $1 } | 69 TLocal ident_list { $$ = ss(yylex).pDeclareAssign([]Node($2.(IdentList)), nil, false, $1) } | 70 TLocal ident_list '=' expr_list { $$ = ss(yylex).pDeclareAssign([]Node($2.(IdentList)), $4.(ExprList), false, $1) } | 71 declarator_list '=' expr_list { $$ = ss(yylex).pDeclareAssign([]Node($1.(DeclList)), $3.(ExprList), true, $2) } | 72 declarator TAddEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpAdd, $1, $3, $2), $2) } | 73 declarator TSubEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpSub, $1, $3, $2), $2) } | 74 declarator TMulEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpMul, $1, $3, $2), $2) } | 75 declarator TDivEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpDiv, $1, $3, $2), $2) } | 76 declarator TIDivEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpIDiv, $1, $3, $2), $2) } | 77 declarator TModEq expr { $$ = assignLoadStore($1, ss(yylex).pBinary(typ.OpMod, $1, $3, $2), $2) } | 78 declarator TBitAndEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitAnd, $1, $3, $2), $2) } | 79 declarator TBitOrEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitOr, $1, $3, $2), $2) } | 80 declarator TBitXorEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitXor, $1, $3, $2), $2) } | 81 declarator TBitLshEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitLsh, $1, $3, $2), $2) } | 82 declarator TBitRshEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitRsh, $1, $3, $2), $2) } | 83 declarator TBitURshEq expr { $$ = assignLoadStore($1, ss(yylex).pBitwise(typ.OpExtBitURsh, $1, $3, $2), $2) } 84 85 for_stat: 86 TWhile expr TDo stats TEnd { $$ = ss(yylex).pLoop(&If{$2, $4, emptyBreak}) } | 87 TRepeat stats TUntil expr { $$ = ss(yylex).pLoop($2, &If{$4, emptyBreak, emptyProg}) } | 88 TFor TIdent '=' expr ',' expr TDo stats TEnd { $$ = ss(yylex).pForRange($2, $4, $6, one, $8, $1) } | 89 TFor TIdent '=' expr ',' expr ',' expr TDo stats TEnd { $$ = ss(yylex).pForRange($2, $4, $6, $8, $10, $1) } | 90 TFor TIdent ',' TIdent TIn expr TDo stats TEnd { $$ = ss(yylex).pForIn($2, $4, $6, $8, $1) } | 91 TFor TIdent TIn expr TDo stats TEnd { $$ = ss(yylex).pForIn($2, $1, $4, $6, $1) } 92 93 if_stat: 94 TIf expr TThen stats elseif_stat TEnd %prec 'T' { $$ = &If{$2, $4, $5} } | 95 TIf TLabel TIdent TLabel TThen stats TEnd %prec 'T' { 96 $$ = &If{ss(yylex).Int(0), ss(yylex).pProg(false, &GotoLabel{$3.Str, false, $1.Line()}, $6), emptyProg} 97 } 98 99 elseif_stat: 100 { $$ = nil } | 101 TElse stats { $$ = $2 } | 102 TElseIf expr TThen stats elseif_stat { $$ = &If{$2, $4, $5} } 103 104 func_stat: 105 TFunc TIdent func_params stats TEnd { 106 $$ = ss(yylex).pFunc(false, $2, $3, $4, $1) 107 } | 108 TFunc TIdent '.' TIdent func_params stats TEnd { 109 m := ss(yylex).pFunc(true, __markupFuncName($2, $4), $5, $6, $1) 110 $$ = &Tenary{typ.OpStore, Sym($2), ss(yylex).Str($4.Str), m, $1.Line()} 111 } 112 113 func_params: 114 TLParen ')' { $$ = (IdentList)(nil) } | 115 TLParen ident_list ')' { $$ = $2 } | 116 TLParen ident_list TDotDotDot ')' { $$ = IdentVarargList{$2.(IdentList)} } | 117 TLParen TDotDotDot ident_list ')' { $$ = IdentVarargExpandList{nil, $3.(IdentList)} } | 118 TLParen ident_list TDotDotDot ident_list ')' { $$ = IdentVarargExpandList{$2.(IdentList), $4.(IdentList)} } | 119 '(' ')' { $$ = (IdentList)(nil) } | 120 '(' ident_list ')' { $$ = $2 } | 121 '(' ident_list TDotDotDot ')' { $$ = IdentVarargList{$2.(IdentList)} } | 122 '(' TDotDotDot ident_list ')' { $$ = IdentVarargExpandList{nil, $3.(IdentList)} } | 123 '(' ident_list TDotDotDot ident_list ')' { $$ = IdentVarargExpandList{$2.(IdentList), $4.(IdentList)} } 124 125 jmp_stat: 126 TBreak { $$ = &BreakContinue{true, $1.Line()} } | 127 TContinue { $$ = &BreakContinue{false, $1.Line()} } | 128 TGoto TIdent { $$ = &GotoLabel{$2.Str, true, $1.Line()} } | 129 TLabel TIdent TLabel { $$ = &GotoLabel{$2.Str, false, $1.Line()} } | 130 TReturnVoid { $$ = &Unary{typ.OpRet, SNil, $1.Line()} } | 131 TReturn expr_list { 132 if el := $2.(ExprList); len(el) == 1 { 133 ss(yylex).pFindTailCall(el[0]) 134 $$ = &Unary{typ.OpRet, el[0], $1.Line()} 135 } else { 136 $$ = &Unary{typ.OpRet, $2, $1.Line()} 137 } 138 } 139 140 declarator: 141 TIdent { 142 $$ = Sym($1) 143 } | 144 prefix_expr TLBracket expr ']' { 145 $$ = &Tenary{typ.OpLoad, $1, $3, Address(typ.RegA), $2.Line()} 146 } | 147 prefix_expr '.' TIdent { 148 $$ = &Tenary{typ.OpLoad, $1, ss(yylex).Str($3.Str), Address(typ.RegA), $2.Line()} 149 } 150 151 expr_declarator: 152 expr { $$ = $1 } | 153 TGoto TIdent { $$ = ss(yylex).Str($2.Str) } | 154 TLocal TIdent '=' expr { $$ = ss(yylex).pDeclareAssign([]Node{Sym($2)}, ExprList{$4}, false, $1) } | 155 TLocal TIdent TLBracket TNumber']'{ $$ = &Declare{Sym($2), ss(yylex).pArrayN($4.Str), $1.Line()} } 156 157 expr: 158 prefix_expr { $$ = $1 } | 159 TNumber { $$ = ss(yylex).Num($1.Str) } | 160 expr TOr expr { $$ = &Or{$1, $3} } | 161 expr TAnd expr { $$ = &And{$1, $3} } | 162 expr '>' expr { $$ = ss(yylex).pBinary(typ.OpLess, $3, $1, $2) } | 163 expr '<' expr { $$ = ss(yylex).pBinary(typ.OpLess, $1, $3, $2) } | 164 expr TGte expr { $$ = ss(yylex).pBinary(typ.OpLessEq, $3, $1, $2) } | 165 expr TLte expr { $$ = ss(yylex).pBinary(typ.OpLessEq, $1, $3, $2) } | 166 expr TEqeq expr { $$ = ss(yylex).pBinary(typ.OpEq, $1, $3, $2) } | 167 expr TNeq expr { $$ = ss(yylex).pBinary(typ.OpNeq, $1, $3, $2) } | 168 expr '+' expr { $$ = ss(yylex).pBinary(typ.OpAdd, $1, $3, $2) } | 169 expr '-' expr { $$ = ss(yylex).pBinary(typ.OpSub, $1, $3, $2) } | 170 expr '*' expr { $$ = ss(yylex).pBinary(typ.OpMul, $1, $3, $2) } | 171 expr '/' expr { $$ = ss(yylex).pBinary(typ.OpDiv, $1, $3, $2) } | 172 expr TIDiv expr { $$ = ss(yylex).pBinary(typ.OpIDiv, $1, $3, $2) } | 173 expr '%' expr { $$ = ss(yylex).pBinary(typ.OpMod, $1, $3, $2) } | 174 expr '&' expr { $$ = ss(yylex).pBitwise(typ.OpExtBitAnd, $1, $3 ,$2) } | 175 expr '|' expr { $$ = ss(yylex).pBitwise(typ.OpExtBitOr, $1, $3, $2) } | 176 expr '^' expr { $$ = ss(yylex).pBitwise(typ.OpExtBitXor, $1, $3, $2) } | 177 expr TLsh expr { $$ = ss(yylex).pBitwise(typ.OpExtBitLsh, $1, $3, $2) } | 178 expr TRsh expr { $$ = ss(yylex).pBitwise(typ.OpExtBitRsh, $1, $3, $2) } | 179 expr TURsh expr { $$ = ss(yylex).pBitwise(typ.OpExtBitURsh, $1, $3, $2) } | 180 expr TIs prefix_expr { $$ = ss(yylex).pBinary(typ.OpIsProto, $1, $3, $2) } | 181 expr TIs TNot prefix_expr { $$ = pUnary(typ.OpNot, ss(yylex).pBinary(typ.OpIsProto, $1, $4, $2), $2) } | 182 '~' expr %prec UNARY { $$ = ss(yylex).pBitwise(typ.OpExtBitXor, ss(yylex).Int(-1), $2, $1) } | 183 '#' expr %prec UNARY { $$ = pUnary(typ.OpLen, $2, $1) } | 184 TInv expr %prec UNARY { $$ = ss(yylex).pBinary(typ.OpSub, zero, $2, $1) } | 185 TNot expr %prec UNARY { $$ = pUnary(typ.OpNot, $2, $1) } 186 187 prefix_expr: 188 declarator { $$ = $1 } | 189 TIf TLParen expr ',' expr ',' expr ')' { $$ = &If{$3, &Assign{Sa, $5, $1.Line()}, &Assign{Sa, $7, $1.Line()}} } | 190 TFunc func_params stats TEnd { $$ = ss(yylex).pFunc(false, __markupLambdaName($1), $2, $3, $1) } | 191 TString { $$ = ss(yylex).Str($1.Str) } | 192 '(' expr ')' { $$ = $2 } | 193 '[' ']' { $$ = ss(yylex).pEmptyArray() } | 194 '{' '}' { $$ = ss(yylex).pEmptyObject() } | 195 '[' expr_list comma ']' { $$ = $2 } | 196 '{' expr_assign_list comma'}' { $$ = $2 } | 197 prefix_expr TLBracket expr ':' expr ']' { $$ = &Tenary{typ.OpSlice, $1, $3, $5, $2.Line()} } | 198 prefix_expr TLBracket ':' expr ']' { $$ = &Tenary{typ.OpSlice, $1, zero, $4, $2.Line()} } | 199 prefix_expr TLBracket expr ':' ']' { $$ = &Tenary{typ.OpSlice, $1, $3, ss(yylex).Int(-1), $2.Line()} } | 200 prefix_expr TLParen ')' { $$ = &Call{typ.OpCall, $1, ExprList(nil), false, $2.Line() } } | 201 prefix_expr TLParen expr_list comma ')' { $$ = &Call{typ.OpCall, $1, $3.(ExprList), false, $2.Line() } } | 202 prefix_expr TLParen expr_list TDotDotDot comma ')' { $$ = &Call{typ.OpCall, $1, $3.(ExprList), true, $2.Line() } } 203 204 declarator_list: 205 declarator { $$ = DeclList{$1} } | 206 declarator_list ',' declarator { $$ = append($1.(DeclList), $3) } 207 208 ident_list: 209 TIdent { $$ = IdentList{Sym($1)} } | 210 ident_list ',' TIdent { $$ = append($1.(IdentList), Sym($3)) } 211 212 expr_list: 213 expr_declarator { $$ = ss(yylex).pArray(nil, $1) } | 214 expr_list ',' expr_declarator { $$ = ss(yylex).pArray($1, $3) } 215 216 expr_assign_list: 217 TIdent '=' expr_declarator { $$ = ss(yylex).pObject(nil, ss(yylex).Str($1.Str), $3) } | 218 expr ':' expr_declarator { $$ = ss(yylex).pObject(nil, $1, $3) } | 219 expr_assign_list ',' TIdent '=' expr_declarator { $$ = ss(yylex).pObject($1, ss(yylex).Str($3.Str), $5) } | 220 expr_assign_list ',' expr ':' expr_declarator { $$ = ss(yylex).pObject($1, $3, $5) } 221 222 comma: {} | ',' {} 223 224 %%