z_mirror/luapls
git clone https://git.raiguard.me/z_mirror/luapls
37b5dce
main
1package parser 2 3import ( 4"github.com/raiguard/luapls/lua/ast" 5"github.com/raiguard/luapls/lua/token" 6"github.com/raiguard/luapls/util" 7) 8 9func (p * Parser )parseStatement () ast.Statement { 10switch p .unit ().Type () { 11case token .BREAK : 12return p .parseBreakStatement () 13case token .DO : 14return p .parseDoStatement () 15case token .FOR : 16return p .parseForStatement () 17case token .FUNCTION : 18return p .parseFunctionStatement (nil ) 19case token .GOTO : 20return p .parseGotoStatement () 21case token .IF : 22return p .parseIfStatement () 23case token .LABEL : 24return p .parseLabelStatement () 25case token .LOCAL : 26tok := p .expect (token .LOCAL ) 27switch p .unit ().Type () { 28case token .FUNCTION : 29return p .parseFunctionStatement (& tok ) 30case token .IDENT : 31return p .parseLocalStatement (tok ) 32 } 33stat := & ast.Invalid {Position :tok .Pos ()} 34p .addErrorForNode (stat ,"Invalid statement" ) 35return stat 36case token .REPEAT : 37return p .parseRepeatStatement () 38case token .RETURN : 39return p .parseReturnStatement () 40case token .SEMICOLON : 41return p .parseSemicolonStatement () 42case token .WHILE : 43return p .parseWhileStatement () 44 } 45 46exps := p .parseExpressionList () 47if p .tokIs (token .ASSIGN ) { 48return p .parseAssignmentStatement (exps ) 49// TODO: Can there ever be zero expressions? 50 }else if fc ,ok := exps .Pairs [0 ].Node .(* ast.FunctionCall );ok { 51return fc 52 }else { 53stat := & ast.Invalid {Position :exps .Pos ()} 54p .addErrorForNode (stat ,"Invalid statement" ) 55return stat 56 } 57} 58 59func (p * Parser )parseAssignmentStatement (vars ast.Punctuated [ast.Expression ])* ast.AssignmentStatement { 60assign := p .expect (token .ASSIGN ) 61exps := p .parseExpressionList () 62 63return & ast.AssignmentStatement { 64Vars :vars , 65Assign :assign , 66Exps :exps , 67 } 68} 69 70func (p * Parser )parseBreakStatement ()* ast.BreakStatement { 71node := util .Ptr (ast .BreakStatement (* p .unit ())) 72p .expect (token .BREAK ) 73return node 74} 75 76func (p * Parser )parseDoStatement ()* ast.DoStatement { 77do := p .expect (token .DO ) 78block := p .parseBlock () 79end := p .expect (token .END ) 80return & ast.DoStatement { 81DoTok :do , 82Body :block , 83EndTok :end , 84 } 85} 86 87func (p * Parser )parseForStatement () ast.Statement { 88forTok := p .expect (token .FOR ) 89names := p .parseNameList () 90 91var sepTok ast.Unit 92 93bareLoop := len (names .Pairs )== 1 && p .tokIs (token .ASSIGN ) 94if bareLoop { 95sepTok = p .expect (token .ASSIGN ) 96 }else { 97sepTok = p .expect (token .IN ) 98 } 99 100exps := p .parseExpressionList () 101doTok := p .expect (token .DO ) 102body := p .parseBlock () 103endTok := p .expect (token .END ) 104 105if bareLoop { 106var start ,finish ast.Pair [ast.Expression ] 107if len (exps .Pairs )< 2 || len (exps .Pairs )> 3 { 108p .addError ("Expected 2 to 3 expressions" ) 109 } 110start = exps .Pairs [0 ] 111finish = exps .Pairs [1 ] 112var step * ast.Pair [ast.Expression ] 113if len (exps .Pairs )> 2 { 114step = & exps .Pairs [2 ] 115 } 116return & ast.ForStatement { 117ForTok :forTok , 118Name :names .Pairs [0 ].Node , 119AssignTok :sepTok , 120Start :start , 121Finish :finish , 122Step :step , 123DoTok :doTok , 124Body :body , 125EndTok :endTok , 126 } 127 } 128 129return & ast.ForInStatement { 130ForTok :forTok , 131Names :names , 132InTok :sepTok , 133Exps :exps , 134DoTok :doTok , 135Body :body , 136EndTok :endTok , 137 } 138} 139 140func (p * Parser )parseFunctionStatement (localTok * ast.Unit )* ast.FunctionStatement { 141funcTok := p .expect (token .FUNCTION ) 142name := p .parseExpression (LOWEST ,false ) 143lparen := p .expect (token .LPAREN ) 144params ,vararg := p .parseParameterList () 145rparen := p .expect (token .RPAREN ) 146body := p .parseBlock () 147endTok := p .expect (token .END ) 148 149return & ast.FunctionStatement { 150LocalTok :localTok , 151FuncTok :funcTok , 152Name :name , 153LeftParen :lparen , 154Params :params , 155Vararg :vararg , 156RightParen :rparen , 157Body :body , 158EndTok :endTok , 159 } 160} 161 162func (p * Parser )parseGotoStatement ()* ast.GotoStatement { 163gotoTok := p .expect (token .GOTO ) 164name := p .parseIdentifier () 165return & ast.GotoStatement { 166GotoTok :gotoTok , 167Name :name , 168 } 169} 170 171func (p * Parser )parseIfStatement ()* ast.IfStatement { 172ifTok := p .expect (token .IF ) 173 174clauses := []* ast.IfClause {p .parseIfClause (ifTok )} 175 176for p .tokIs (token .ELSEIF ) { 177elseifTok := p .expect (token .ELSEIF ) 178clauses = append (clauses ,p .parseIfClause (elseifTok )) 179 } 180 181if p .tokIs (token .ELSE ) { 182elseTok := p .expect (token .ELSE ) 183body := p .parseBlock () 184clauses = append (clauses ,& ast.IfClause { 185LeadingTok :elseTok , 186Condition :nil , 187ThenTok :nil , 188Body :body , 189 }) 190 } 191 192endTok := p .expect (token .END ) 193 194return & ast.IfStatement { 195IfTok :ifTok , 196Clauses :clauses , 197EndTok :endTok , 198 } 199} 200 201func (p * Parser )parseIfClause (leadingTok ast.Unit )* ast.IfClause { 202condition := p .parseExpression (LOWEST ,true ) 203thenTok := p .expect (token .THEN ) 204block := p .parseBlock () 205return & ast.IfClause { 206LeadingTok :leadingTok , 207Condition :condition , 208ThenTok :& thenTok , 209Body :block , 210 } 211} 212 213func (p * Parser )parseLabelStatement ()* ast.LabelStatement { 214leadingLabelTok := p .expect (token .LABEL ) 215name := p .parseIdentifier () 216trailingLabelTok := p .expect (token .LABEL ) 217return & ast.LabelStatement { 218LeadingLabelTok :leadingLabelTok , 219Name :name , 220TrailingLabelTok :trailingLabelTok , 221 } 222} 223 224func (p * Parser )parseLocalStatement (localTok ast.Unit )* ast.LocalStatement { 225ls := & ast.LocalStatement { 226LocalTok :localTok , 227Names :p .parseNameList (), 228 } 229if assignTok := p .accept (token .ASSIGN );assignTok != nil { 230ls .AssignTok = assignTok 231ls .Exps = util .Ptr (p .parseExpressionList ()) 232 } 233return ls 234} 235 236func (p * Parser )parseRepeatStatement ()* ast.RepeatStatement { 237repeatTok := p .expect (token .REPEAT ) 238body := p .parseBlock () 239untilTok := p .expect (token .UNTIL ) 240condition := p .parseExpression (LOWEST ,true ) 241return & ast.RepeatStatement { 242RepeatTok :repeatTok , 243Body :body , 244UntilTok :untilTok , 245Condition :condition , 246 } 247} 248 249func (p * Parser )parseReturnStatement ()* ast.ReturnStatement { 250returnTok := p .expect (token .RETURN ) 251rs := & ast.ReturnStatement {ReturnTok :returnTok } 252if ! blockEnd [p .unit ().Type ()] { 253rs .Exps = util .Ptr (p .parseExpressionList ()) 254 } 255return rs 256} 257 258func (p * Parser )parseSemicolonStatement ()* ast.SemicolonStatement { 259return util .Ptr (ast .SemicolonStatement (p .expect (token .SEMICOLON ))) 260} 261 262func (p * Parser )parseWhileStatement ()* ast.WhileStatement { 263whileTok := p .expect (token .WHILE ) 264condition := p .parseExpression (LOWEST ,true ) 265doTok := p .expect (token .DO ) 266body := p .parseBlock () 267endTok := p .expect (token .END ) 268return & ast.WhileStatement { 269WhileTok :whileTok , 270Condition :condition , 271DoTok :doTok , 272Body :body , 273EndTok :endTok , 274 } 275}