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  %%