parser

package module
v0.0.0-...-1ed018b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

README

go-ruby-parser/parser

parser — go-ruby-parser

ci License Go

A pure-Go (CGO=0) Ruby front-end — a lexer, a recursive-descent + Pratt parser, and an AST for Ruby source. No cgo, no Prism, no shelling out to Ruby: the single thing the Go ecosystem lacked for building Ruby tooling (linters, formatters, analysers, doc generators, LSP servers, transpilers) in pure Go.

It was extracted from the go-embedded-ruby interpreter — which now consumes it — and is developed test-first against MRI Ruby 4.0.5.

Install

go get github.com/go-ruby-parser/parser

Usage

import "github.com/go-ruby-parser/parser"

prog, err := parser.Parse(`
def fib(n)
  n < 2 ? n : fib(n - 1) + fib(n - 2)
end
puts fib(20)
`)
if err != nil {
    // err is a parse error with a line number
}
// prog is an *ast.Program; walk prog.Body ([]ast.Node).

The AST node types live in github.com/go-ruby-parser/parser/ast; the token kinds in .../token; the stateful lexer in .../lexer.

What it parses

A broad, practical subset of Ruby 4.0, all differential-tested against MRI:

  • Literals: integers (with Bignum/arbitrary precision, radix 0x/0o/ 0b/0d, underscores), floats (incl. scientific 1.5e3), strings (double- and single-quoted, interpolation, heredocs <</<<-/<<~, %q/%Q literals, the \a/\b/\v/\f/\s/\n/\t/\r/\e/\0 escapes), symbols (incl. quoted/operator), %w/%i/%W/%I arrays, arrays, hashes (incl. the {x:} value-shorthand), ranges (incl. beginless/endless), regexps (/re/imx), true/false/nil.
  • Operators: arithmetic, comparison/<=>, ==/===, bitwise/shift, &&/||/and/or/not, ternary, :: scope, safe navigation &., compound assignment (+=, -=, *=, /=, %=, <<=, ||=, &&=).
  • Control flow: if/unless/while/until (block and modifier), case/when, case/in pattern matching (array/find/hash/pin/ alternative/range patterns, guards, one-line =>/in), begin/rescue/ else/ensure/retry, break/next/return, loop.
  • Methods/blocks: required/optional/*splat/keyword/**rest/&block params, endless methods (def f = expr), setters, operator/[]/[]= method names, operator-method calls (1.+(2)), { } / do…end blocks, (a, b) destructuring group params, stabby lambdas ->(){}, numbered params (_1) and it, yield, super, multiple-value return a, b.
  • Classes/modules/metaprogramming: class/module, inheritance, @ivars, @@class variables, constants, singleton method defs (def self.foo/def obj.foo/def Const.foo), global-variable assignment ($g = …), multiple assignment / destructuring, adjacent string-literal concatenation ("a" "b").

Performance

On the both-accept corpus (the 615 harvested snippets + 110 real CRuby-4.0.5 stdlib files both engines parse), go-ruby-parser beats MRI's reference C parser: it parses 1.5× faster than RubyVM::AbstractSyntaxTree.parse on small snippets and 2.1× faster on real stdlib files, ~6× faster than Ripper.sexp, and the lexer is ~24–30× faster than Ripper.lex — all while building a full Go AST. Methodology, full parity tables, and the allocation hotspots / action items are in BENCHMARKS.md; reproduce with benchmarks/run.sh (an isolated module, outside the coverage gate).

Known limitations

The following are not yet parsed (they remain on go-embedded-ruby's roadmap; contributions welcome):

  • paren-less command calls with keyword/splat/block args (foo a: 1)
  • default block parameters ({ |a = 1| }) — splat block params ({ |*a| }) are supported
  • the positional Class(a) find-pattern (Class[a] is supported)

License

BSD-3-Clause © the go-ruby-parser/parser authors.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Package parser builds an AST from tokens: recursive descent for statements, Pratt (precedence-climbing) for expressions, and a scope stack to resolve the classic local-variable-vs-method-call ambiguity (plan-rbgo.md §10).

The scope stack is what lets `foo` mean a variable read when `foo` was assigned earlier in the same def, and a (possibly command-style) method call otherwise — exactly MRI's rule.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Parse

func Parse(src string) (prog *ast.Program, err error)

Parse lexes and parses src into a Program. It never panics: a malformed input yields a parse error, and any unexpected internal panic is also surfaced as a parse error rather than propagating to the caller.

Types

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser holds parsing state.

Directories

Path Synopsis
Package ast defines the Phase 0 abstract syntax tree.
Package ast defines the Phase 0 abstract syntax tree.
Package lexer turns source bytes into tokens.
Package lexer turns source bytes into tokens.
Package token defines the lexical tokens for the Phase 0 subset.
Package token defines the lexical tokens for the Phase 0 subset.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL