z_mirror/luapls

git clone https://git.raiguard.me/z_mirror/luapls

Caleb HeuerFixed that the parser would throw bogus diagnostics when parsing raw stringsdfb9640

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