Documentation
¶
Overview ¶
Package racc is a pure-Go (CGO=0) port of MRI's Racc::Parser runtime — the table-driven LALR(1) parse engine that every racc-generated Ruby parser drives via `include Racc::Parser`.
This is the RUNTIME only, not the racc generator. A racc-generated parser file embeds a constant `Racc_arg` (the parse tables: action/goto/reduce tables, the token-value table, the shift/reduce counts, …) plus the generated reduce-action methods (`_reduce_N`) and a `next_token` lexer. At parse time, MRI's `_racc_do_parse_rb` / `_racc_yyparse_rb` interpret those tables, calling back into the lexer and the reduce actions. This package reproduces that interpreter byte-for-byte on the parse trajectory: given the same tables and the same token stream, it performs the same shift/reduce/accept/error sequence and returns the same result as MRI running its Ruby runtime core.
The engine is pure compute. The host (e.g. rbgo) injects three SEAMS that, in a generated parser, are the user's Ruby code:
- NextToken: the lexer (`next_token` / the iterator yielded by yyparse). It returns the next [tokenSymbol, value] pair; symbol == nil signals EOF, which MRI spells `[false, false]`.
- Reduce: the reduce-action dispatch (`__send__(method_id, val, vstack[, result])`), i.e. the generated `_reduce_N` callbacks. Given the rule index (the racc `method_id`) and the slice of popped symbol values, it returns the value of the produced nonterminal.
- OnError: the parse-error handler (`on_error`). It is called the first time an error action fires; returning normally enters racc's error-recovery mode, and returning an error aborts the parse with that error. The default handler (Parser.OnError unset) raises a ParseError, matching MRI.
The Tables layout mirrors MRI's `Racc_arg` array exactly so a generated parser's tables drive this engine unchanged; see Tables for the index mapping.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ParseError ¶
type ParseError struct {
// Tok is the internal token id of the token that caused the error
// (MRI's ERROR_TOKEN_ID).
Tok int
// Val is the value of the offending token (MRI's ERROR_VALUE).
Val any
// Msg is the rendered message, matching MRI's
// "parse error on value <val.inspect> (<token_to_str or '?'>)".
Msg string
}
ParseError is the error MRI's Racc::Parser raises (and rescues) on a parse error. It corresponds to Ruby's `Racc::ParseError < StandardError`.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
type Parser ¶
type Parser struct {
// Tables are the racc-generated parse tables driving the automaton.
Tables *Tables
// NextToken is the lexer seam, used by DoParse. It returns the next token's
// internal-or-external symbol and value. A nil symbol means EOF (MRI's
// `[false, false]`). The returned symbol is looked up in Tables.TokenTable;
// an unknown non-nil symbol maps to the error token (internal id 1).
NextToken func() (sym any, val any)
// Reduce is the reduce-action dispatch seam (the generated `_reduce_N`). It is
// called with the racc rule's method_id and the slice of popped symbol values
// (MRI's `val`), and returns the value of the produced nonterminal. When
// Tables.UseResult is true the action conventionally starts from values[0]
// (MRI passes `tmp_v[0]` as the initial `result`); that initial value is also
// provided here as result for parity with the generated `def _reduce_N(val, _values, result)`.
Reduce func(methodID int, values []any, result any) any
// OnError is the parse-error seam (MRI's `on_error`). It is called the first
// time an error action fires, with the offending token id/value and a snapshot
// of the value stack (callers must not mutate it). Returning nil enters racc's
// error-recovery mode; returning a non-nil error aborts the parse with that
// error. When nil, the engine raises a ParseError, matching MRI's default.
OnError func(tok int, val any, valueStack []any) error
// contains filtered or unexported fields
}
Parser is the table-driven LALR(1) parse engine. Construct it with a Tables and the host seams, then call Parser.DoParse or Parser.Yyparse.
A zero Parser is not usable; Tables and NextToken (for DoParse) / the iterator (for Yyparse) plus Reduce must be set.
func (*Parser) DoParse ¶
DoParse runs the parser using the NextToken lexer seam. It is the Go counterpart of Racc::Parser#do_parse → _racc_do_parse_rb. It returns the accepted result (MRI's Symbol_Value_Stack[0]) or a *ParseError (or the error returned by a custom OnError) on failure.
func (*Parser) Yyaccept ¶
func (p *Parser) Yyaccept()
Yyaccept exits the parser from inside a reduce action, like MRI's Racc::Parser#yyaccept (`throw :racc_jump, 2`). Call it only from within a Reduce callback.
func (*Parser) Yyerrok ¶
func (p *Parser) Yyerrok()
Yyerrok leaves error-recovery mode, like MRI's Racc::Parser#yyerrok. Call it from within a Reduce/OnError seam.
func (*Parser) Yyerror ¶
func (p *Parser) Yyerror()
Yyerror enters error-recovery mode from inside a reduce action, like MRI's Racc::Parser#yyerror (`throw :racc_jump, 1`). Call it only from within a Reduce callback; it unwinds to the reduce dispatcher.
func (*Parser) Yyparse ¶
Yyparse runs the parser using a pull-style iterator seam instead of NextToken, mirroring Racc::Parser#yyparse → _racc_yyparse_rb. The yield function passed to iter must be called once per token with (sym, val) (nil sym == EOF), exactly as MRI's RECEIVER#METHOD_ID yields [tok, val]. It returns the accepted result or an error, like DoParse.
In a generated parser, `yyparse(recv, mid)` drives the automaton from tokens that recv.mid yields; here the caller supplies that iterator directly as iter.
type Symbol ¶
type Symbol string
Symbol is the Go representation of a Ruby Symbol token (e.g. :NUMBER). A racc token table keys terminals by their grammar symbol; for named tokens MRI uses a Ruby Symbol and for character literals a String. Use Symbol so the two are distinct map keys in Tables.TokenTable, matching MRI where :foo and "foo" differ.
type Tables ¶
type Tables struct {
ActionTable []int // [0] compressed action table (negative=reduce, positive=shift, shift_n=accept)
ActionCheck []int // [1] validity check parallel to ActionTable
ActionDefault []int // [2] default action per state
ActionPointer []int // [3] per-state base offset into ActionTable (nil ⇒ use default)
GotoTable []int // [4] compressed goto table
GotoCheck []int // [5] validity check parallel to GotoTable
GotoDefault []int // [6] default goto per produced nonterminal
GotoPointer []int // [7] per-state base offset into GotoTable (nil ⇒ use default)
NtBase int // [8] first nonterminal id; reduce_to-NtBase indexes the goto tables
ReduceTable []int // [9] flat triples (len, reduce_to, method_id) indexed by act*-3
TokenTable map[any]int // [10] maps an external token symbol to its internal id (EOF symbol ⇒ 0)
ShiftN int // [11] boundary: 0<act<ShiftN ⇒ shift; act==ShiftN ⇒ accept
ReduceN int // [12] boundary: 0>act>-ReduceN ⇒ reduce; act==-ReduceN ⇒ error
UseResult bool // [13] whether reduce actions take the extra `result` argument
// TokenToS optionally maps an internal token id to its display string
// (MRI's Racc_token_to_s_table), used by [Tables.TokenToStr] and in the
// default parse-error message. It is not part of Racc_arg.
TokenToS []string
}
Tables holds a racc-generated parser's parse tables. The field order and semantics mirror MRI's `Racc_arg` array element-for-element (the comment after each field is the `Racc_arg` index), so the constants emitted by `racc` map directly onto this struct:
Racc_arg = [ action_table, action_check, action_default, action_pointer, # 0..3 goto_table, goto_check, goto_default, goto_pointer, # 4..7 nt_base, reduce_table, token_table, shift_n, # 8..11 reduce_n, use_result_var [, ...] ] # 12..13
The action/goto tables use racc's compressed double-array layout: an entry at pointer+input is valid only when the parallel *_check array equals the current state (resp. nonterminal index), otherwise the *_default for that state is used.
func (*Tables) TokenToStr ¶
TokenToStr returns the display string for an internal token id, mirroring MRI's Racc::Parser#token_to_str (returns "" when there is no mapping, where MRI returns nil). It is exposed because OnError handlers commonly want it.
