tabnasjson

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2026 License: MIT Imports: 4 Imported by: 0

README

json (Go)

A standard JSON parser (RFC 8259 / ECMA-404) for Go — the standard-JSON grammar plugin for the tabnas parsing engine (github.com/tabnas/parser/go).

This is the Go port of @tabnas/json. TypeScript is canonical; both runtimes share the conformance fixtures in ../ts/test/spec/ and produce identical results.

Install

go get github.com/tabnas/json/go

The module depends on github.com/tabnas/parser/go; until that is published it is resolved via a replace directive to a sibling checkout — see Develop.

Quick example

package main

import (
	"fmt"

	tabnasjson "github.com/tabnas/json/go"
)

func main() {
	v, err := tabnasjson.Parse(`{"a":1,"b":[2,3]}`)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v\n", v) // map[string]interface {}{"a":1, "b":[]interface {}{2, 3}}
}

Parse returns values using the same Go types as encoding/json: nil, bool, float64, string, []any, and map[string]any.

Documentation

Full Diátaxis docs:

TypeScript is canonical; its docs are in ../ts/doc/.

Use it as a plugin

The package is a tabnas grammar plugin. Install it on your own engine instance and layer further grammar on the shared rules:

import (
	tabnasjson "github.com/tabnas/json/go"
	tabnas "github.com/tabnas/parser/go"
)

j := tabnas.Make()
j.Use(tabnasjson.Json)
v, err := j.Parse(`{"a":[1,2,3]}`)

RegisterJSONGrammar(j) installs just the val / map / list / pair / elem rules (jsonic's "Plain JSON" core) for plugins that want to build on the JSON rule set.

Reuse and options

Parse reuses a single lazily-created instance (safe for concurrent use, since each parse builds its own context), so you don't rebuild the grammar on every call. To customize, build your own instance with Make(extra ...Options):

tr := true
p := tabnasjson.Make(tabnas.Options{Info: &tabnas.InfoOptions{Map: &tr, List: &tr}})
p.Parse(`{"a":[1,2]}`)

What it accepts

Exactly standard JSON — objects with double-quoted string keys, arrays, double-quoted strings (with \" \\ \/ \b \f \n \r \t \uXXXX and surrogate pairs), numbers, true, false, null, and insignificant whitespace. It rejects everything outside that grammar (comments, trailing commas, unquoted keys, single quotes, implicit structures, hex numbers, leading zeros, .5, 1., +1, empty input) — the same surface as encoding/json.

Extending the grammar

Because this is a plain grammar plugin on the shared engine, it is a foundation to build other parsers on. Layer options or rules on top of the JSON grammar. For example, a JSON-with-comments (JSONC) parser is just the JSON grammar with comment lexing re-enabled:

tr := true
jsonc := tabnasjson.Make(tabnas.Options{Comment: &tabnas.CommentOptions{Lex: &tr}})
jsonc.Parse(`{"a":1} // ok`)    // map[string]any{"a": 1}
jsonc.Parse(`{"a":/* ok */1}`)  // map[string]any{"a": 1}

For deeper changes, call RegisterJSONGrammar(j) to install just the rules, then use the engine's rule API (j.Rule(...), and the ClearOpen / ClearClose / @<rule>-<phase>/replace hooks) to replace or extend the shared val / map / list / pair / elem rules without re-declaring the JSON core.

Errors

On invalid input Parse returns a *tabnas.TabnasError:

v, err := tabnasjson.Parse("{a:1}")
if err != nil {
	var je *tabnas.TabnasError
	if errors.As(err, &je) {
		fmt.Println(je.Code) // unexpected
	}
}

Develop

This module depends on the engine as a sibling checkout:

git clone https://github.com/tabnas/parser   # sibling of this repo
go test ./...   # replace directive resolves ../../parser/go;
                # also runs the shared ../ts/test/spec fixtures

See AGENTS.md for layout and conventions.

Grammar diagram

The grammar is identical across runtimes. Its railroad/syntax diagram (generated from the live TS grammar with @tabnas/railroad) lives in the TS docs: ../ts/doc/grammar.svg, with an ASCII version in ../ts/doc/grammar.txt.

License

MIT.

Documentation

Overview

Package json is a standard JSON grammar plugin for the tabnas parsing engine (github.com/tabnas/parser/go).

The engine ships no grammar of its own; this package supplies the strict, standard-JSON one. The rule set (val / map / list / pair / elem) is jsonic's "Plain JSON" grammar — the pure-JSON core jsonic defines before extending it for the relaxed jsonic format. Here that core is installed on its own, with the lexer restricted to strict JSON and none of jsonic's extended grammar (comments, unquoted keys, implicit objects/arrays, trailing commas, single/backtick strings, path diving). It mirrors encoding/json: quoted-string keys only, double-quoted strings, plain decimal numbers, true/false/null.

This plugin is intended to be the foundation other tabnas grammar plugins build on: Use it first, then layer rules on the shared val / map / list / pair / elem rules.

Index

Constants

View Source
const Version = "0.2.0"

Version is the current version of the module.

Variables

This section is empty.

Functions

func Json

func Json(j *tabnas.Tabnas, _ map[string]any) error

Json is the standard plugin form: apply the strict JSON options, then register the JSON grammar. Use it on a bare engine, or call Make.

func Make

func Make(extra ...tabnas.Options) *tabnas.Tabnas

Make builds a standard-JSON parser instance, optionally layering extra options (e.g. info.Map/List/Text) over the base strict configuration.

func Parse

func Parse(src string) (any, error)

Parse parses a JSON source string with a default standard-JSON parser and returns the resulting value, or a *tabnas.TabnasError on failure.

func RegisterJSONGrammar

func RegisterJSONGrammar(j *tabnas.Tabnas) error

RegisterJSONGrammar installs the standard JSON rule set (val / map / list / pair / elem) on j via the engine's declarative grammar spec — the same shape as the TypeScript registerJsonGrammar. Exposed separately from the options so other grammar plugins can layer on the JSON core.

The value tree is built ENTIRELY by the engine's native-value `$`-builtins (object/array/reset/key/setval/push/value); there are NO grammar-local closures. The builders are info-aware, so when the MapRef / ListRef / TextInfo options are enabled they allocate the engine's info carriers (MapRef / ListRef / Text) and perform the container/quote annotation themselves — the json plugin used to hand-write that as @map-bc / @list-bc / @val-bc state hooks. Strict JSON containers are always explicit, so @object$/@array$ take the default implicit:false (no `K` config needed).

The builtin actions used below, one line each:

@reset$  — clear the parent-seeded node (so a value doesn't inherit the parent container).
@object$ — allocate an empty object into the node (a MapRef under info.Map).
@array$  — allocate an empty array into the node (a ListRef under info.List).
@key$    — capture the matched key token into a scratch slot for the pending @setval$.
@setval$ — assign the just-built child value into the object under the captured key.
@push$   — append the just-built child value to the array.
@value$  — resolve the rule's value: a built child wins, else the scalar token (a Text under info.Text).

Types

This section is empty.

Directories

Path Synopsis
cmd
tabnas-json command
Command tabnas-json is a tiny command-line front end: read JSON from the arguments or from stdin, parse it (strict, standard JSON), and print the canonical re-serialized form.
Command tabnas-json is a tiny command-line front end: read JSON from the arguments or from stdin, parse it (strict, standard JSON), and print the canonical re-serialized form.

Jump to

Keyboard shortcuts

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