std / saurus/parser

saurus/parser

import "std:saurus/parser"

Recursive descent parser for Saurus source code. Parses token streams into abstract syntax trees with full error recovery and diagnostic reporting. Includes a Pratt parser for expressions with correct operator precedence.

View source on Codeberg →

Types

#
type DiagLevel int

Severity level for a diagnostic message.

#
type Diag struct {
    level DiagLevel
    pos   token.Pos
    msg   string
}

A diagnostic message with severity level, source position, and message text. Fields are unexported; use accessor functions.

#
type DiagList struct { /* unexported fields */ }

A collection of diagnostic messages accumulated during parsing. Create with NewDiagList and free with FreeDiagList.

#
type IntrinsicTypeHandler func(*Parser, string, token.Pos) *ast.TypeNode

Callback for parsing compiler-intrinsic type expressions. Receives the parser, intrinsic name, and source position. Returns a type node or nil on failure.

#
type IntrinsicExprHandler func(*Parser, string, token.Pos) *ast.Expr

Callback for parsing compiler-intrinsic expressions. Receives the parser, intrinsic name, and source position. Returns an expression node or nil on failure.

#
type Parser struct { /* unexported fields */ }

The parser state. Wraps a scanner and maintains current/previous tokens, error state, diagnostic list, and intrinsic handler callbacks.

Constants

#
const (
    NOTE        DiagLevel = iota
    WARNING
    ERROR_LEVEL
)

Diagnostic severity levels: NOTE for informational messages, WARNING for non-fatal issues, and ERROR_LEVEL for parse errors.

Diagnostic Functions

#
func DiagLevelOf(d Diag) DiagLevel

Returns the severity level of a diagnostic.

#
func DiagPos(d Diag) token.Pos

Returns the source position of a diagnostic.

#
func DiagMsg(d Diag) string

Returns the message text of a diagnostic.

#
func NewDiagList() DiagList

Creates a new empty diagnostic list.

#
func FreeDiagList(dl *DiagList)

Frees the internal storage of a diagnostic list.

#
func HasErrors(dl *DiagList) bool

Reports whether the diagnostic list contains any error-level diagnostics.

#
func ErrorCount(dl *DiagList) int

Returns the number of error-level diagnostics.

#
func DiagCount(dl *DiagList) int

Returns the total number of diagnostics (all levels).

#
func GetDiag(dl *DiagList, index int) Diag

Returns the diagnostic at the given index.

#
func DiagHandler(ctx any, pos token.Pos, msg string)

Scanner error handler callback compatible with scanner.ErrorHandler. Pass this as the error handler when creating a scanner for use with the parser. The ctx parameter must be a *DiagList.

Parser Functions

#
func New(s *scanner.Scanner, diags *DiagList) Parser

Creates a new parser from a scanner and diagnostic list. The scanner should use DiagHandler as its error handler with the same DiagList as the context. The parser advances past the first token during initialization.

#
func ParseFile(p *Parser) *ast.File

Parses an entire source file, returning the AST. Handles the package declaration, imports, top-level declarations (functions, variables, constants, types, structs), and compiler directives. The returned File must be freed with ast.FreeFile.

#
func ParseExpr(p *Parser) *ast.Expr

Parses a single expression. Useful for testing and REPL scenarios. The returned Expr must be freed with ast.FreeExpr.

#
func ParseStmt(p *Parser) *ast.Stmt

Parses a single statement. Useful for testing and REPL scenarios. The returned Stmt must be freed with ast.FreeStmt.

#
func HadError(p *Parser) bool

Reports whether the parser encountered any errors during parsing.

Callback Registration

#
func SetIntrinsicTypeHandler(p *Parser, h IntrinsicTypeHandler)

Registers a callback for parsing compiler-intrinsic type expressions (e.g. #type).

#
func SetIntrinsicExprHandler(p *Parser, h IntrinsicExprHandler)

Registers a callback for parsing compiler-intrinsic expressions.

Parser Operations

These functions are primarily for use within intrinsic handler callbacks, allowing custom parsing logic to interact with the parser's token stream.

#
func Advance(p *Parser)

Advances to the next token.

#
func Consume(p *Parser, kind token.Kind, msg string)

Advances if the current token matches the expected kind, otherwise reports an error with the given message.

#
func Check(p *Parser, kind token.Kind) bool

Reports whether the current token is of the given kind without consuming it.

#
func Match(p *Parser, kind token.Kind) bool

If the current token matches the expected kind, consumes it and returns true. Otherwise returns false.

#
func Current(p *Parser) token.Token

Returns the current token without consuming it.

#
func ErrorAtPos(p *Parser, pos token.Pos, msg string)

Reports an error at a specific source position.