z_mirror/luapls
git clone https://git.raiguard.me/z_mirror/luapls
dfb9640
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 )parseExpression (precedence operatorPrecedence ,allowCall bool ) ast.Expression { 10var left ast.Expression 11switch p .unit ().Type () { 12case token .FUNCTION : 13left = p .parseFunctionExpression () 14case token .IDENT : 15left = p .parseIdentifier () 16case token .LBRACE : 17left = p .parseTableLiteral () 18case token .LEN ,token .MINUS ,token .NOT : 19left = p .parsePrefixExpression () 20case token .LPAREN : 21left = p .parseSurroundingExpression () 22case token .NIL : 23left = p .parseNilLiteral () 24case token .NUMBER : 25left = p .parseNumberLiteral () 26case token .STRING : 27left = p .parseStringLiteral () 28case token .RAWSTRING : 29left = p .parseRawStringLiteral () 30case token .TRUE ,token .FALSE : 31left = p .parseBooleanLiteral () 32case token .VARARG : 33left = p .parseVararg () 34default : 35invalid := ast.Invalid {Position :p .unit ().Pos ()} 36p .addError ("Expected expression" ) 37p .next () 38return & invalid 39 } 40 41for isSuffixOperator (p .unit ().Type ()) { 42switch p .unit ().Type () { 43case token .LPAREN ,token .LBRACE ,token .STRING : 44if ! allowCall { 45return left 46 } 47left = p .parseFunctionCall (left ) 48case token .LBRACK ,token .DOT ,token .COLON : 49left = p .parseIndexExpression (left ) 50 } 51 } 52 53for isInfixOperator (p .unit ().Type ()) { 54tokPrecedence := p .tokPrecedence () 55if isRightAssociative (p .unit ().Type ()) { 56tokPrecedence ++ 57 } 58if precedence >= tokPrecedence { 59break 60 } 61left = p .parseInfixExpression (left ) 62 } 63 64return left 65} 66 67func (p * Parser )parseExpressionList () ast.Punctuated [ast.Expression ] { 68exps := ast.Punctuated [ast.Expression ]{StartPos :p .unit ().Pos ()} 69 70for { 71pair := ast.Pair [ast.Expression ]{ 72Node :p .parseExpression (LOWEST ,true ), 73 } 74if p .tokIs (token .COMMA ) { 75pair .Delimeter = p .unit () 76p .next () 77 } 78exps .Pairs = append (exps .Pairs ,pair ) 79if pair .Delimeter == nil { 80break 81 } 82 } 83 84return exps 85} 86 87// Identical to parseExpressionList, but only for identifiers 88func (p * Parser )parseNameList () ast.Punctuated [* ast.Identifier ] { 89list := ast.Punctuated [* ast.Identifier ]{StartPos :p .unit ().Pos ()} 90 91for { 92if ! p .tokIs (token .IDENT ) { 93break 94 } 95pair := ast.Pair [* ast.Identifier ]{Node :p .parseIdentifier ()} 96if p .tokIs (token .COMMA ) { 97pair .Delimeter = p .unit () 98p .next () 99 } 100list .Pairs = append (list .Pairs ,pair ) 101if pair .Delimeter == nil { 102break 103 } 104 } 105 106return list 107} 108 109// Parses a namelist, then an optional vararg 110func (p * Parser )parseParameterList () (ast.Punctuated [* ast.Identifier ],* ast.Unit ) { 111return p .parseNameList (),p .accept (token .VARARG ) 112} 113 114func (p * Parser )parseFunctionExpression ()* ast.FunctionExpression { 115function := p .expect (token .FUNCTION ) 116lparen := p .expect (token .LPAREN ) 117 118params ,vararg := p .parseParameterList () 119 120rparen := p .expect (token .RPAREN ) 121 122body := p .parseBlock () 123 124end := p .expect (token .END ) 125 126return & ast.FunctionExpression { 127FuncTok :function , 128LeftParen :lparen , 129Params :params , 130Vararg :vararg , 131RightParen :rparen , 132Body :body , 133EndUnit :end , 134 } 135} 136 137func (p * Parser )parseIndexExpression (prefix ast.Expression )* ast.IndexExpression { 138ie := & ast.IndexExpression { 139Prefix :prefix , 140LeftIndexer :* p .unit (), 141 } 142p .next () 143 144if ie .LeftIndexer .Type ()== token .LBRACK { 145ie .Inner = p .parseExpression (LOWEST ,true ) 146ie .RightIndexer = util .Ptr (p .expect (token .RBRACK )) 147 }else { 148ie .Inner = p .parseIdentifier () 149 } 150 151return ie 152} 153 154func (p * Parser )parseInfixExpression (left ast.Expression )* ast.InfixExpression { 155expression := & ast.InfixExpression { 156Left :left , 157Operator :* p .unit (), 158Right :nil , 159 } 160 161precedence := p .tokPrecedence () 162p .next () 163expression .Right = p .parseExpression (precedence ,true ) 164 165return expression 166} 167 168func (p * Parser )parseSurroundingExpression () ast.Expression { 169p .expect (token .LPAREN ) 170exp := p .parseExpression (LOWEST ,true ) 171p .expect (token .RPAREN ) 172return exp 173} 174 175func (p * Parser )parsePrefixExpression ()* ast.PrefixExpression { 176operator := * p .unit () 177p .next () 178right := p .parseExpression (PREFIX ,true ) 179return & ast.PrefixExpression {Operator :operator ,Right :right } 180} 181 182func (p * Parser )parseBooleanLiteral ()* ast.BooleanLiteral { 183bl := ast .BooleanLiteral (* p .unit ()) 184p .next () 185return & bl 186} 187 188func (p * Parser )parseIdentifier ()* ast.Identifier { 189return util .Ptr (ast .Identifier (p .expect (token .IDENT ))) 190} 191 192func (p * Parser )parseNilLiteral ()* ast.NilLiteral { 193return util .Ptr (ast .NilLiteral (p .expect (token .NIL ))) 194} 195 196func (p * Parser )parseNumberLiteral ()* ast.NumberLiteral { 197return util .Ptr (ast .NumberLiteral (p .expect (token .NUMBER ))) 198} 199 200func (p * Parser )parseStringLiteral ()* ast.StringLiteral { 201return util .Ptr (ast .StringLiteral (p .expect (token .STRING ))) 202} 203 204func (p * Parser )parseRawStringLiteral ()* ast.StringLiteral { 205return util .Ptr (ast .StringLiteral (p .expect (token .RAWSTRING ))) 206} 207 208func (p * Parser )parseTableLiteral ()* ast.TableLiteral { 209tl := & ast.TableLiteral {LeftBrace :p .expect (token .LBRACE )} 210 211if rbrace := p .accept (token .RBRACE );rbrace != nil { 212tl .RightBrace = * rbrace 213return tl 214 } 215 216tl .Fields = p .parseTableFieldList () 217tl .RightBrace = p .expect (token .RBRACE ) 218 219return tl 220} 221 222func isType [T any ](thing any )bool { 223_ ,ok := thing .(* T ) 224return ok 225} 226 227func (p * Parser )parseVararg ()* ast.Vararg { 228return util .Ptr (ast .Vararg (p .expect (token .VARARG ))) 229} 230 231var tableSep = map [token.TokenType ]bool { 232token .COMMA :true , 233token .SEMICOLON :true , 234} 235 236type prefixParseFn func () ast.Expression 237 238type operatorPrecedence int 239 240const ( 241LOWEST operatorPrecedence = iota 242OR 243AND 244CMP 245CONCAT 246SUM 247PRODUCT 248PREFIX 249POW 250) 251 252var precedences = map [token.TokenType ]operatorPrecedence { 253token .OR :OR , 254token .AND :AND , 255token .LT :CMP , 256token .GT :CMP , 257token .LEQ :CMP , 258token .GEQ :CMP , 259token .NEQ :CMP , 260token .EQUAL :CMP , 261token .CONCAT :CONCAT , 262token .PLUS :SUM , 263token .MINUS :SUM , 264token .MUL :PRODUCT , 265token .SLASH :PRODUCT , 266token .MOD :PRODUCT , 267token .NOT :PREFIX , 268token .LEN :PREFIX , 269token .POW :POW , 270} 271 272var infixOperators = map [token.TokenType ]bool { 273token .AND :true , 274token .CONCAT :true , 275token .EQUAL :true , 276token .GEQ :true , 277token .GT :true , 278token .LEQ :true , 279token .LT :true , 280token .MINUS :true , 281token .NEQ :true , 282token .OR :true , 283token .MOD :true , 284token .PLUS :true , 285token .POW :true , 286token .SLASH :true , 287token .MUL :true , 288} 289 290func isInfixOperator (tok token.TokenType )bool { 291return infixOperators [tok ] 292} 293 294func isRightAssociative (tok token.TokenType )bool { 295return tok == token .POW || tok == token .CONCAT 296} 297 298var suffixOperators = map [token.TokenType ]bool { 299token .COLON :true , 300token .DOT :true , 301token .LBRACE :true , 302token .LBRACK :true , 303token .LPAREN :true , 304token .STRING :true , 305} 306 307func isSuffixOperator (tok token.TokenType )bool { 308return suffixOperators [tok ] 309}