@eryx/luau/parse Module

Luau source code parser and comment utilities.

Wraps the native Luau parser to produce a serialized AST. Nodes are discriminated by category and lowercase type, and concrete syntax tokens preserve their exact source text plus leading/trailing trivia. The module also provides helpers for extracting comment text from token trivia and for round-trip pretty-printing.

local parse = require("@eryx/luau/parse")

local result = parse.parse(source, { collectComments = true })
print("Lines:", result.lines)
for _, stat in result.root.body do
    print(stat.type, stat.location.beginline)
end

-- Extract comment payloads from token trivia text.
local stat = result.root.body[1]
if stat.type == "return" then
    local comments = parse.extractComments(stat.returnKeywordToken.leadingText, {
        stripLineLeadingWhitespace = true,
    })
    print(comments[1])
end

Summary

Functions

parse.parse(source: string, options: ParseOptions?)ParseResult<ast.AstStatBlock>
parse.parseExpr(source: string, options: ParseOptions?)ParseResult<ast.AstExpr>
parse.prettyPrint(source: string)string
parse.extractComments(text: string, options: ExtractCommentsOptions?){ string }

API Reference

Functions

parse.parse

Parses Luau source code and returns a structured AST.

The returned root is an AstStatBlock node whose body contains an array of statement nodes. Serialized AST nodes carry a category, a lowercase type discriminator, and a 1-based source location.

Pass { collectComments = true } to include a comments array in the result. Concrete syntax tokens are included directly on the AST and carry text, location, leadingText, and trailingText.

local result = parse.parse(source, { collectComments = true })
print("Lines:", result.lines)
print("Errors:", #result.errors)
print("Top-level statements:", #result.root.body)
parse.parse(source: string, options: ParseOptions?)ParseResult<ast.AstStatBlock>

Parameters

source: string

The Luau source code string to parse.

options: ParseOptions?

Parse options (e.g. comment capture).

Returns

The parse result containing the AST root, errors, and optional comments.

parse.parseExpr

Parses a single Luau expression and returns that expression as root.

The result has the same shape as parse, but root is an AstExpr instead of a top-level statement block. Syntax errors are reported through errors and may produce error placeholder nodes.

parse.parseExpr(source: string, options: ParseOptions?)ParseResult<ast.AstExpr>

Parameters

source: string

The Luau expression source string to parse.

options: ParseOptions?

Parse options (e.g. comment capture).

Returns

The parse result containing the expression root, errors, and optional comments.

parse.prettyPrint

Pretty-prints Luau source code by round-tripping through the parser.

parse.prettyPrint(source: string)string

Parameters

source: string

The Luau source code to format.

Returns

string

The reformatted source code.

parse.extractComments

Extracts comment content from raw leading or trailing text.

This is intended for use with strings from token leadingText and trailingText fields. Those strings preserve all trivia; this helper turns comments inside them into payload strings on demand.

When stripLineLeadingWhitespace is true, line comments like -- hello are returned as "hello" instead of " hello".

parse.extractComments(text: string, options: ExtractCommentsOptions?){ string }

Parameters

text: string

Raw surrounding text.

Comment extraction options.

Returns

{ string }

Extracted comment strings.

Types

Position

type Position = ast.Position
Implements: ast.Position

Location

type Location = ast.Location
Implements: ast.Location

ParseResult<Root>

type ParseResult<Root> = { root: Root, errors: { { message: string, location: Location } }, source: string, lines: { string }, comments: { { type: "line" | "block" | "broken" | "unknown", location: Location } }? }
root: Root
errors: { { message: string, location: Location } }
source: string
lines: { string }
comments: { { type: "line" | "block" | "broken" | "unknown", location: Location } }?

ParseOptions

type ParseOptions = { collectComments: boolean? }
collectComments: boolean?

ExtractCommentsOptions

type ExtractCommentsOptions = { unindentMultiLineContent: boolean?, stripLineLeadingWhitespace: boolean?, merge: ("none" | "same" | "all")? }
unindentMultiLineContent: boolean?

If true, strip the common leading indentation from block comment content.

stripLineLeadingWhitespace: boolean?

If true, strip leading whitespace from line comment content (e.g. -- hello -> "hello").

merge: ("none" | "same" | "all")?

Controls merging of adjacent comments. "none" (default) keeps each comment separate, "same" merges adjacent same-kind comments, "all" merges all adjacent comments.