├── .clang-format
├── .devcontainer
└── devcontainer.json
├── .github
├── dependabot.yml
├── release.yml
└── workflows
│ ├── auto-approve.yaml
│ ├── brgen-test.yaml
│ ├── build.yml
│ ├── codeql.yml
│ ├── deploy.yml
│ ├── puppeteer-test.yml
│ ├── release.yml
│ └── test.yml
├── .gitignore
├── .licensed.yml
├── .vscode
├── c_cpp_properties.json
├── launch.json
├── settings.json
└── tasks.json
├── CMakeLists.txt
├── CONTRIBUTE.md
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── arch.md
├── astlib
├── ast2c
│ ├── ast.c
│ ├── ast.h
│ └── test.c
├── ast2csharp
│ ├── ast.cs
│ └── ast2csharp.csproj
├── ast2dart
│ └── lib
│ │ └── ast.dart
├── ast2go
│ ├── ast
│ │ └── ast.go
│ ├── gen
│ │ └── gen.go
│ ├── generate_nix.go
│ ├── generate_win.go
│ ├── js
│ │ └── set.go
│ └── request
│ │ ├── exec.go
│ │ ├── generator.go
│ │ ├── request.go
│ │ └── response.go
├── ast2py
│ ├── __init__.py
│ ├── ast.py
│ ├── example.py
│ └── test.py
├── ast2rust
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── core
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ ├── ast.rs
│ │ │ ├── eval.rs
│ │ │ ├── lib.rs
│ │ │ ├── test.rs
│ │ │ └── traverse.rs
│ └── macros
│ │ ├── Cargo.toml
│ │ └── src
│ │ └── lib.rs
└── ast2ts
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ ├── analyze.ts
│ ├── ast.ts
│ └── index.ts
│ └── tsconfig.json
├── brgen.json
├── brgen.sln
├── build.bat
├── build.sh
├── build_all.bat
├── docker-compose.yml
├── docker_vscode
├── c_cpp_properties.json
├── launch.json
├── settings.json
└── tasks.json
├── example
├── 9p.bgn
├── arp.bgn
├── asn1.bgn
├── ast_step
│ ├── step1.bgn
│ ├── step2.bgn
│ ├── step3.bgn
│ ├── step4.bgn
│ ├── step5.bgn
│ ├── step6.bgn
│ ├── step7.bgn
│ ├── step8.bgn
│ └── step9.bgn
├── att.bgn
├── attestation_object.bgn
├── avro.bgn
├── ax25.bgn
├── bgp.bgn
├── bmp.bgn
├── bmp.txt
├── bpf.bgn
├── brgen_help
│ ├── ast_enum.bgn
│ ├── game.bgn
│ ├── generator.bgn
│ ├── key.bgn
│ ├── lexer_enum.bgn
│ ├── segment_routing_header.bgn
│ ├── share.bgn
│ ├── ssa.bgn
│ ├── vm2.bgn
│ └── vm_enum.bgn
├── can.bgn
├── capnproto.bgn
├── cbor.bgn
├── ccsds.bgn
├── chg.bgn
├── cmsg.bgn
├── coap.bgn
├── core_can_proto.bgn
├── dccp.bgn
├── dhcp.bgn
├── dhcpv6.bgn
├── dns.bgn
├── dnssec.bgn
├── dq2.bgn
├── dq4.bgn
├── elf.bgn
├── ether.bgn
├── etherip.bgn
├── fastcgi.bgn
├── feature_test
│ ├── analyze_block_trait.bgn
│ ├── assert_or_implicit_yeild.bgn
│ ├── bit_fields.bgn
│ ├── comma_match.bgn
│ ├── const_length.bgn
│ ├── edge_case1.bgn
│ ├── for_in.bgn
│ ├── import_and_use.bgn
│ ├── loop_ref.bgn
│ ├── nested_state.bgn
│ ├── regexp.bgn
│ ├── simple_binary.bgn
│ ├── sort_test.bgn
│ ├── state_variable.bgn
│ ├── state_variable2.bgn
│ ├── test_import.bgn
│ ├── tree_test.bgn
│ ├── trial_match.bgn
│ ├── union.bgn
│ └── varint_test.bgn
├── fido_u2f.bgn
├── from_kaitai
│ └── btrfs_stream.bgn
├── fs.txt
├── gen_step
│ ├── step1.bgn
│ ├── step2.bgn
│ ├── step3.bgn
│ ├── step4.bgn
│ ├── step4_a.bgn
│ ├── step4_b.bgn
│ ├── step5.bgn
│ ├── step6.bgn
│ └── step7.bgn
├── gif.bgn
├── gpio_r1.bgn
├── gre.bgn
├── gzip.bgn
├── hci.bgn
├── http.bgn
├── http2.bgn
├── icmp.bgn
├── icn.bgn
├── ico.bgn
├── ieee802_11.bgn
├── ietf_hackathon
│ ├── bgp_ls.bgn
│ ├── initial_registory.bgn
│ ├── routing.bgn
│ └── sid.bgn
├── igmp.bgn
├── ike.bgn
├── il.bgn
├── impromptu_app_protocol.bgn
├── ip.bgn
├── ipsec.bgn
├── ipv6addr.bgn
├── isis.bgn
├── l2cap.bgn
├── l2tp.bgn
├── llama2.bgn
├── llcp.bgn
├── llvm_ir.bgn
├── mach-o.bgn
├── minecraft.bgn
├── mp3.bgn
├── mp4.bgn
├── mpls.bgn
├── mptcp.bgn
├── mqtt.bgn
├── mrt.bgn
├── msgpack.bgn
├── nes.bgn
├── nes_sound_register.bgn
├── netlink.bgn
├── ntfs.bgn
├── ntp.bgn
├── ospfv2.bgn
├── ospfv3.bgn
├── pcap.bgn
├── pcapng.bgn
├── pcep.bgn
├── pe_header.bgn
├── pefile.txt
├── pefile_map.json
├── png.bgn
├── ppp.bgn
├── protobuf.bgn
├── qr_code.bgn
├── quic_frame.bgn
├── quic_packet.bgn
├── quic_transport_parameter.bgn
├── quic_varint.bgn
├── radius.bgn
├── rdp.bgn
├── rip.bgn
├── rtp.bgn
├── rudp.bgn
├── s2j_test
│ ├── arp.bgn.json
│ ├── asn1.bgn.json
│ ├── attestation_object.bgn.json
│ ├── avro.bgn.json
│ ├── bgp.bgn.json
│ ├── bpf.bgn.json
│ ├── can.bgn.json
│ ├── capnproto.bgn.json
│ ├── cbor.bgn.json
│ ├── ccsds.bgn.json
│ ├── chg.bgn.json
│ ├── dhcp.bgn.json
│ ├── dhcpv6.bgn.json
│ ├── dns.bgn.json
│ ├── dnssec.bgn.json
│ ├── elf.bgn.json
│ ├── ether.bgn.json
│ ├── etherip.bgn.json
│ ├── gif.bgn.json
│ ├── http.bgn.json
│ ├── http2.bgn.json
│ ├── icmp.bgn.json
│ ├── ieee802_11.bgn.json
│ ├── igmp.bgn.json
│ ├── ike.bgn.json
│ ├── impromptu_app_protocol.bgn.json
│ ├── ip.bgn.json
│ ├── ipsec.bgn.json
│ ├── ipv6addr.bgn.json
│ ├── l2tp.bgn.json
│ ├── llvm_ir.bgn.json
│ ├── mach-o.bgn.json
│ ├── mp3.bgn.json
│ ├── mp4.bgn.json
│ ├── mqtt.bgn.json
│ ├── msgpack.bgn.json
│ ├── nes.bgn.json
│ ├── ntfs.bgn.json
│ ├── ntp.bgn.json
│ ├── pcap.bgn.json
│ ├── pcapng.bgn.json
│ ├── pe_header.bgn.json
│ ├── ppp.bgn.json
│ ├── protobuf.bgn.json
│ ├── quic_frame.bgn.json
│ ├── quic_packet.bgn.json
│ ├── quic_transport_parameter.bgn.json
│ ├── quic_varint.bgn.json
│ ├── rtp.bgn.json
│ ├── sctp.bgn.json
│ ├── simple.bgn.json
│ ├── smf.bgn.json
│ ├── stl.bgn.json
│ ├── stub.bgn.json
│ ├── stun.bgn.json
│ ├── swf_rect.bgn.json
│ ├── syslog.bgn.json
│ ├── tar.bgn.json
│ ├── tcp_segment.bgn.json
│ ├── tftp.bgn.json
│ ├── tls_record.bgn.json
│ ├── tzdb.bgn.json
│ ├── udp.bgn.json
│ ├── usb.bgn.json
│ ├── wasm.bgn.json
│ ├── wasmos.bgn.json
│ ├── wave.bgn.json
│ ├── websocket.bgn.json
│ ├── wireguard.bgn.json
│ └── zip.bgn.json
├── safetensor.bgn
├── sctp.bgn
├── simple.bgn
├── smf.bgn
├── socks.bgn
├── softether.bgn
├── sqlite.bgn
├── srv6.bgn
├── ssh.bgn
├── stl.bgn
├── stp.bgn
├── stub.bgn
├── stun.bgn
├── swf_rect.bgn
├── syslog.bgn
├── tar.bgn
├── tcp_segment.bgn
├── tftp.bgn
├── tls_ech.bgn
├── tls_record.bgn
├── tor.bgn
├── tor_prop220.bgn
├── tor_prop224.bgn
├── tor_rend.bgn
├── tpacket.bgn
├── tpm2.bgn
├── tpm2_enum.txt
├── ts.bgn
├── tzdb.bgn
├── udp.bgn
├── usb.bgn
├── vm_test
│ └── udp_test.bgn
├── vrrp.bgn
├── wasm.bgn
├── wasmos.bgn
├── wasmos_def.txt
├── wave.bgn
├── webauthn.bgn
├── webauthn_cosepubkey.bgn
├── websocket.bgn
├── wimax.bgn
├── wire_data
│ ├── capnproto.dat
│ ├── request.dat
│ ├── tcp.dat
│ ├── udp.dat
│ ├── unknwon_raspi.bgn
│ ├── varint.dat
│ └── websocket.dat
├── wireguard.bgn
├── x64.bgn
├── xfs.bgn
└── zip.bgn
├── go.mod
├── go.sum
├── lsp
├── .vscodeignore
├── LICENSE
├── client
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ └── extension.ts
│ └── tsconfig.json
├── package-lock.json
├── package.json
└── server
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ └── server.ts
│ └── tsconfig.json
├── renovate.json
├── script
├── clean.bat
├── clone_utils.bat
├── clone_utils.sh
├── cmptest_debug.sh
├── collect_licenses.sh
├── copy_bmgen_stub.py
├── copy_example.py
├── dirty_patch.py
├── export_tag.sh
├── fetch_rebrgen.sh
├── gen_deep.bat
├── gen_enum.bat
├── gen_large.py
├── gen_sample.bat
├── gen_samples.sh
├── generate.py
├── install_lsp.bat
├── license_note.txt
├── link_path.sh
├── make_ast_doc.sh
├── make_cpp_test.sh
├── make_cpp_tests.sh
├── push_and_watch.bat
├── tag.txt
└── tag_release.bat
├── spec
├── brgen_cmptest_config_schema.json
├── brgen_generated_mapping_schema.json
├── brgen_json_schema.json
├── brgen_test_info_schema.json
├── draft1.md
├── draft2.md
├── draft3.md
├── draft4.md
└── generator_spec_file.md
├── src
├── CMakeLists.txt
├── core
│ ├── ast
│ │ ├── ast.h
│ │ ├── expr_layer.h
│ │ ├── file.h
│ │ ├── json.h
│ │ ├── kill_node.h
│ │ ├── line_map.h
│ │ ├── node
│ │ │ ├── ast_enum.h
│ │ │ ├── base.h
│ │ │ ├── deep_copy.h
│ │ │ ├── expr.h
│ │ │ ├── literal.h
│ │ │ ├── node_type.h
│ │ │ ├── scope.h
│ │ │ ├── statement.h
│ │ │ ├── translated.h
│ │ │ └── type.h
│ │ ├── node_type_list.h
│ │ ├── parse.cpp
│ │ ├── parse.h
│ │ ├── stream.h
│ │ ├── tool
│ │ │ ├── compare.h
│ │ │ ├── eval.h
│ │ │ ├── extract_config.h
│ │ │ ├── ident.h
│ │ │ ├── metadata.h
│ │ │ ├── sort.h
│ │ │ ├── stringer.h
│ │ │ └── tmp_ident.h
│ │ └── traverse.h
│ ├── common
│ │ ├── debug.h
│ │ ├── error.h
│ │ ├── expected.h
│ │ ├── file.h
│ │ └── util.h
│ ├── lexer
│ │ ├── lexer.h
│ │ ├── lexer_enum.h
│ │ └── token.h
│ └── middle
│ │ ├── analyze_block_trait.cpp
│ │ ├── analyze_block_trait.h
│ │ ├── replace_assert.h
│ │ ├── replace_error.h
│ │ ├── replace_metadata.h
│ │ ├── replace_order_spec.h
│ │ ├── replacer.h
│ │ ├── resolve_available.h
│ │ ├── resolve_import.h
│ │ ├── resolve_io_operation.h
│ │ ├── resolve_state_dependency.h
│ │ ├── type_attribute.cpp
│ │ ├── type_attribute.h
│ │ ├── typing.cpp
│ │ └── typing.h
├── request
│ ├── generator.hpp
│ └── stream.hpp
├── test
│ ├── CMakeLists.txt
│ ├── core
│ │ ├── ast_test.cpp
│ │ ├── ast_test_component.cpp
│ │ ├── ast_test_component.h
│ │ ├── deep_copy_test.cpp
│ │ ├── derive_test.cpp
│ │ ├── from_json_test.cpp
│ │ ├── lexer_test.cpp
│ │ ├── middle_test.cpp
│ │ ├── middle_test.h
│ │ ├── section_writer_test.cpp
│ │ ├── type_attribute_test.cpp
│ │ └── typing_test.cpp
│ ├── test_tool
│ │ ├── fuzzing_test.go
│ │ └── test_log_server
│ │ │ └── main.go
│ └── tool
│ │ └── json2c
│ │ └── ctype_test.cpp
├── tool
│ ├── brgen
│ │ ├── config.go
│ │ ├── generator.go
│ │ ├── generator_handler.go
│ │ ├── main.go
│ │ └── stdin_stream.go
│ ├── cmptest
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ ├── main.rs
│ │ │ └── testutil.rs
│ ├── common
│ │ ├── em_main.h
│ │ ├── generate.h
│ │ ├── load_json.h
│ │ ├── print.h
│ │ └── send.h
│ ├── ctobgn
│ │ └── main.cpp
│ ├── gen
│ │ ├── ast2c
│ │ │ └── gen_ast2c.go
│ │ ├── ast2csharp
│ │ │ └── gen_ast2csharp.go
│ │ ├── ast2dart
│ │ │ └── gen_ast2dart.go
│ │ ├── ast2go
│ │ │ └── gen_ast2go.go
│ │ ├── ast2mermaid
│ │ │ └── gen_ast2mermaid.go
│ │ ├── ast2py
│ │ │ └── gen_ast2py.go
│ │ ├── ast2rust
│ │ │ └── gen_ast2rust.go
│ │ ├── ast2ts
│ │ │ └── gen_ast2ts.go
│ │ ├── cpp_deep_copy
│ │ │ └── main.go
│ │ ├── enum_gen
│ │ │ └── enum_gen.go
│ │ ├── gen.go
│ │ └── type.go
│ ├── hex2bin
│ │ ├── hex.h
│ │ └── main.cpp
│ ├── json2c
│ │ ├── ctype.h
│ │ ├── generate.h
│ │ └── main.cpp
│ ├── json2cpp2
│ │ ├── generate.h
│ │ └── main.cpp
│ ├── json2go
│ │ ├── generate.go
│ │ ├── js.go
│ │ └── main.go
│ ├── json2graphviz
│ │ └── main.go
│ ├── json2kaitai
│ │ ├── js.go
│ │ ├── kaitai.go
│ │ ├── main.go
│ │ └── schema.go
│ ├── json2llvm
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ └── src
│ │ │ ├── generate.rs
│ │ │ └── main.rs
│ ├── json2mermaid
│ │ └── main.go
│ ├── json2rust
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ ├── generator.rs
│ │ │ ├── lib.rs
│ │ │ └── main.rs
│ ├── json2spicy
│ │ └── spicy.go
│ ├── json2ts
│ │ ├── generate.cpp
│ │ ├── generate.h
│ │ └── main.cpp
│ ├── json2vm
│ │ └── main.cpp
│ ├── json2vm2
│ │ └── main.cpp
│ ├── rfc2bgn
│ │ └── main.cpp
│ ├── s2jgo
│ │ ├── capability.go
│ │ ├── common.go
│ │ ├── s2j_dlopen.go
│ │ ├── s2j_stub.go
│ │ ├── s2j_test.go
│ │ └── s2j_win.go
│ ├── src2json
│ │ ├── capi.h
│ │ ├── capi_export.h
│ │ ├── entry.cpp
│ │ ├── entry.h
│ │ ├── hook.h
│ │ ├── network.cpp
│ │ ├── src2json.cpp
│ │ ├── test.cpp
│ │ ├── test.h
│ │ └── version.h
│ └── ssagen
│ │ ├── main.go
│ │ └── ssa
│ │ ├── compile.go
│ │ └── ssa.go
├── vm
│ ├── compile.cpp
│ ├── compile.h
│ ├── vm.cpp
│ ├── vm.h
│ ├── vm2
│ │ ├── compile.cpp
│ │ ├── compile.h
│ │ ├── interpret.cpp
│ │ ├── interpret.h
│ │ ├── jit_x64.cpp
│ │ ├── layout.cpp
│ │ ├── layout.h
│ │ ├── vm2.h
│ │ └── vm_enum.h
│ └── vm_enum.h
└── writer
│ ├── bit_io.h
│ ├── config.h
│ ├── context.h
│ ├── section.h
│ └── writer.h
├── test-brgen.json
├── test.bat
├── testkit
├── cmptest.json
├── cpp
│ ├── CMakeLists.txt
│ ├── config.json
│ ├── setup.py
│ ├── stub.hpp
│ └── test_template.cpp
├── go
│ ├── config.json
│ ├── setup.py
│ ├── test_class.go
│ └── test_template.go
└── rust
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── config.json
│ ├── setup.py
│ └── src
│ ├── main.rs
│ └── target.rs
└── web
├── dev
├── package-lock.json
├── package.json
├── src
│ ├── compiler-explorer
│ │ ├── api.ts
│ │ └── types.ts
│ ├── cpp_include.ts
│ ├── generator.ts
│ ├── index.tsx
│ ├── s2j
│ │ ├── brgen_lsp.ts
│ │ ├── caller.ts
│ │ ├── dummy_fs.ts
│ │ ├── em_work_ctx.ts
│ │ ├── emscripten_mod.ts
│ │ ├── file_select.ts
│ │ ├── go_work_ctx.ts
│ │ ├── inputServiceStub.js
│ │ ├── job_mgr.ts
│ │ ├── msg.ts
│ │ ├── request_queue.ts
│ │ ├── update.tsx
│ │ └── worker
│ │ │ ├── bmgen
│ │ │ ├── bmgen_worker.ts
│ │ │ └── util.ts
│ │ │ ├── json2c_worker.ts
│ │ │ ├── json2cpp2_worker.ts
│ │ │ ├── json2go_worker.ts
│ │ │ ├── json2kaitai_worker.ts
│ │ │ ├── json2rust_worker.ts
│ │ │ ├── json2ts_worker.ts
│ │ │ └── src2json_worker.ts
│ ├── save-data
│ │ └── save.ts
│ ├── storage.ts
│ ├── types.ts
│ └── ui.tsx
├── stub
│ └── bmgen
│ │ ├── bm2cpp.js
│ │ ├── bm2rust.js
│ │ ├── bm_caller.js
│ │ └── bmgen.js
├── test
│ └── puppet.mjs
├── tsconfig.json
├── wasmCopy.js.txt
└── webpack.config.js
├── doc
├── .hugo_build.lock
├── archetypes
│ └── default.md
├── content
│ ├── _index.md
│ └── docs
│ │ ├── ast.md
│ │ ├── bnf.md
│ │ ├── builtin.md
│ │ ├── change.md
│ │ ├── config.md
│ │ ├── exec_model.md
│ │ ├── for_ai.md
│ │ ├── generator_dev.md
│ │ ├── language.md
│ │ ├── metadata.md
│ │ ├── overview.md
│ │ ├── setup.md
│ │ ├── src_core.md
│ │ ├── src_tool.md
│ │ └── todo.md
├── go.mod
├── go.sum
├── hugo.toml
└── layouts
│ └── shortcodes
│ └── mermaid.html
└── public
└── index.html
/.clang-format:
--------------------------------------------------------------------------------
1 | UseTab: Never
2 | BasedOnStyle: Google
3 | BreakBeforeBraces: Custom
4 | SortIncludes: false
5 | ColumnLimit: 0
6 | IndentWidth: 4
7 | NamespaceIndentation: All
8 | AllowShortFunctionsOnASingleLine: Empty
9 | BraceWrapping:
10 | AfterFunction: false
11 | BeforeElse: true
12 | AfterControlStatement: false
13 | AfterNamespace: false
14 | AfterClass: false
15 | AfterStruct: false
16 | AfterEnum: false
17 | AfterUnion: false
18 | AfterExternBlock: false
19 | BeforeCatch: false
20 | BeforeLambdaBody: false
21 | BeforeWhile: false
22 | RequiresExpressionIndentation: OuterScope
23 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependence for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "weekly"
8 |
9 | # Maintain dependence for golang
10 | - package-ecosystem: "gomod"
11 | directory: "/**"
12 | schedule:
13 | interval: "weekly"
14 |
15 | - package-ecosystem: "npm"
16 | directory: "/**"
17 | schedule:
18 | interval: "weekly"
19 | - package-ecosystem: "cargo"
20 | directory: "/**"
21 | schedule:
22 | interval: "weekly"
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | categories:
3 | - title: 🏕 Features
4 | labels:
5 | - '*'
6 | exclude:
7 | labels:
8 | - dependencies
9 | - title: 👒 Dependencies
10 | labels:
11 | - dependencies
--------------------------------------------------------------------------------
/.github/workflows/auto-approve.yaml:
--------------------------------------------------------------------------------
1 | name: Auto approve
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, ready_for_review]
6 |
7 | jobs:
8 | auto-approve:
9 | runs-on: ubuntu-latest
10 | if: |
11 | github.event.pull_request.user.login == github.repository_owner &&
12 | ! github.event.pull_request.draft
13 | permissions:
14 | pull-requests: write
15 | steps:
16 | - name: Auto approve
17 | uses: hmarr/auto-approve-action@8f929096a962e83ccdfa8afcf855f39f12d4dac7 # v4
18 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: brgen-test
2 | run-name: brgen test
3 | on:
4 | - push
5 | jobs:
6 | test-linux:
7 | runs-on: ubuntu-latest
8 | timeout-minutes: 10
9 | steps:
10 | - name: Timeline
11 | uses: Kesin11/actions-timeline@427ee2cf860166e404d0d69b4f2b24012bb7af4f # v2.2.3
12 | with:
13 | github-token: ${{ secrets.GITHUB_TOKEN }}
14 | - name: Checkout repository
15 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
16 | - name: Set up Ninja
17 | uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # master
18 | - name: Set up Clang
19 | uses: egor-tensin/setup-clang@ef434b41eb33a70396fb336b1bae39c76d740c3d # v1.4
20 | with:
21 | version: latest
22 | platform: x64
23 | - name: Install libc++-dev and libc++abi-dev
24 | run: sudo apt-get install libc++-dev libc++abi-dev -y
25 | - name: Build
26 | run: |
27 | . build.sh
28 | - name: Test
29 | run: |
30 | CTEST_OUTPUT_ON_FAILURE=1 BASE_PATH=${{ github.workspace }} ninja -C built/native/Debug test
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /tool/
2 | /lib/
3 | CMakeFiles
4 | /test/
5 | /ignore/
6 | .ninja_deps
7 | .ninja_log
8 | build.ninja
9 | CMakeCache.txt
10 | cmake_install.cmake
11 | /_deps/
12 | /bin/
13 | /built/
14 | node_modules/
15 | out/
16 | target/
17 | /web/dev/src/lib/
18 | *.wasm
19 | /web/public/script
20 | __pycache__/
21 | *.vsix
22 | /utils/
23 | bin/
24 | obj/
25 | testdata/
26 | *.profraw
27 | go_dump_env.bat
28 | /web/public/doc
29 | /web/public/example
30 | /web/doc/resources/_gen
31 | license_cache
32 | pkg/
33 | stats.json
34 | zig-cache/
35 | zig-out/
36 | rebrgen/
37 | wasmCopy.js
--------------------------------------------------------------------------------
/.licensed.yml:
--------------------------------------------------------------------------------
1 | name: "brgen" # デフォルトはsource_pathの名前
2 | source_path:
3 | - "./web/dev" # デフォルトはカレントディレクトリ
4 | - "./lsp"
5 | - "./lsp/server"
6 | - "./lsp/client"
7 | cache_path: "./license_cache" # source_pathからの相対パス。デフォルトは .licenses
8 |
9 | sources: # 今回はnpmを使います
10 | npm: true
11 |
12 | allowed: # 以下のライセンスならOKとします
13 | - mit
14 | - apache-2.0
15 | - isc
16 | - bsd-3-clause
17 | - cc-by-4.0
18 | - other
19 | - gpl-2.0
20 | - bsd-2-clause
21 | - 0bsd
22 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "includePath": [
6 | "${workspaceFolder}/src/**",
7 | "C:/workspace/utils_backup/src/include",
8 | "${workspaceFolder}/built/native/Debug/_deps/googletest-src/googletest/include",
9 | ],
10 | "defines": [
11 | "_DEBUG",
12 | "UNICODE",
13 | "_UNICODE"
14 | ],
15 | "windowsSdkVersion": "10.0.22000.0",
16 | "compilerPath": "C:/Program Files/LLVM/bin/clang++.exe",
17 | "cStandard": "c17",
18 | "cppStandard": "c++20",
19 | "intelliSenseMode": "windows-clang-x64"
20 | }
21 | ],
22 | "version": 4
23 | }
--------------------------------------------------------------------------------
/CONTRIBUTE.md:
--------------------------------------------------------------------------------
1 | # List of Contributors
2 |
3 | write GitHub account
4 |
5 | [on-keyday](https://github.com/on-keyday) - repository owner
6 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | #license
2 | FROM ubuntu:devel
3 |
4 | RUN mkdir -p /workspace
5 |
6 | WORKDIR /workspace
7 |
8 | # if you are not in Japan region, you should comment out this line, or change `ftp.jaist.ac.jp/pub/Linux` to your region millor server address.
9 | RUN sed -i 's@archive.ubuntu.com@ftp.jaist.ac.jp/pub/Linux@g' /etc/apt/sources.list
10 |
11 | RUN /bin/bash -c "$(curl -s https://apt.llvm.org/llvm.sh)"
12 |
13 |
14 |
15 | RUN apt-get update && \
16 | apt-get install -y\
17 | clang\
18 | libc++-dev\
19 | golang-go\
20 | lldb\
21 | liblldb-dev\
22 | lld\
23 | git\
24 | curl
25 |
26 |
27 | RUN apt-get update && \
28 | apt-get install -y\
29 | ninja-build\
30 | cmake
31 | RUN apt-get update && \
32 | apt-get install -y\
33 | vim
34 |
35 | # RUN ln -s /lib/llvm-15/bin/clang++ /bin/clang++
36 | # RUN ln -s /lib/llvm-15/bin/clang /bin/clang
37 | # RUN ln -s /bin/lldb-15 /bin/lldb
38 | RUN ln -s /usr/lib/x86_64-linux-gnu/libc++abi.so.1.0 /usr/lib/x86_64-linux-gnu/libc++abi.so
39 | RUN unlink /usr/bin/ld
40 | RUN ln -s /bin/lld /usr/bin/ld
41 | RUN ln -s /usr/bin/lldb-server-16 /usr/bin/lldb-server-16.0.6
42 |
43 | RUN apt-get update && \
44 | apt-get install -y\
45 | unzip
46 |
47 | RUN curl https://github.com/lldb-tools/lldb-mi/archive/refs/heads/main.zip \
48 | -o /workspace/lldb-mi.zip -L
49 |
50 |
51 | RUN unzip /workspace/lldb-mi.zip -d /workspace
52 | RUN rm /workspace/lldb-mi.zip
53 |
54 | RUN (cd /workspace/lldb-mi-main;cmake -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .)
55 | RUN (cd /workspace/lldb-mi-main;cmake --build .)
56 | RUN cp /workspace/lldb-mi-main/src/lldb-mi /bin/lldb-mi
57 |
58 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-2025 on-keyday (https://github.com/on-keyday)
4 | Copyright (c) 2024-2025 Contributors of brgen (https://github.com/on-keyday/brgen)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | 問題は基本的にはこのリポジトリの GitHub Issue で報告してください。
4 |
5 | セキュリティ脆弱性については
6 | GitHub Security Advisories の機能を使って報告してください。
7 |
8 | v0.0.x 及び main ブランチやその他のブランチの最新版についてはこのリポジトリの中身を使ったことによるセキュリティ脆弱性があったとしても
9 | 作者は責任を負いません。(ライセンスとしても一切保証はありません)
10 | また、可能な限り Issue に対しては応答するよう努めますが、確実な対応は保証できません。
11 |
12 | v0.1.0 以降では別途ポリシーを定める予定です。
13 |
14 | Please report issues primarily on the GitHub Issue of this repository.
15 |
16 | For security vulnerabilities, please report using the GitHub Security Advisories feature.
17 |
18 | The author bears no responsibility for any security vulnerabilities resulting from the use of the contents of this repository in v0.0.x, main branch, or any other branches' latest versions. (There is no guarantee whatsoever, even in terms of licensing).
19 | Furthermore, while efforts will be made to respond to issues, it cannot be guaranteed that responses will be provided promptly or reliably.
20 |
21 | Separate policies will be established for v0.1.0 and onwards.
22 |
--------------------------------------------------------------------------------
/arch.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | tool/brgen - code generator driver <- input is brgen.json
4 | |
5 | |--tool/src2json - parse source code then convert to json ast, dump type information of ast node, lexer etc...
6 | |
7 | |--tool/json2cpp - C++ code generator
8 | |
9 | |--tool/json2go - Go code generator
10 |
--------------------------------------------------------------------------------
/astlib/ast2c/test.c:
--------------------------------------------------------------------------------
1 | /*license*/
2 |
3 | #include "ast.h"
4 |
5 | int main(int argc, char *argv[]) {
6 | ast2c_json_handlers handlers;
7 | return 0;
8 | }
--------------------------------------------------------------------------------
/astlib/ast2csharp/ast2csharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/astlib/ast2go/generate_nix.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 |
3 | //go:generate ../tool/gen_ast2go ast/ast.go
4 | //go:generate gofmt -w ast/ast.go
5 | package ast2go
6 |
--------------------------------------------------------------------------------
/astlib/ast2go/generate_win.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 |
3 | //go:generate ../tool/gen_ast2go.exe ast/ast.go
4 | //go:generate gofmt -w ast/ast.go
5 | package ast2go
6 |
--------------------------------------------------------------------------------
/astlib/ast2go/request/exec.go:
--------------------------------------------------------------------------------
1 | package request
2 |
3 | import (
4 | "io"
5 | "os"
6 | "os/exec"
7 | )
8 |
9 | type ProcessClient struct {
10 | cmd *exec.Cmd
11 | SourceManager
12 | }
13 |
14 | // NewProcessClient creates a new process client
15 | // stdin and stdout are set to handle the communication
16 | // you should set stderr if you want to see the error
17 | func NewProcessClient(cmd *exec.Cmd) (*ProcessClient, error) {
18 | rp, ws, err := os.Pipe()
19 | if err != nil {
20 | return nil, err
21 | }
22 | rs, wp, err := os.Pipe()
23 | if err != nil {
24 | return nil, err
25 | }
26 | cmd.Stdin = rp
27 | cmd.Stdout = wp
28 | err = cmd.Start()
29 | if err != nil {
30 | return nil, err
31 | }
32 | c := NewRequestManager(rs, ws, func(err error) {
33 | if err != io.EOF {
34 | cmd.Process.Kill()
35 | }
36 | })
37 | go func() {
38 | err := cmd.Wait()
39 | c.CloseWithError(err)
40 | }()
41 | return &ProcessClient{
42 | cmd: cmd,
43 | SourceManager: c,
44 | }, nil
45 | }
46 |
--------------------------------------------------------------------------------
/astlib/ast2py/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/on-keyday/brgen/950489741469a370ab244f44f59ae6732914cb37/astlib/ast2py/__init__.py
--------------------------------------------------------------------------------
/astlib/ast2py/test.py:
--------------------------------------------------------------------------------
1 | import ast2py as ast
2 | import subprocess as sp
3 | import json
4 |
5 | if __name__ == "__main__":
6 | # execute tool/src2json(.exe) example/tree_test.bgn and get stdout
7 | # (stdout is json format)
8 | cmd = ["./tool/src2json.exe", "example/feature_test/tree_test.bgn"]
9 | proc = sp.Popen(cmd, stdout=sp.PIPE)
10 | stdout, stderr = proc.communicate()
11 | # create AstFile object
12 | d = json.loads(stdout.decode("utf-8"))
13 | file = ast.parse_AstFile(d)
14 | node = ast.ast2node(file.ast)
15 | assert isinstance(node, ast.Program)
16 |
17 | def walker(f, node):
18 | ast.walk(node, f)
19 | print(type(node))
20 |
21 | ast.walk(node, walker)
22 |
--------------------------------------------------------------------------------
/astlib/ast2rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 |
3 | members = [
4 | "core",
5 | "macros"
6 | ]
7 |
--------------------------------------------------------------------------------
/astlib/ast2rust/core/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "ast2rust"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | serde_json = "1.0.116"
10 | serde = "1.0.200"
11 | serde_derive = "1.0.200"
12 | bitflags = {version ="2.5.0",features=["serde"]}
13 | ast2rust_macro = {path = "../macros"}
14 |
15 | [features]
16 | default = ["std"]
17 | macros = []
18 | std = []
19 |
--------------------------------------------------------------------------------
/astlib/ast2rust/core/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | cell::RefCell,
3 | hash::{Hash, Hasher},
4 | rc::Rc,
5 | };
6 |
7 | pub mod ast;
8 | pub mod eval;
9 | mod test;
10 | pub mod traverse;
11 |
12 | #[derive(Debug)]
13 | pub enum PtrUnwrapError {
14 | ExpiredWeakPtr(&'static str),
15 | Nullptr(&'static str),
16 | }
17 |
18 | impl std::fmt::Display for PtrUnwrapError {
19 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
20 | match self {
21 | PtrUnwrapError::ExpiredWeakPtr(s) => write!(f, "expired weak ptr: {}", s),
22 | PtrUnwrapError::Nullptr(s) => write!(f, "nullptr: {}", s),
23 | }
24 | }
25 | }
26 |
27 | impl std::error::Error for PtrUnwrapError {}
28 |
29 | pub struct PtrKey {
30 | ptr: *const T,
31 | _phantom: std::marker::PhantomData,
32 | }
33 |
34 | impl PtrKey {
35 | pub fn new(ptr: &Rc>) -> Self {
36 | PtrKey {
37 | ptr: ptr.as_ptr() as *const T,
38 | _phantom: std::marker::PhantomData,
39 | }
40 | }
41 | }
42 |
43 | impl PartialEq for PtrKey {
44 | fn eq(&self, other: &Self) -> bool {
45 | std::ptr::eq(self.ptr, other.ptr)
46 | }
47 | }
48 |
49 | impl Eq for PtrKey {}
50 |
51 | impl Hash for PtrKey {
52 | fn hash(&self, state: &mut H) {
53 | self.ptr.hash(state);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/astlib/ast2rust/core/src/test.rs:
--------------------------------------------------------------------------------
1 | use std::{env, path};
2 |
3 | use crate::ast;
4 | use serde::Deserialize;
5 |
6 | pub fn exec_and_output(file: &str) -> std::io::Result {
7 | env::set_current_dir(path::Path::new("..")).unwrap();
8 | println!("current dir: {:?}", env::current_dir().unwrap());
9 | let cmd = env::current_dir()
10 | .unwrap()
11 | .join(path::Path::new("tool/src2json"));
12 | #[cfg(target_os = "windows")]
13 | let cmd = cmd.with_extension("exe");
14 | println!("cmd: {:?}", cmd);
15 | let mut cmd = std::process::Command::new(cmd);
16 | cmd.arg(file).output()
17 | }
18 |
19 | pub fn load_test_file() -> ast::Node {
20 | let ch = exec_and_output("./example/feature_test/tree_test.bgn").unwrap();
21 | let mut de = serde_json::Deserializer::from_slice(&ch.stdout);
22 | let file = ast::AstFile::deserialize(&mut de).unwrap();
23 | let prog = ast::parse_ast(file.ast.unwrap()).unwrap();
24 | prog.into()
25 | }
26 |
--------------------------------------------------------------------------------
/astlib/ast2rust/core/src/traverse.rs:
--------------------------------------------------------------------------------
1 | use super::ast;
2 | use std::ops::Fn;
3 |
4 | pub fn traverse(n: &ast::Node, f: &F)
5 | where
6 | F: Fn(&ast::Node) -> (),
7 | {
8 | ast::walk_node(n, &|s: &dyn ast::Visitor, n: &ast::Node| -> bool {
9 | ast::walk_node(n, s);
10 | f(n);
11 | true
12 | })
13 | }
14 |
15 | #[cfg(test)]
16 | mod tests {
17 |
18 | use super::super::ast;
19 | use super::super::test;
20 | use super::traverse;
21 |
22 | #[test]
23 | fn test_traverse() {
24 | let prog = test::load_test_file();
25 | traverse(&prog, &mut |n: &ast::Node| {
26 | let t: ast::NodeType = n.into();
27 | println!("node: {:?}", t);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/astlib/ast2rust/macros/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "ast2rust_macro"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | syn = "2.0"
10 | quote = "1.0"
11 | proc-macro2 = "1.0.86"
12 |
13 | [lib]
14 | proc-macro=true
15 |
16 | [features]
--------------------------------------------------------------------------------
/astlib/ast2ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ast2ts",
3 | "version": "0.0.1",
4 | "description": "brgen ast to typescript",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "tsc"
9 | },
10 | "author": "on-keyday (https://github.com/on-keyday)",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "@types/node": "^22.0.0",
14 | "ts-node": "^10.9.1",
15 | "typescript": "^5.2.2"
16 | },
17 | "dependencies": {
18 | "vscode-languageserver": "^9.0.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/astlib/ast2ts/src/index.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export {ast2ts} from "./ast";
4 | export {analyze} from "./analyze";
5 |
--------------------------------------------------------------------------------
/astlib/ast2ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "declaration": true,
6 | "outDir": "./out",
7 | "strict": true,
8 | "esModuleInterop": true
9 | },
10 | "include": [
11 | "."
12 | ]
13 | }
--------------------------------------------------------------------------------
/brgen.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.002.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ast2csharp", "ast2csharp\ast2csharp.csproj", "{5A3E00B5-19F5-4261-BBE8-9FD96BBE815B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {5A3E00B5-19F5-4261-BBE8-9FD96BBE815B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {5A3E00B5-19F5-4261-BBE8-9FD96BBE815B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {5A3E00B5-19F5-4261-BBE8-9FD96BBE815B}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {5A3E00B5-19F5-4261-BBE8-9FD96BBE815B}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {73FF9147-74B4-40D7-A9E4-C1CDE14F69B1}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | set S2J_LIB=1
4 | set BRGEN_RUST_ENABLED=1
5 | set BUILD_MODE=%1
6 | set BUILD_TYPE=%2
7 | set FUTILS_DIR=%3
8 |
9 | if "%BUILD_MODE%" == "" (
10 | set BUILD_MODE=native
11 | )
12 | if "%FUTILS_DIR%" == "" (
13 | rem for developers
14 | set FUTILS_DIR=C:/workspace/utils_backup
15 | )
16 | if not exist %FUTILS_DIR% (
17 | call script\clone_utils.bat %BUILD_MODE% %BUILD_TYPE%
18 | set FUTILS_DIR=%CD%\utils
19 | )
20 |
21 | if "%BUILD_TYPE%" == "" (
22 | set BUILD_TYPE=Debug
23 | )
24 |
25 | if "%EMSDK_PATH%" == "" (
26 | set EMSDK_PATH=C:\workspace\emsdk\emsdk_env.bat
27 | )
28 |
29 | set INSTALL_PREFIX=.
30 | if "%BUILD_MODE%" == "native" (
31 | cmake -D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang -G Ninja -DCMAKE_INSTALL_PREFIX=%INSTALL_PREFIX% -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -S . -B ./built/%BUILD_MODE%/%BUILD_TYPE%
32 | ) else if "%BUILD_MODE%" == "wasm-em" (
33 | call %EMSDK_PATH%
34 | set GOOS=js
35 | set GOARCH=wasm
36 | call emcmake cmake -G Ninja -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_INSTALL_PREFIX=%INSTALL_PREFIX%/web/dev/src -S . -B ./built/%BUILD_MODE%/%BUILD_TYPE%
37 | ) else (
38 | echo "Invalid build mode: %BUILD_MODE%"
39 | exit 1
40 | )
41 | rem ninja -C ./built/%BUILD_MODE%/%BUILD_TYPE%
42 | ninja -C ./built/%BUILD_MODE%/%BUILD_TYPE% install
43 |
44 | if "%BUILD_MODE%" == "wasm-em" (
45 | rem cd ./src/tool/json2rust
46 | rem wasm-pack build --target web
47 | rem copy ..\..\..\LICENSE .\pkg\LICENSE
48 | rem cd ../../../
49 | python script/copy_bmgen_stub.py
50 | cd ./web/dev
51 | call tsc
52 | call webpack
53 | cd ../../
54 | python script/copy_example.py
55 | )
56 |
--------------------------------------------------------------------------------
/build_all.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | set BUILD_MODE_BASE=%1
4 | call build.bat native %BUILD_MODE_BASE%
5 | if not %errorlevel% == 0 goto :error
6 | go env > script/go_dump_env.bat
7 | call script\go_dump_env.bat
8 | set WASMEXEC_FILE=%GOROOT%\lib\wasm\wasm_exec.js
9 | call build.bat wasm-em %BUILD_MODE_BASE%
10 | if not %errorlevel% == 0 goto :error
11 | python script/generate.py
12 | if not %errorlevel% == 0 goto :error
13 | cd web/dev
14 | call webpack.cmd
15 | set LEV=%errorlevel%
16 | cd ../..
17 | rem if not %LEV% == 0 goto :error
18 | call script\install_lsp.bat
19 | :error
20 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | #license
2 | version: "3"
3 | services:
4 | brgen_linux:
5 | build: .
6 | container_name: brgen
7 | tty: true
8 | stdin_open: true
9 | volumes:
10 | - ./src:/workspace/src:cached
11 | - ./build.sh:/workspace/build.sh:cached
12 | - ./CMakeLists.txt:/workspace/CMakeLists.txt:cached
13 | - ./docker_vscode:/workspace/.vscode:cached
14 | - ./script:/workspace/script:cached
15 | - ./example:/workspace/example:cached
16 | - ./go.mod:/workspace/go.mod:cached
17 | - ./go.sum:/workspace/go.sum:cached
18 | - ./ast2go:/workspace/ast2go:cached
19 | - ./brgen.json:/workspace/brgen.json:cached
20 | - ./Dockerfile:/workspace/Dockerfile:cached
21 | - ./docker-compose.yml:/workspace/docker-compose.yml:cached
22 | - ./README.md:/workspace/README.md:cached
23 | - ./.devcontainer:/workspace/.devcontainer:cached
24 | cap_add:
25 | - SYS_PTRACE
26 | security_opt:
27 | - seccomp:unconfined
28 | ports:
29 | - "8090:8080"
30 |
31 | volumes:
32 | src:
33 |
--------------------------------------------------------------------------------
/docker_vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "includePath": [
6 | "${workspaceFolder}/**",
7 | "C:/workspace/utils_backup/src/include",
8 | "C:/workspace/shbrgen/brgen/build/_deps/googletest-src/googletest/include",
9 | "C:/workspace/llvm-project/clang/include"
10 | ],
11 | "defines": [
12 | "_DEBUG",
13 | "UNICODE",
14 | "_UNICODE"
15 | ],
16 | "windowsSdkVersion": "10.0.22000.0",
17 | "compilerPath": "C:/Program Files/LLVM/bin/clang++.exe",
18 | "cStandard": "c17",
19 | "cppStandard": "c++20",
20 | "intelliSenseMode": "windows-clang-x64"
21 | }
22 | ],
23 | "version": 4
24 | }
--------------------------------------------------------------------------------
/example/arp.bgn:
--------------------------------------------------------------------------------
1 |
2 | # ArpPacket
3 | # arp packet is used to resolve ip address to mac address
4 | # -------------
5 |
6 | enum Operation:
7 | :u16
8 | Request = 1
9 | Reply = 2
10 |
11 | format ArpPacket:
12 | hardware_type :u16
13 | protocol_type :u16
14 | hardware_len :u8
15 | protocol_len :u8
16 | operation :Operation
17 | operation == Operation.Request || operation == Operation.Reply
18 | source_hardware_address :[hardware_len]u8
19 | source_protocol_address :[protocol_len]u8
20 | target_hardware_address :[hardware_len]u8
21 | target_protocol_address :[protocol_len]u8
22 |
23 |
24 |
--------------------------------------------------------------------------------
/example/asn1.bgn:
--------------------------------------------------------------------------------
1 | enum Tag:
2 | :u8
3 | RESERVED
4 | BOOLEAN
5 | INTEGER
6 | BIT_STRING
7 | OCTET_STRING
8 | NULL
9 | OBJECT_IDENTIFIER
10 |
11 | # c ::=config.import("./arp.bgn")
12 |
13 |
14 | format Len:
15 | len :u64
16 |
17 | fn size() -> u8:
18 | if len < 0x80:
19 | return 1
20 | else:
21 | len_of_len := 0
22 | val := len
23 | for val > 0:
24 | len_of_len = len_of_len + 1
25 | val = val >> 8
26 | return len_of_len + 1
27 |
28 | fn encode():
29 | if len < 0x80:
30 | output.put(u8(len))
31 | return
32 | else:
33 | len_of_len := size() - 1
34 | output.put(u8(0x80 | len_of_len))
35 | for len_of_len > 0:
36 | output.put(u8(len >> (len_of_len - 1) * 8))
37 | len_of_len = len_of_len - 1
38 |
39 | fn decode():
40 | input.endian = config.endian.little
41 | val := input.get()
42 | if val < 0x80:
43 | len = val
44 | else:
45 | len_of_len := val & 0x7f
46 | len = 0
47 | for len_of_len > 0:
48 | len = len << 8
49 | v ::= input.get()
50 | len = len | u64(v)
51 | len_of_len = len_of_len - 1
52 |
53 | fn u64() -> u64: # cast operator
54 | return len
55 |
56 | format TLV: # tag length value
57 | tag: Tag
58 | len: Len
59 | value :[len.len]u8
60 |
61 | format Integer:
62 | tlv :TLV
63 | tlv.tag == Tag.INTEGER
64 |
65 |
66 |
--------------------------------------------------------------------------------
/example/ast_step/step1.bgn:
--------------------------------------------------------------------------------
1 | 0x100
--------------------------------------------------------------------------------
/example/ast_step/step2.bgn:
--------------------------------------------------------------------------------
1 | p := 200
2 | p&0xC0 >>
3 | 6
4 |
--------------------------------------------------------------------------------
/example/ast_step/step3.bgn:
--------------------------------------------------------------------------------
1 | value := if 1 == (0 == 1 ? 1 : if 1!=0:
2 | 30
3 | else:
4 | 40
5 | ):
6 | 3
7 | else:
8 | 4
9 |
10 | value = - 10
11 |
--------------------------------------------------------------------------------
/example/ast_step/step4.bgn:
--------------------------------------------------------------------------------
1 | config.debug = true
2 | for:
3 | if config.debug:
4 | trace()
5 | data = readfrom()
6 | input.buffer = data
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/ast_step/step5.bgn:
--------------------------------------------------------------------------------
1 | form :u1
2 | if form == 1:
3 | :LongPacket
4 | else:
5 | :ShortPacket
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ast_step/step6.bgn:
--------------------------------------------------------------------------------
1 | format LongPacket:
2 | fixed :u1
3 | long_packet_type :u2
4 | reserved :u2
5 | packet_number_length :u2
6 | version :u32
7 | dst_conn_id :ConnectionID()
8 | src_conn_id :ConnectionID()
9 |
10 |
--------------------------------------------------------------------------------
/example/ast_step/step7.bgn:
--------------------------------------------------------------------------------
1 |
2 | if input.remain < 9:
3 | val := input.get(u8)
4 |
5 |
--------------------------------------------------------------------------------
/example/ast_step/step8.bgn:
--------------------------------------------------------------------------------
1 |
2 | format Data:
3 | data1 :u32
4 | data2 :u32
5 | data3 :u64
6 |
7 | format Data2:
8 | data1 :u64
9 |
10 | format Data3:
11 | data1 :u15
12 | data2 :u49
13 |
14 | format QUICLongPacket:
15 | form :u1
16 | fixed :u1
17 | packet_type :u2
18 | reserved :u2
19 | packet_number_len:u2
20 | version :u32
21 |
--------------------------------------------------------------------------------
/example/ast_step/step9.bgn:
--------------------------------------------------------------------------------
1 | format Data:
2 | len :u8
3 | payload :[len]u8
4 |
5 | format 🎅サンタΑa:
6 | ..
7 |
8 | format A:
9 | cond :u8
10 | if cond == 8:
11 | a :u8
12 | else:
13 | b :u16
14 |
15 |
16 |
17 | format B:
18 | x :u8
19 |
20 | X ::= "dom dom"
21 |
--------------------------------------------------------------------------------
/example/att.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://techweb.rohm.co.jp/product/wireless/bluetooth/bluetooth-basic/3367/"
3 | input.bit_order = config.bit_order.lsb
4 |
5 |
6 | format ATT_PDU:
7 | method :u6
8 | command :u1
9 | authentication_signature :u1
10 | if authentication_signature == 0:
11 | parameter :[..]u8
12 | else:
13 | parameter :[..]u8
14 | signature :[12]u8
15 |
16 |
17 |
--------------------------------------------------------------------------------
/example/attestation_object.bgn:
--------------------------------------------------------------------------------
1 | cbor := config.import("cbor.bgn")
2 |
3 | format AuthFlags: # from msb
4 | ed :u1
5 | at :u1
6 | reserved1:u1(0)
7 | bs :u1
8 | be :u1
9 | uv :u1
10 | reserved2 :u1(0)
11 | up :u1
12 |
13 | format AuthenticatorData:
14 | rp_id_hash :[32]u8
15 | flags :AuthFlags
16 | counter :ub32
17 | if flags.at == 1:
18 | attested_credential_data :AuthenticatorDataAttestation
19 | if flags.ed == 1:
20 | extensions :[..]u8
21 |
22 | format AuthenticatorDataAttestation:
23 | aaguid :[16]u8
24 | credential_id_length :u16
25 | credential_id :[credential_id_length]u8
26 | credential_public_key :cbor.Value
27 |
--------------------------------------------------------------------------------
/example/ax25.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://www.tapr.org/pdf/AX25.2.2.pdf"
3 |
4 | state ProtocolState:
5 | is_16bit_addressing: bool
6 |
7 | s :ProtocolState
8 |
9 | format AX25Frame:
10 | begin_magic: "\x7e"
11 | if s.is_16bit_addressing:
12 | address :u16
13 | else:
14 | address :u8
15 | control :u8
16 | pid :u8
17 | data :[..]u8
18 | fcs :u16
19 | end_magic: "\x7e"
20 |
--------------------------------------------------------------------------------
/example/bmp.bgn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | format BMPHeader:
5 | bfType :ul16
6 | bfSize :ul32
7 | bfReserved1 :ul16
8 | bfReserved2 :ul16
9 | bfOffBits :ul32
10 | biSize :ul32
11 | biWidth :sl32
12 | biHeight :sl32
13 | biPlanes :ul16
14 | biBitCount :ul16
15 | biCompression :ul32
16 | biSizeImage :ul32
17 | biXPelsPerMeter :sl32
18 | biYPelsPerMeter :sl32
19 | biClrUsed :ul32
20 | biClrImportant :ul32
21 |
22 | format RGB:
23 | b :u8
24 | g :u8
25 | r :u8
26 |
27 | format BMP:
28 | header :BMPHeader
29 | data :[header.biSizeImage]u8
30 |
31 | state LineState:
32 | width :u32
33 | bitSize :u32
34 |
35 | line_state :LineState
36 |
37 | format SingleLine:
38 | inByte ::= line_state.width * line_state.bitSize / 8
39 | #delta ::= 4 - inByte % 4
40 | len ::= inByte + (4 - inByte % 4) % 4
41 | data :[len]u8
42 |
--------------------------------------------------------------------------------
/example/bmp.txt:
--------------------------------------------------------------------------------
1 | struct BMPHeader
2 | {
3 | uint16 bfType;
4 | uint32 bfSize;
5 | uint16 bfReserved1;
6 | uint16 bfReserved2;
7 | uint32 bfOffBits;
8 | uint32 biSize;
9 | int32 biWidth;
10 | int32 biHeight;
11 | uint16 biPlanes;
12 | uint16 biBitCount;
13 | uint32 biCompression;
14 | uint32 biSizeImage;
15 | int32 biXPelsPerMeter;
16 | int32 biYPelsPerMeter;
17 | uint32 biClrUsed;
18 | uint32 biClrImportant;
19 | };
--------------------------------------------------------------------------------
/example/brgen_help/game.bgn:
--------------------------------------------------------------------------------
1 |
2 | format FrameContainer:
3 | len :u32
4 | data :[len]u8
5 |
6 | enum GameType:
7 | :u8
8 | ID
9 | Move
10 |
11 | format GameFrame:
12 | type :GameType
13 | match type:
14 | GameType.ID => id :ID
15 | GameType.Move => move :MoveFrame
16 | .. => error("invalid GameType")
17 |
18 | format ID:
19 | id :[16]u8
20 |
21 | format LocationPath:
22 | world :ID
23 | region :ID
24 | area :ID
25 | field :ID
26 | position :Vector
27 |
28 | format Vector:
29 | x :f32
30 | y :f32
31 | z :f32
32 |
33 | format MoveFrame:
34 | position :Vector
35 | velocity :Vector
36 | acceleration :Vector
37 |
38 | format EventFlag:
39 | is_active :u1
40 | is_triggered :u1
41 | is_managed :u1
42 | reserved :u5(0)
--------------------------------------------------------------------------------
/example/brgen_help/key.bgn:
--------------------------------------------------------------------------------
1 | format KeyExchangeInfo:
2 | sign :[16]u8
3 | client_id :[16]u8
4 | salt :[3][32]u8
5 | public_key :ECDHMaterial
6 |
7 | enum ECDHParam:
8 | :u8
9 | curve25519 = 0
10 | curve448 = 1
11 | p256 = 2
12 | p384 = 3
13 | p521 = 4
14 |
15 | format ECDHMaterial:
16 | param :ECDHParam
17 | match param:
18 | ECDHParam.curve25519:
19 | material :[32]u8
20 | ECDHParam.curve448:
21 | material :[56]u8
22 | ECDHParam.p256:
23 | material :[64]u8
24 | ECDHParam.p384:
25 | material :[96]u8
26 | ECDHParam.p521:
27 | material :[132]u8
28 | .. => error("invalid ECDHParam")
29 |
--------------------------------------------------------------------------------
/example/brgen_help/lexer_enum.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.cpp.namespace = "brgen::lexer"
3 |
4 | enum Tag:
5 | indent
6 | space
7 | line
8 | punct
9 | int_literal
10 | bool_literal
11 | str_literal
12 | regex_literal
13 | char_literal
14 | keyword
15 | ident
16 | comment
17 | error
18 | unknown
19 | partial_str_literal
20 | partial_char_literal
21 | partial_regex_literal
22 |
23 |
--------------------------------------------------------------------------------
/example/brgen_help/segment_routing_header.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.rfc-editor.org/rfc/rfc8754"
2 |
3 |
4 | format RoutingHeader:
5 | next_header :u8
6 | hdr_ext_len :u8
7 | routing_type :u8
8 | segments_left :u8
9 | last_entry :u8
10 | flags :u8
11 | tag :u16
12 |
13 | format TLV:
14 | type :u8
15 | if type != 0:
16 | length :u8
17 | value :[length]u8
18 |
19 | format Routing:
20 | header :RoutingHeader
21 | match header.routing_type:
22 | 4:
23 | segments :[header.segments_left][16]u8
24 | ext_len ::= header.hdr_ext_len * 8
25 | segment_len ::= header.segments_left * 16
26 | ext_len > segment_len
27 | bytes_len ::= ext_len - segment_len
28 | tlv :[..]TLV(input =input.subrange(bytes_len))
29 |
--------------------------------------------------------------------------------
/example/brgen_help/ssa.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.cpp.namespace = "brgen::ssa"
3 | config.go.package = "ssa"
4 | config.word.map("Ssa","SSA")
5 |
6 | enum SsaOp:
7 | :u8
8 |
9 | # arithmetic operations
10 | ADD = 0
11 | SUB = 1
12 | MUL = 2
13 | DIV = 3
14 | MOD = 4
15 |
16 | # bitwise operations
17 | AND = 5
18 | OR = 6
19 | XOR = 7
20 | SHL = 8
21 | SHR = 9
22 |
23 | # comparison operations
24 | EQ = 10
25 | NE = 11
26 | LT = 12
27 | LE = 13
28 | GT = 14
29 | GE = 15
30 |
31 | # logical operations
32 | LAND = 16
33 | LOR = 17
34 |
35 | # unary operations
36 | NEG = 18
37 | NOT = 19
38 |
39 | # phi function
40 | PHI = 20
41 |
42 | # memory operations
43 | LOAD = 21
44 | STORE = 22
45 |
46 | # call/ret operations
47 | CALL = 23
48 | RET = 24
49 |
50 | # branch operations
51 | BR = 25 # unconditional branch
52 | BRC = 26 # conditional branch
53 |
54 | # meta operations
55 | BEGIN_BLOCK = 27
56 |
57 | # special operations
58 | NOP = 28
59 | ASSIGN = 29
60 |
61 | format VarInt:
62 | config.type = u64
63 | prefix :u2
64 | match prefix:
65 | 0 => value :u6
66 | 1 => value :u14
67 | 2 => value :u30
68 | 3 => value :u62
69 |
70 | fn u64() -> u64:
71 | return value
72 |
73 | format SSA:
74 | op :SsaOp
75 | arg_len :VarInt
76 | args :[arg_len]u8
77 |
78 | format SsaBlock:
79 | id :u32
80 | ssas :[..]SSA
81 |
--------------------------------------------------------------------------------
/example/can.bgn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | config.url = "https://www.keyence.co.jp/ss/products/recorder/lab/candata/mechanism.jsp"
5 | config.url = "https://sunnygiken.jp/product/can-fd-tool/about_canfd/"
6 | fn extendedDataLength(r :u4) -> u8:
7 | x ::= match r:
8 | 0 => 0
9 | 1 => 1
10 | 2 => 2
11 | 3 => 3
12 | 4 => 4
13 | 5 => 5
14 | 6 => 6
15 | 7 => 7
16 | 8 => 8
17 | 9 => 12
18 | 10 => 16
19 | 11 => 20
20 | 12 => 24
21 | 13 => 32
22 | 14 => 48
23 | 15 => 64
24 | return x
25 |
26 | format ControlField:
27 | ide :u1
28 | if ide == 1:
29 | id_ext :u18
30 | rtr_or_rss :u1
31 | reserved1 :u1
32 | fdf :u1
33 | if fdf == 1:
34 | reserved2 :u1
35 | brs :u1
36 | esi :u1
37 | dlc :u4
38 |
39 | format CANFrame:
40 | sof :u1
41 | id :u11
42 | rtr_or_srr_or_rss :u1
43 | control :ControlField
44 | len ::= control.fdf == 1 ? extendedDataLength(control.dlc) : (control.dlc >= 9 ? 8 : control.dlc)
45 | data :[len]u8
46 | if control.fdf == 1:
47 | stuff_count :u4
48 | crc :u15
49 | crc_delimiter :u1
50 | ack :u1
51 | ack_delimiter :u1
52 | eof :u7
53 | intermission :u3
54 |
55 |
56 |
--------------------------------------------------------------------------------
/example/capnproto.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://capnproto.org/encoding.html"
3 | input.endian = config.endian.little
4 | input.bit_order = config.bit_order.lsb
5 | # little endian and begin with lsb
6 |
7 | # for example, the following code
8 | #
9 | format StructPointer:
10 | config.type = u64
11 | magic :u2(0)
12 | offset :s30
13 | sizeOfDataInWord :u16
14 | sizeOfPointerInWord :u16
15 |
16 | enum SizeOfListElement:
17 | :u3
18 | void_ = 0
19 | bit = 1
20 | byte1 = 2
21 | byte2 = 3
22 | byte4 = 4
23 | byte8 = 5
24 | pointer8 = 6
25 | composite = 7
26 |
27 | format ListPointer:
28 | config.type = u64
29 | magic :u2(1)
30 | offset :u30
31 | sizeOfElement :SizeOfListElement
32 | # if sizeOfElemet == SizeOfListElement.composite
33 | # then sizeOfList is the word count in list
34 | # otehrwise element count
35 | sizeOfList :u29
36 |
37 |
38 | format InterSegmentPointer:
39 | config.type = u64
40 | magic :u2(2)
41 | padding2byte :u1
42 | offset :u29
43 | id :u32
44 |
45 | format Capabilities:
46 | config.type = u64
47 | magic :u2(3)
48 | reserved :u30(0)
49 | capabilityTable :u32
50 |
--------------------------------------------------------------------------------
/example/ccsds.bgn:
--------------------------------------------------------------------------------
1 |
2 | format CCSDS:
3 | version :u3
4 | type :u1
5 | packet_secondary_header_flag :u1
6 | application_process_id :u11
7 | group_flags :u2
8 | soruce_sequence_count :u14
9 | packet_data_length :u16
10 | packet_data :[packet_data_length]u8
11 |
--------------------------------------------------------------------------------
/example/chg.bgn:
--------------------------------------------------------------------------------
1 |
2 | format MonomakhSaprChg:
3 | title : [10]u8
4 | block :[..]Block
5 |
6 | format Block:
7 | title : [13]u8
8 | file_size :ul64
9 | data : [file_size]u8
10 |
11 |
--------------------------------------------------------------------------------
/example/cmsg.bgn:
--------------------------------------------------------------------------------
1 | config.cpp.namespace = "futils::fnet"
2 | format CMsg:
3 | len :ul64
4 | level :ul32
5 | type :ul32
6 | msg :[len]u8
7 |
--------------------------------------------------------------------------------
/example/core_can_proto.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://github.com/core-rocket/CCP"
2 |
3 |
4 | format Str:
5 | seconds :u16
6 | text :[6]u8
7 |
8 | format Int:
9 | milliseconds :u32
10 | value :u32
11 |
12 | format Float:
13 | milliseconds :u32
14 | value :f32
15 |
16 | format FastFloat:
17 | seconds :u16
18 | fp16 :[3]f16
19 |
--------------------------------------------------------------------------------
/example/dccp.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://en.wikipedia.org/wiki/Datagram_Congestion_Control_Protocol"
3 |
4 | format GenericHeader:
5 | srcPort :u16
6 | dstPort :u16
7 | dataOffset :u8
8 | ccVal :u4
9 | csCov :u4
10 | checksum :u16
11 | res :u3
12 | type :u4
13 | x :u1
14 | if x == 1:
15 | reserved :u8
16 | seqNum :u48
17 | else:
18 | seqNum :u24
19 |
--------------------------------------------------------------------------------
/example/dnssec.bgn:
--------------------------------------------------------------------------------
1 |
2 | dns ::= config.import("./dns.bgn")
3 |
4 | format DNSKeyRData:
5 | flags :u16
6 | protocol :u8
7 | algorithm :u8
8 | public_key :[..]u8
9 |
10 | format RRSIGRData:
11 | type_covered :u16
12 | algorithm :u8
13 | labels :u8
14 | original_ttl :u32
15 | signature_expiration :u32
16 | signature_inception :u32
17 | key_tag :u16
18 | signer_name :dns.DomainName
19 | signature :[..]u8
20 |
21 | # unsigned int
22 | # keytag (
23 | # unsigned char key[], /* the RDATA part of the DNSKEY RR */
24 | # unsigned int keysize /* the RDLENGTH */
25 | # )
26 | # {
27 | # unsigned long ac; /* assumed to be 32 bits or larger */
28 | # int i; /* loop index */
29 | #
30 | # for ( ac = 0, i = 0; i < keysize; ++i )
31 | # ac += (i & 1) ? key[i] : key[i] << 8;
32 | # ac += (ac >> 16) & 0xFFFF;
33 | # return ac & 0xFFFF;
34 | # }
35 |
36 | fn keytag(key: []u8) -> u16:
37 | ac := u32(0)
38 | for i in key.length:
39 | if i & 1 == 1:
40 | ac += u32(key[i])
41 | else:
42 | ac += u32(key[i]) << 8
43 | ac += (ac >> 16) & 0xFFFF
44 | return ac & 0xFFFF
45 |
--------------------------------------------------------------------------------
/example/ether.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.go.package = "ether"
3 |
4 | enum EtherType:
5 | :u16
6 | ipv4 = 0x0800
7 | arp = 0x0806
8 | vlan = 0x8100
9 | ipv6 = 0x86DD
10 | service_vlen = 0x88A8
11 | pppoe_discovery = 0x8863
12 | pppoe_session = 0x8864
13 |
14 | format OUI:
15 | high: u6
16 | local :u1
17 | multicast :u1
18 | low :[2]u8
19 |
20 | format MacAddress:
21 | oui :OUI
22 | nic :[3]u8
23 |
24 | format EthernetFrame:
25 | dstMac :[6]u8
26 | srcMac :[6]u8
27 | ether_type :u16
28 | if ether_type == u16(EtherType.vlan):
29 | vlan_tag :u16
30 | ether_type2 :u16
31 | elif ether_type == u16(EtherType.service_vlen):
32 | service_vlan_tag :u16
33 | dummy_ether_type :u16(u16(EtherType.vlan))
34 | vlan_tag :u16
35 | ether_type2 :u16
36 | len ::= available(ether_type2) ? ether_type2 : ether_type
37 | len <= 0x5dc || len >= 0x600
38 | if len >= 0x600:
39 | data :[..]u8
40 | else:
41 | # peek :u16(input.peek = true)
42 | data :[len]u8
43 |
44 | format PPPoE:
45 | version :u4(1)
46 | type :u4(1)
47 | code :u8
48 | session_id :u16
49 | len :u16
50 | data :[len]u8
51 |
--------------------------------------------------------------------------------
/example/etherip.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.rfc = "https://www.rfc-editor.org/rfc/rfc3378"
3 |
4 | format EtherIP:
5 | version :u3
6 | reserved :u13
7 |
--------------------------------------------------------------------------------
/example/feature_test/analyze_block_trait.bgn:
--------------------------------------------------------------------------------
1 |
2 | state S:
3 | is_ok :bool
4 | ok_bit :u1
5 | s :S
6 |
7 | format Nest:
8 | a :u32
9 |
10 | format None:
11 | ..
12 |
13 | format A:
14 | a :u1
15 | d :[a]u8
16 | if a == 1:
17 | q :[a]u8
18 | n :[22]u8
19 | if d.length > 0:
20 | if s.ok_bit != a:
21 | error("not output")
22 | s.ok_bit == 1
23 | v := input.get(u8)
24 | input.bit_order = v == 0 ? config.bit_order.lsb : config.bit_order.msb
25 | nest :Nest
26 |
27 | fn encode():
28 | input.bit_order = config.bit_order.msb
29 | val := input.get(<[32]u1>)
30 | result := <[]A>()
31 | result[result.length] = A()
32 | for v in val:
33 | ..
--------------------------------------------------------------------------------
/example/feature_test/assert_or_implicit_yeild.bgn:
--------------------------------------------------------------------------------
1 |
2 | format ImplicitYieldMatchPattern:
3 | type :u8
4 | len :u8
5 | data :[len]u8
6 | ok ::= match type: # match type is bool
7 | 0 => (data.length >= 10) # as boolean expression
8 | 1 => (data.length >= 20)
9 | .. => (data.length >= 30)
10 | ok == true
11 |
12 | format AssertMatchPattern:
13 | type :u8
14 | len :u8
15 | data :[len]u8
16 | match type: # match type is void
17 | 0 => data.length >= 10 # as assertion
18 | 1 => data.length >= 20
19 | .. => data.length >= 30
20 |
21 | format ImplicitYieldIfPattern:
22 | type :u8
23 | len :u8
24 | data :[len]u8
25 | ok ::= if type == 0: # if type is bool
26 | (data.length >= 10) # as boolean expression
27 | elif type == 1:
28 | (data.length >= 20)
29 | else:
30 | (data.length >= 30)
31 | ok == true
32 |
33 | format AssertIfPattern:
34 | type :u8
35 | len :u8
36 | data :[len]u8
37 | if type == 0: # if type is void
38 | data.length >= 10 # as assertion
39 | elif type == 1:
40 | data.length >= 20
41 | else:
42 | data.length >= 30
43 |
44 |
--------------------------------------------------------------------------------
/example/feature_test/bit_fields.bgn:
--------------------------------------------------------------------------------
1 |
2 | format BitFields:
3 | a :u1
4 | b :u2
5 | c :u3
6 | d :u4
7 | e :u5
8 | f :u6
9 | g :u7
10 | h :u8
11 | i :u9
12 | j :u10
13 | k :u11
14 | l :u12
15 | m :u13
16 | n :u14
17 | o :u15
18 |
19 | # flag value is 1, data value is 0x1234, opaque1 value is 0x2678
20 |
21 | # msb lsb
22 | # |0 |1 |2 |3
23 | # |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|
24 | # 0 1|0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0|1 0 0 1 1 0 0 1 1 1 1 0 0 0|
25 | # |f|data |opaque1 |
26 | format DefaultLayout:
27 | flag :u2
28 | data :u16
29 | opaque1 :u14
30 |
31 | # msb lsb
32 | # |0 |1 |2 |3
33 | # |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|
34 | # 1 0 0 0 0 1|0 1|0 0 0 0 1 1 0 0| |0 1
35 | # |
36 | format LSBProiorLayout:
37 | input.bit_order = config.bit_order.lsb
38 | flag :u2
39 | data :u30
40 | opaque1 :u32
41 |
--------------------------------------------------------------------------------
/example/feature_test/comma_match.bgn:
--------------------------------------------------------------------------------
1 |
2 | x := u1()
3 | match x:
4 | 0,1 => ..
5 |
6 | fn isHexDigit(c :u8) -> bool:
7 | return match c:
8 | '0'..='9','a'..='f','A'..='F' => true
9 | .. => false
10 |
11 |
--------------------------------------------------------------------------------
/example/feature_test/const_length.bgn:
--------------------------------------------------------------------------------
1 |
2 | format A:
3 | T ::=30
4 | val :[T+1]u8
5 |
--------------------------------------------------------------------------------
/example/feature_test/edge_case1.bgn:
--------------------------------------------------------------------------------
1 |
2 | format A:
3 | a :u8 b :u8
4 | b
5 | a
6 | b
7 |
--------------------------------------------------------------------------------
/example/feature_test/for_in.bgn:
--------------------------------------------------------------------------------
1 |
2 | for x in 10:
3 | y ::= x + 1
4 |
5 | for x in 1..10:
6 | y ::= x + 1
7 |
8 | for x in "HELLO":
9 | y ::= x + 1
10 |
11 | arr :[]u8
12 |
13 | for x in arr:
14 | x = 0
15 |
--------------------------------------------------------------------------------
/example/feature_test/import_and_use.bgn:
--------------------------------------------------------------------------------
1 |
2 | arp ::= config.import("../arp.bgn")
3 | ether ::=config.import("../ether.bgn")
4 | ip ::= config.import("../ip.bgn")
5 |
6 | format ArpProtocol:
7 | etherHeader :ether.EthernetFrame
8 | ipHeader :ip.IPv4Header
9 | arpHeader :arp.ArpPacket
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/feature_test/loop_ref.bgn:
--------------------------------------------------------------------------------
1 |
2 | format A:
3 | c :C
4 |
5 | format B:
6 | a :A
7 |
8 | format C:
9 | b :B
10 |
11 |
--------------------------------------------------------------------------------
/example/feature_test/nested_state.bgn:
--------------------------------------------------------------------------------
1 |
2 |
3 | state S:
4 | isA :bool
5 |
6 | sstate :S
7 |
8 | format A:
9 | len :u8
10 | if sstate.isA:
11 | a :u8
12 | else:
13 | b :u8
14 |
15 | format B:
16 | a :A
17 |
18 |
--------------------------------------------------------------------------------
/example/feature_test/regexp.bgn:
--------------------------------------------------------------------------------
1 |
2 | format RegExp:
3 | reg : /\s/(input.skip = true)
4 |
5 | r ::= /r/gi
6 |
7 | "a" == r
8 |
--------------------------------------------------------------------------------
/example/feature_test/simple_binary.bgn:
--------------------------------------------------------------------------------
1 | x := 1 + 1
2 | err := if true:
3 | 2
4 | else:
5 | 3
6 | n ::= 20
7 | V ::= if n < 10 && n > -10:
8 | 10 * n
9 | else:
10 | n / 2
11 |
12 | for i in 10:
13 | error("error!",i)
14 |
--------------------------------------------------------------------------------
/example/feature_test/sort_test.bgn:
--------------------------------------------------------------------------------
1 |
2 | format A:
3 | x :u8
4 | y :B
5 |
6 | format B:
7 | x :u8
8 | y :u8
9 | z :u8
10 |
11 | format G:
12 | d :D
13 |
14 | format D:
15 | d :B
16 | s :G
17 |
18 | format E:
19 | e :D
20 |
21 |
22 |
23 | config.test.sort.expect(B,A,D,G,E)
24 |
--------------------------------------------------------------------------------
/example/feature_test/state_variable.bgn:
--------------------------------------------------------------------------------
1 |
2 | state S:
3 | is_ok :bool
4 |
5 | s :S
6 | y :S
7 |
8 | format N:
9 | s.is_ok = true
10 |
11 | format X:
12 | if s.is_ok:
13 | a :u8
14 | else:
15 | if !s.is_ok:
16 | c :u8
17 | b :u8
18 | y.is_ok = true
19 | if y.is_ok:
20 | d :N
21 | v :N
22 | else:
23 | e :u8
--------------------------------------------------------------------------------
/example/feature_test/state_variable2.bgn:
--------------------------------------------------------------------------------
1 | state Condition:
2 | is_16bit :bool
3 |
4 | condition :Condition
5 |
6 | format Data:
7 | if condition.is_16bit:
8 | data :u16
9 | else:
10 | data :u32
--------------------------------------------------------------------------------
/example/feature_test/test_import.bgn:
--------------------------------------------------------------------------------
1 |
2 | format Import:
3 | x :u8
4 |
5 | a :u32
--------------------------------------------------------------------------------
/example/feature_test/trial_match.bgn:
--------------------------------------------------------------------------------
1 |
2 | match:
3 | .. => x :u8(0x90)
4 | .. => x :u8(0x80)
5 | .. => x :u8(0x81)
6 |
--------------------------------------------------------------------------------
/example/feature_test/union.bgn:
--------------------------------------------------------------------------------
1 | # this type is union of a,b,c and x
2 | format UnionSample:
3 | tag :u8
4 | match tag:
5 | 1 => a :u8
6 | 2 :
7 | b :u16
8 | 3 => c :u32
9 | .. => x :u64
10 |
11 | format UnionExample:
12 | size :u8
13 | match size:
14 | 1 => len :u8
15 | 2 => len :u16
16 | 4 => len :u32
17 | 8 => len :u64
18 | .. => error("invalid size")
19 | data :[len]u8
20 |
21 | # but actually, this type is become like this
22 | # struct { uint8_t tag; union { uint8_t a; uint16_t b; uint32_t c; uint64_t x; };
23 |
24 | enum EnumExample:
25 | A
26 | B
27 | C
28 | D
29 |
30 | format LEB128:
31 | value :u64
32 | fn encode():
33 | data := value
34 | # encode value to LEB128
35 | for data > 0:
36 | output.put(0x80 | (data & 0x7f))
37 | data = data >> 7
38 |
39 | fn decode():
40 | # decode LEB128 to value
41 | i := 0
42 | for value < 0x80:
43 | byte := input.get()
44 | value = value | u64(byte & 0x7f) << (i * 7)
45 | i = i + 1
46 |
47 | fn u64():
48 | return value
49 |
50 |
51 | format Magic:
52 | magic :"\xab\xcd\xef\x00"
53 |
54 | format FixedValue:
55 | fixed :u8(0x12)
56 |
--------------------------------------------------------------------------------
/example/feature_test/varint_test.bgn:
--------------------------------------------------------------------------------
1 |
2 | q ::= config.import("../quic_varint.bgn")
3 | format Length:
4 | indicator :u1
5 | match indicator:
6 | 0 => len :u7
7 | 1 => len :u31
8 |
9 | format TestVarint: # total 16 field
10 | field_1 :q.VarInt # 8-bit data
11 | field_2 :q.VarInt # 8-bit data
12 | field_3 :q.VarInt # 8-bit data
13 | field_4 :q.VarInt # 8-bit data
14 | field_5 :q.VarInt # 16-bit data
15 | field_6 :q.VarInt # 16-bit data
16 | field_7 :q.VarInt # 16-bit data
17 | field_8 :q.VarInt # 16-bit data
18 | field_9 :q.VarInt # 32-bit data
19 | field_10 :q.VarInt # 32-bit data
20 | field_11 :q.VarInt # 32-bit data
21 | field_12 :q.VarInt # 32-bit data
22 | field_13 :q.VarInt # 64-bit data
23 | field_14 :q.VarInt # 64-bit data
24 | field_15 :q.VarInt # 64-bit data
25 | field_16 :q.VarInt # 64-bit data
26 |
27 | field_17 :Length # 8-bit data
28 | field_18 :Length # 32-bit data
29 |
--------------------------------------------------------------------------------
/example/fido_u2f.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html"
3 |
4 | enum U2FCommand:
5 | :u8
6 | Register = 0x01
7 | Authenticate = 0x02
8 |
9 | format U2FMessage:
10 | type :U2FCommand
11 | if type == U2FCommand.Register:
12 | register :RegisterRequest
13 | else:
14 | authenticate :AuthenticateRequest
15 |
16 | format RegisterRequest:
17 | challenge :[32]u8
18 | application :[32]u8
19 |
20 | format AuthenticateRequest:
21 | challenge :[32]u8
22 | application :[32]u8
23 | key_handle_len :u8
24 | key_handle :[key_handle_len]u8
25 |
--------------------------------------------------------------------------------
/example/from_kaitai/btrfs_stream.bgn:
--------------------------------------------------------------------------------
1 |
2 | format SendStreamHeader:
3 | magic :"btrfs-stream\x00"
4 | version :ul32
5 |
6 | format TLV:
7 | type :ul16
8 | length :ul16
9 | value :[length]u8
10 |
11 | format SendCommand:
12 | len :ul32
13 | type :ul16
14 | checksum :ul32
15 | data :[len]TLV
--------------------------------------------------------------------------------
/example/gen_step/step1.bgn:
--------------------------------------------------------------------------------
1 | # step 1 - can generate set of fundamental types
2 | format Step1:
3 | hello :u8
4 | world :u16
5 | is :u32
6 | cheap :u64
7 |
--------------------------------------------------------------------------------
/example/gen_step/step2.bgn:
--------------------------------------------------------------------------------
1 | # step2 - fixed array of fundamental types
2 | format Step2:
3 | hello :[16]u8
4 | world :[8]u16
5 | is :[4]u32
6 | cheap :[2]u64
7 |
--------------------------------------------------------------------------------
/example/gen_step/step3.bgn:
--------------------------------------------------------------------------------
1 | # step3 - dynamic length byte array
2 | format Step3:
3 | len :u8
4 | data :[len]u8
5 |
--------------------------------------------------------------------------------
/example/gen_step/step4.bgn:
--------------------------------------------------------------------------------
1 | # step4 - dynamic length byte array (length is used with operator)
2 | format Step4:
3 | len1 :u8
4 | data1 :[len1*2]u8
5 | len2 :u8
6 | data2 :[len2/2]u8
7 | len3 :u8
8 | data3 :[len3 << 2]u8
9 |
--------------------------------------------------------------------------------
/example/gen_step/step4_a.bgn:
--------------------------------------------------------------------------------
1 | # step4.a - dynamic length byte array (length is used with operator)
2 | config.cpp.vector_mode = "pointer"
3 | format Step4:
4 | len1 :u8
5 | data1 :[len1*2]u8
6 | len2 :u8
7 | data2 :[len2/2]u8
8 | true || false
9 |
--------------------------------------------------------------------------------
/example/gen_step/step4_b.bgn:
--------------------------------------------------------------------------------
1 | # step4.a - dynamic length byte array (length is used with operator)
2 | config.cpp.vector_mode = "pointer"
3 | # asymmetric length treatment
4 | # when decode, decode length as is
5 | # when encode, length is actual buffer length
6 | config.cpp.vector_pointer.asymmetric = true
7 | format Step4:
8 | len1 :u8
9 | data1 :[len1*2]u8
10 | len2 :u8
11 | data2 :[len2/2]u8
12 |
--------------------------------------------------------------------------------
/example/gen_step/step5.bgn:
--------------------------------------------------------------------------------
1 | # step5 - bit field
2 | format Step5:
3 | reserved: u1
4 | code :u2
5 | offset :u1
6 | len :u4
7 |
--------------------------------------------------------------------------------
/example/gen_step/step6.bgn:
--------------------------------------------------------------------------------
1 |
2 | # step6 - bit field (with length)
3 | format Step6:
4 | reserved: u1
5 | code :u2
6 | offset :u1
7 | len :u4
8 | data :[len]u8
9 |
--------------------------------------------------------------------------------
/example/gen_step/step7.bgn:
--------------------------------------------------------------------------------
1 | format Step7:
2 | len :u8
3 | match len:
4 | 0 => value :u8
5 | 1 => value :u16
6 | 2 => value :u32
7 | 3 => value :u64
8 |
--------------------------------------------------------------------------------
/example/gif.bgn:
--------------------------------------------------------------------------------
1 |
2 | format GifHeader:
3 | gif :"GIF"
4 | version :[3]u8
5 |
6 | format LogicalScreen:
7 | width :ul16
8 | height :ul16
9 | flags :u8
10 | backgroundColorIndex :u8
11 | pixelAspectRatio :u8
12 |
13 | format Gif:
14 | header :GifHeader
15 | logicalScreen :LogicalScreen
16 | globalColorTable :[256]ColorTable
17 | blocks :[..]Block
18 | :";"
19 |
20 | format ColorTable:
21 | colors :[3]u8
22 |
23 | format Block:
24 | blockType :u8
25 | data :[..]u8
26 |
27 | format ImageDescriptor:
28 | left :ul16
29 | top :ul16
30 | width :ul16
31 | height :ul16
32 | flags :u8
33 |
--------------------------------------------------------------------------------
/example/gzip.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.rfc-editor.org/rfc/rfc1952"
2 | input.endian = config.endian.little
3 | input.bit_order = config.bit_order.lsb
4 |
5 | format GZipHeader:
6 | magic :"\x1f\x8b"
7 | method :CompressionMethod
8 | flags :GZipFlag
9 | mtime :u32
10 | xfl :u8
11 | os :OS
12 | if flags.extra ==1:
13 | extra :GZipExtra
14 | if flags.fname ==1:
15 | fname :CString
16 | if flags.fcomment ==1:
17 | fcomment :CString
18 | if flags.crc ==1:
19 | crc16 :u16
20 |
21 | format GZipExtra:
22 | xlen :u16
23 | data :[xlen]u8
24 |
25 | format CString:
26 | data :[..]u8
27 | :"\x00"
28 |
29 | format GZipFlag:
30 | text :u1
31 | crc :u1
32 | extra :u1
33 | fname :u1
34 | fcomment :u1
35 | reserved :u3
36 | reserved == 0
37 |
38 | enum CompressionMethod:
39 | :u8
40 | deflate = 8
41 |
42 | enum OS:
43 | :u8
44 | fat = 0
45 | amiga = 1
46 | vms = 2
47 | unix_ = 3
48 | vm_cms = 4
49 | atari = 5
50 | hpfs = 6
51 | machintosh = 7
52 | z_system = 8
53 | cp_m = 9
54 | tops_20 = 10
55 | ntfs = 11
56 | qdos = 12
57 | acorn_risc_os = 13
58 | vfat = 14
59 | mvs = 15
60 | beos = 16
61 |
--------------------------------------------------------------------------------
/example/hci.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.wdic.org/w/WDIC/HCI%20%28Bluetooth%29"
2 | config.url = "https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=521059"
3 | input.endian = config.endian.little
4 | input.bit_order = config.bit_order.msb
5 |
6 | format HCIHeader:
7 | indicator :u8
8 |
9 | format HCICommand:
10 | opcode_group_field :u6
11 | opcode_command_field :u10
12 | length :u8
13 | parameters :[length]u8
14 |
15 | format ACLData:
16 | conn_handle :u12
17 | packet_boundary :u2
18 | broadcast :u2
19 | length :u8
20 | data :[length]u8
21 |
22 | format HCIEvent:
23 | event_code :u16
--------------------------------------------------------------------------------
/example/http.bgn:
--------------------------------------------------------------------------------
1 |
2 | format RequestLine:
3 | method :[..]u8
4 | :" "
5 | path :[..]u8
6 | :" "
7 | version :[..]u8
8 | :"\r\n"
9 |
10 | format ResponseLine:
11 | version :[..]u8
12 | :" "
13 | status :[..]u8
14 | :" "
15 | reason :[..]u8
16 | :"\r\n"
17 |
18 | format Field:
19 | name :[..]u8
20 | :": "
21 | value :[..]u8
22 | :"\r\n"
23 |
24 | format RequestHeader:
25 | line :RequestLine
26 | fields :[..]Field
27 | :"\r\n"
28 |
29 | format ResponseHeader:
30 | line :ResponseLine
31 | fields :[..]Field
32 | :"\r\n"
33 |
--------------------------------------------------------------------------------
/example/icn.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://datatracker.ietf.org/doc/rfc8609/"
2 | enum TLVType:
3 | T_ORG
4 |
5 | format TLV:
6 | type :u16
7 | length :u16
8 | data :[length]u8
9 |
10 | enum PacketType:
11 | :u8
12 | Interest = 0x00
13 | Content = 0x01
14 | Return = 0x02
15 |
16 | enum ReturnCode:
17 | :u8
18 | NoRoute = 0x01
19 | LimitExceeded = 0x02
20 | NoResources = 0x03
21 | PathError = 0x04
22 | ReturnProhibited = 0x05
23 | Congested = 0x06
24 | ReturnMtuTooLarge = 0x07
25 | ReturnUnsupportedHashRestriction = 0x08
26 | MalformedInterest = 0x09
27 |
28 | format CCNxPacketHeader:
29 | version :u8
30 | packet_type :PacketType
31 | packet_length :u16
32 | packet_specific :u24
33 | header_length :u8
34 |
35 | format CCNxPacket:
36 | header :CCNxPacketHeader
37 | header.packet_length >= u16(header.header_length)
38 | header_tlvs :[..]TLV(input = input.subrange(header.header_length))
39 | payload_tlvs :[..]TLV(input = input.subrange(header.packet_length - header.header_length))
40 |
--------------------------------------------------------------------------------
/example/ico.bgn:
--------------------------------------------------------------------------------
1 | config.url ="https://en.wikipedia.org/wiki/ICO_(file_format)"
2 | input.endian = config.endian.little
3 |
4 | enum Type:
5 | :u16
6 | ICON = 1
7 | CURSOR = 2
8 |
9 | format ICONDir:
10 | reserved :u16(0)
11 | type :Type
12 | count :u16
13 |
14 | format ICONDirEntry:
15 | width :u8
16 | height :u8
17 | colors :u8
18 | reserved :u8
19 | planes :u16
20 | bitcount :u16
21 | size :u32
22 | offset :u32
23 |
24 | format ICOHeader:
25 | dir :ICONDir
26 | entries : [dir.count]ICONDirEntry
27 |
--------------------------------------------------------------------------------
/example/ieee802_11.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.n-study.com/wlan-detail/802-11-frame-type-subtype/"
2 | enum FrameType:
3 | :u2
4 | Management = 0
5 | Control = 1
6 | Data = 2
7 | Extension = 3
8 |
9 |
10 | format FrameControl: # msb to lsb
11 | protocol_version :u2
12 | frame_type: FrameType
13 | sub_type: u4
14 | to_ds: u1
15 | from_ds: u1
16 | more_frag: u1
17 | retry: u1
18 | power_mgmt: u1
19 | more_data: u1
20 | protected_frame: u1
21 | order: u1
22 |
23 | format IEEE802_11:
24 | frame_control: FrameControl
25 | duration_id: u16
26 | addr1 : [6]u8
27 | addr2 : [6]u8
28 | addr3 : [6]u8
29 | sequence_control: u16
30 | addr4 : [6]u8
31 | payload: [..]u8
32 |
33 | format IEEE802_11FCS:
34 | frame_control: u16
35 | duration_id: u16
36 | addr1 : [6]u8
37 | addr2 : [6]u8
38 | addr3 : [6]u8
39 | sequence_control: u16
40 | addr4 : [6]u8
41 | payload: [..]u8
42 | fcs: u32
43 |
--------------------------------------------------------------------------------
/example/ietf_hackathon/bgp_ls.bgn:
--------------------------------------------------------------------------------
1 |
2 | format ServiceChaining:
3 | type :u16
4 | length :u16
5 | service_type :u16
6 | flags :u8
7 | traffic_type :u8
8 | reserved :u16
9 |
10 | format OpaqueMetadata:
11 | type :u16
12 | length :u16
13 | opaque_type :u16
14 | flags :u8
15 | data :[length * 8 + 1]u8
16 |
--------------------------------------------------------------------------------
/example/ietf_hackathon/initial_registory.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.rfc-editor.org/rfc/rfc8986#name-initial-registrations"
2 |
3 | enum RegistrationProcedures:
4 | :u16
5 | reserved = 0x0
6 | first_come_first_served_begin = 0x1
7 | first_come_first_served_end = 0x7fff
8 | private_use_begin = 0x8000
9 | private_use_end = 0x87ff
10 | reserved2_begin = 0x8800
11 | reserved2_end = 0xfffe
12 | opaque = 0xffff
13 |
14 | enum EndpointBehavior:
15 | :u16
16 | reserved
17 | end
18 | end_with_psp
19 | end_with_usp
20 | end_with_psp_and_usp
21 | end_x
22 | end_x_with_psp
23 | end_x_with_usp
24 | end_x_with_psp_and_usp
25 | end_t
26 | end_t_with_psp
27 | end_t_with_usp
28 | end_t_with_psp_and_usp
29 | unassigned
30 | end_b6_encaps
31 | end_bm
32 | end_dx6
33 | end_dx4
34 | end_dt6
35 | end_dt4
36 | end_dt46
37 | end_dx2
38 | end_dx2v
39 | end_dx2u
40 | end_dx2m
41 | reserved2
42 | unassigned2
43 | end_b6_encaps_red
44 | end_with_usd
45 | end_with_psp_and_usd
46 | end_with_usp_and_usd
47 | end_x_with_usd
48 | end_x_with_psp_and_usd
49 | end_x_with_usp_and_usd
50 | end_x_with_psp_usp_and_usd
51 | end_t_with_psp_and_usd
52 | end_t_with_usp_and_usd
53 | end_t_with_psp_usp_and_usd
54 |
55 | sid_defined_in_rfc8754 = 0x7fff
56 | reserved_for_private_use_begin = 0x8000
57 | reserved_for_private_use_end = 0xfffe
58 | opaque = 0xffff
59 |
--------------------------------------------------------------------------------
/example/ietf_hackathon/sid.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.rfc-editor.org/rfc/rfc8986#name-sid-format"
2 | state Lengths:
3 | F :u16
4 | L :u16
5 | A :u16
6 |
7 | lengths :Lengths
8 |
9 | format SID: # msb to lsb
10 | lengths.L + lengths.F + lengths.A <= 128
11 | loc :[lengths.L]u1
12 | func :[lengths.F]u1
13 | args :[lengths.A]u1
14 | padding :[128 - lengths.L - lengths.F - lengths.A]u1
15 |
--------------------------------------------------------------------------------
/example/ike.bgn:
--------------------------------------------------------------------------------
1 |
2 | format IKEHeader:
3 | initiators_spi :u64
4 | responders_spi :u64
5 | next_payload :u8
6 | major_version :u4
7 | minor_version :u4
8 | exchange_type :u8
9 | reserved1 :u2
10 | response :u1
11 | version :u1
12 | initiator :u1
13 | reserved2 :u3
14 | message_id :u32
15 | length :u32
16 |
17 | format GenericPayloadHeader:
18 | next_payload :u8
19 | critical :u1
20 | reserved :u7
21 | payload_length :u16
22 |
23 | format GenericPayload:
24 | header :GenericPayloadHeader
25 | payload :[header.payload_length - 4]u8
26 |
--------------------------------------------------------------------------------
/example/il.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://doc.cat-v.org/plan_9/4th_edition/papers/il/"
3 |
4 | enum ILType:
5 | :u8
6 | sync = 0
7 | data = 1
8 | dataquery = 2
9 | ack = 3
10 | query = 4
11 | state_ = 5
12 | close = 6
13 |
14 | format InternetLinkHeader:
15 | checkSum :u16
16 | length :u16
17 | type :ILType
18 | special :u8
19 | srcPort :u16
20 | dstPort :u16
21 | seqNum :u32
22 | ackNum :u32
23 |
--------------------------------------------------------------------------------
/example/impromptu_app_protocol.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum AppProtocolStatus:
3 | :u8
4 | start = 0
5 | middle = 1
6 | end = 2
7 | once = 3
8 | control = 4
9 | fileWatch = 5
10 | fileRequestList = 6
11 | fileRequestWrite = 7
12 | fileRequestRead = 8
13 | fileAcceptWrite = 9
14 | fileAcceptRead = 10
15 | fileError = 11
16 |
17 | format AppProtocolHeader:
18 | id :u32
19 | status :AppProtocolStatus
20 | order :u32
21 |
22 | format AppProtocol:
23 | header :AppProtocolHeader
24 | data :[..]u8
25 |
26 |
--------------------------------------------------------------------------------
/example/ipsec.bgn:
--------------------------------------------------------------------------------
1 |
2 | format AuthenticationHeader:
3 | next_header :u8
4 | payload_length :u8
5 | reserved :u16
6 | security_parameters_index :u32
7 | sequence_number :u32
8 | len ::= (payload_length + 2) *
9 | 4 - # per RFC 4302, the length field is in 4-byte units
10 | 12 # length of fixed part of header
11 | integrity_check_value :[len]u8
12 |
13 | state SPIState:
14 | spi :u32
15 | integrity_check_value_length :u8
16 |
17 | spi_state :SPIState
18 | config.url = "https://www.rfc-editor.org/rfc/rfc4303"
19 | format EncapsulingSecurityPayload:
20 | security_parameters_index :u32
21 | sequence_number :u32
22 | offset ::= input.offset
23 | payload_and_padding :[..]u8
24 | pad_length :u8
25 | payload :[..]u8(input = input.subrange(payload_and_padding.length - pad_length,offset))
26 | next_header :u8
27 | integrity_check_value :[spi_state.integrity_check_value_length]u8
28 |
--------------------------------------------------------------------------------
/example/ipv6addr.bgn:
--------------------------------------------------------------------------------
1 |
2 | state PrefixInfo:
3 | global :u8
4 | subnet :u8
5 |
6 | pinfo :PrefixInfo
7 |
8 | # 2000::/3
9 | format GlobalUnicast:
10 | prefix :u3(1)
11 | global_routing_prefix :[pinfo.global]u1
12 | subnet :[pinfo.subnet]u1
13 | pinfo.global + pinfo.subnet <= 64
14 | interface_id :[125 - pinfo.global - pinfo.subnet]u1
15 |
16 | # fe80::/10
17 | format LinkLocalUnicast:
18 | prefix :u10(0x3fa)
19 | subnet :[54]u1
20 | interface_id :[64/8]u8
21 |
22 | # fc00::/7 || fd00::/8
23 | format UniqueLocalUnicast:
24 | prefix :u7(0x7e)
25 | local_subnet :u1
26 | globalID :[40/8]u8
27 | subnetID :[16/8]u8
28 | interface_id :[64]u1
29 |
30 | # ff00::/8
31 | format Multicast:
32 | prefix :u8(0xff)
33 | flags :u4
34 | scope :u4
35 | group_id :[14]u8
36 |
37 | # fe80::/10
38 | format SolicitedMulticast:
39 | prefix :u104(0xff0200000000000000000001)
40 | addr :[3]u8
41 |
42 | # ::1/128
43 | format Loopback:
44 | prefix :u128(0x1)
45 |
46 | # ::/128
47 | format Unspecified:
48 | prefix :u128(0x0)
49 |
50 | # ::ffff:0:0/96
51 | format IPv4Mapped:
52 | prefix :u96(0x0000000000ffff)
53 | addr :[4]u8
54 |
55 |
--------------------------------------------------------------------------------
/example/isis.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://datatracker.ietf.org/doc/html/rfc5307"
3 |
4 | enum ProtectionCapability:
5 | :u8
6 | extra_traffic = 0x01
7 | unidirectional = 0x02
8 | shared = 0x04
9 | dedicated_1_per_1 = 0x08
10 | dedicated_1_plus_1 = 0x10
11 | enhanced = 0x20
12 |
13 | format LinkProtectionType:
14 | protection_cap :u8
15 | reserved :u8
16 |
17 | enum SwitchingCapability:
18 | :u8
19 | psc_1 = 1
20 | psc_2 = 2
21 | psc_3 = 3
22 | psc_4 = 4
23 | l2_sc = 51
24 | tdm = 100 # time division multiplexing
25 | lsc = 150 # lambda switching
26 | fsc = 200 # fiber switching
27 |
28 |
29 | format InterfaceSwitchingCapabilityDescriptor:
30 | switch_cap :u8
31 | encoding :u8
32 | reserved :u16
33 | max_lsp_bandwidth_per_priority :[8]u32
34 | switching_capabilty_specific_info :[..]u8
35 |
36 | format SRLG:
37 | system_id :[6]u8
38 | pseudonode_num :u8
39 | flags :u8
40 | ipv4_interface_address :[4]u8
41 | ipv4_neighbor_address :[4]u8
42 | shared_risk_link_group_value :[..]u32
43 |
--------------------------------------------------------------------------------
/example/l2cap.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://www.wdic.org/w/WDIC/L2CAP"
2 | format L2CAP:
3 | length :u16
4 | channel_id :ChannelID
5 | payload :[length]u8
6 |
7 | enum ChannelID:
8 | :u16
9 | null = 0x0000
10 | l2cap_signaling = 0x0001
11 | connectionless = 0x0002
12 |
--------------------------------------------------------------------------------
/example/l2tp.bgn:
--------------------------------------------------------------------------------
1 |
2 | format L2TPHeader:
3 | type :u1
4 | has_len :u1
5 | reserved1 :u2
6 | has_seq :u1
7 | reserved2 :u1
8 | has_offset :u1
9 | priority :u1
10 | reserved3 :u4
11 | version :u4
12 |
13 | version == 2 || version == 3
14 | if version == 3:
15 | has_len == 1 && has_seq == 1 && has_offset == 0
16 |
17 | if has_len == 1:
18 | length :u16
19 |
20 | id :u32
21 | if has_seq == 1:
22 | ns :u16
23 | nr :u16
24 |
25 | if has_offset == 1:
26 | ofsset :u16
27 | padding :[ofsset]u8
28 |
29 | format AVP:
30 | mandatory :u1
31 | hidden :u1
32 | reserved :u4
33 | length :u10
34 | length >= 6
35 | vendor_id :u16
36 | type :u16
37 | value :[length - 6]u8
38 |
--------------------------------------------------------------------------------
/example/llama2.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://github.com/karpathy/llama2.c/blob/master/run.c"
3 | input.endian = config.endian.little
4 |
5 | format Llama2Tokenizer:
6 | max_token_length :u32
7 | vocabularies :[..]Vocabulary
8 |
9 | format Vocabulary:
10 | score: f32
11 | len :u32
12 | token :[len]u8
13 |
14 | format Llama2Config:
15 | dim :u32
16 | hidden_dim :u32
17 | num_layers :u32
18 | num_heads :u32
19 | num_kv_heads :u32
20 | shared_weights :u1
21 | vocab_size :u31
22 | seq_len :u32
23 |
24 | state Llama2State:
25 | conf :Llama2Config
26 |
27 | llama2_state :Llama2State
28 |
29 | format Llama2Weights:
30 | conf ::= llama2_state.conf
31 | head_size ::= conf.dim / conf.num_heads
32 | token_embedding_table :[conf.dim][conf.vocab_size]f32
33 | rms_att_weight :[conf.num_layers][conf.dim]f32
34 | wq :[conf.num_layers][conf.dim][conf.num_heads * head_size]f32
35 | wk :[conf.num_layers][conf.dim][conf.num_kv_heads * head_size]f32
36 | wv :[conf.num_layers][conf.dim][conf.num_kv_heads * head_size]f32
37 | wo :[conf.num_layers][conf.num_heads * head_size][conf.dim]f32
38 | rms_ffn_weight :[conf.num_layers][conf.dim]f32
39 | w1 :[conf.num_layers][conf.dim][conf.hidden_dim]f32
40 | w2 :[conf.num_layers][conf.hidden_dim][conf.dim]f32
41 | w3 :[conf.num_layers][conf.dim][conf.hidden_dim]f32
42 | rms_final_weight :[conf.dim]f32
43 | freq_cis_real :[conf.seq_len][head_size/2]f32
44 | freq_cis_imag :[conf.seq_len][head_size/2]f32
45 |
46 |
47 | format Llama2Model:
48 | conf :Llama2Config
49 | llama2_state.conf = conf
50 | weights :Llama2Weights
51 |
52 |
--------------------------------------------------------------------------------
/example/mach-o.bgn:
--------------------------------------------------------------------------------
1 |
2 | format MachOHeader:
3 | magic :u32(0xfeedface)
4 | cputype :u32
5 | cpusubtype :u32
6 | filetype :u32
7 | ncmds :u32
8 | sizeofcmds :u32
9 | flags :u32
10 | reserved :u32
11 |
12 | format LoadCommandHeader:
13 | cmd :u32
14 | cmdsize :u32
15 | data :[cmdsize - 8]u8
16 |
--------------------------------------------------------------------------------
/example/mp3.bgn:
--------------------------------------------------------------------------------
1 |
2 | format MP3Header:
3 | sync :u11
4 | version :u2
5 | layer :u2
6 | protection :u1
7 | bitrate :u4
8 | sampling_frequency :u2
9 | padding :u1
10 | private_ :u1
11 | mode :u2
12 | intensity_stereo :u1
13 | ms_stereo :u1
14 | copy_right :u1
15 | original :u1
16 | emphasis :u2
17 |
--------------------------------------------------------------------------------
/example/mp4.bgn:
--------------------------------------------------------------------------------
1 |
2 | format Box:
3 | size :u32
4 | type :[4]u8
5 | if size == 1:
6 | large_size :u64
7 |
8 | if type == "uuid":
9 | usertype :[16]u8
10 |
11 | if size == 0:
12 | data :[..]u8
13 | else:
14 | data :[size-8]u8
15 |
16 |
--------------------------------------------------------------------------------
/example/mpls.bgn:
--------------------------------------------------------------------------------
1 |
2 | format MPLS:
3 | label :u20
4 | tc :u3
5 | s :u1
6 | ttl :u8
7 |
--------------------------------------------------------------------------------
/example/mqtt.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum PacketType:
3 | :u4
4 | reserved
5 | connect
6 | connack
7 | publish
8 | puback
9 | pubrec
10 | pubrel
11 | pubcomp
12 | subscribe
13 | suback
14 | unsubscribe
15 | unsuback
16 | pingreq
17 | pingresp
18 | disconnect
19 | auth
20 |
21 | format FixedHeader:
22 | packet_type: PacketType
23 | if packet_type == PacketType.publish:
24 | dup : u1
25 | qos : u2
26 | retain : u1
27 | elif packet_type == PacketType.pubrel || packet_type == PacketType.unsubscribe:
28 | reserved :u4(0x2)
29 | else:
30 | reserved : u4(0x0)
31 | remaining_length : u8
32 |
33 |
34 | format MQTTPacket:
35 | header :FixedHeader
36 | input.remain == u64(header.remaining_length)
37 |
--------------------------------------------------------------------------------
/example/ntp.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum Leap:
3 | :u2
4 | NoWarning
5 | LastMinute61
6 | LastMinute59
7 | Unsyncronized
8 |
9 | enum Mode:
10 | :u3
11 | Reserved
12 | SymmetricActive
13 | SymmetricPassive
14 | Client
15 | Server
16 | Broadcast
17 | ReservedForNtpControlMessage
18 | ReservedForPrivateUse
19 |
20 | format ShortFormat:
21 | seconds :u16
22 | fraction :u16
23 |
24 | format Timestamp:
25 | seconds :u32
26 | fraction :u32
27 |
28 | format Extension:
29 | type :u16
30 | length :u16
31 | value :[length]u8
32 |
33 | format ReferenceID:
34 | id :[4]u8
35 |
36 | format Auth:
37 | key_id :u32
38 | digest :[..24]u8
39 |
40 | format NtpPacket:
41 | leap :Leap
42 | version :u3
43 | mode :Mode
44 | stratum :u8
45 | poll :u8
46 | precision :s8
47 | root_delay :ShortFormat
48 | root_dispersion :ShortFormat
49 | reference_id :ReferenceID
50 | reference_timestamp :Timestamp
51 | origin_timestamp :Timestamp
52 | receive_timestamp :Timestamp
53 | transmit_timestamp :Timestamp
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/example/pcap.bgn:
--------------------------------------------------------------------------------
1 |
2 | format PcapHeader:
3 | magic :u32
4 | magic == 0xa1b2c3d4 || magic == 0xa1b2cd34
5 | version_major :u16
6 | version_minor :u16
7 | thiszone :s32
8 | sigfigs :u32
9 | snaplen :u32
10 | network :u32
11 | if magic == 0xa1b2cd34:
12 | ifindex :u32
13 | protocol :u16
14 | pkt_type :u8
15 | pad :u8
16 |
17 | format PcapRecord:
18 | ts_sec :u32
19 | ts_usec :u32
20 | incl_len :u32
21 | orig_len :u32
22 | data :[incl_len]u8
23 |
24 |
--------------------------------------------------------------------------------
/example/pcapng.bgn:
--------------------------------------------------------------------------------
1 |
2 | format PcapNGBlock:
3 | block_type: u32
4 | block_total_length: u32
5 | block_body :[block_total_length -12]u8
6 | block_total_length2: u32
7 | block_total_length == block_total_length2
8 |
9 | format SectionHeaderBlock:
10 | byte_order_magic: u32(0x1A2B3C4D)
11 | major_version: u16
12 | minor_version: u16
13 | section_length: u64
14 | section_options: [section_length - 28]u8
15 |
16 | format EnhancedPacketBlock:
17 | interface_id: u32
18 | timestamp_high: u32
19 | timestamp_low: u32
20 | captured_packet_length: u32
21 | original_packet_length: u32
22 | packet_data: [captured_packet_length]u8
23 | options : [..]u8
24 |
25 | format InterfaceDescriptionBlock:
26 | link_type: u16
27 | reserved: u16
28 | snap_len: u32
29 | options: [..]u8
30 |
31 | format SimplePacketBlock:
32 | packet_len :u32
33 | packet_data: [packet_len]u8
34 | options : [..]u8
35 |
36 | format Record:
37 | record_type: u16
38 | record_length: u16
39 | record_data: [record_length]u8
40 |
41 | format NameResolutionBlock:
42 | record: [..]Record
43 | :"\x00"
44 | options : [..]u8
45 |
--------------------------------------------------------------------------------
/example/pcep.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://tex2e.github.io/rfc-translater/html/rfc5440.html#7-1--PCEP-TLV-Format"
2 |
3 | format CommonHeader:
4 | version :u3
5 | flags :u5
6 | message_type :u8
7 | message_length :u16
8 |
9 | format ObjectTLV:
10 | type :u16
11 | length :u16
12 | value :[length]u8
13 |
14 | format CommonObjectHeader:
15 | object_class :u8
16 | object_type :u4
17 | reserved :u2
18 | p :u1
19 | ignore :u1
20 | object_length :u16
21 |
22 | format PCEPOpen:
23 | version :u3
24 | flags :u5
25 | keep_alive :u8
26 | dead_timer :u8
27 | sid :u8
28 | object :[..]ObjectTLV
29 |
30 | format PCEPRequestParameters:
31 | flags :u26
32 | loose :u1 # O
33 | bidirectional :u1 # B
34 | re_optimization :u1 # R
35 | priority :u3
36 | request_id :u32
37 | tlvs :[..]ObjectTLV
38 |
39 | enum PCEPNatureOfIssue:
40 | :u8
41 | NoPath = 0
42 | PCEChainBroken = 1
43 |
44 | format PCEPNoPath:
45 | nature_of_issue :PCEPNatureOfIssue
46 |
--------------------------------------------------------------------------------
/example/pefile_map.json:
--------------------------------------------------------------------------------
1 | {
2 | "WORD": "u16",
3 | "LONG": "u32",
4 | "MAGIC_MZ": "\"Mz\"",
5 | "DWORD": "u32",
6 | "UINT16": "u16",
7 | "UINT32": "u32",
8 | "UINT64": "u64",
9 | "CHAR8": "u8",
10 | "UINT8": "u8",
11 | "uint8_t": "u8",
12 | "uint16_t": "u16",
13 | "uint32_t": "u32",
14 | "uint64_t": "u64",
15 | "uint48_t": "u48",
16 | "char16_t": "u16",
17 | "uint32": "u32",
18 | "uint64": "u64",
19 | "uint16": "u16",
20 | "uint8": "u8",
21 | "int32": "s32",
22 | "int64": "s64",
23 | "int16": "s16",
24 | "int8": "s8",
25 | "time_t": "u64",
26 | "size_t": "u32",
27 | "int": "u32",
28 | "char": "u8"
29 | }
--------------------------------------------------------------------------------
/example/ppp.bgn:
--------------------------------------------------------------------------------
1 |
2 | format PPP:
3 | flag :u8(0x7e)
4 | address :u8(0xff)
5 | control :u8(0x03)
6 | protocol :u16
7 | data :[..]u8
8 | checksum :u16
9 | flag2 :u8(0x7e)
10 |
11 | format LCP:
12 | code :u8
13 | identifier :u8
14 | length :u16
15 | data :LCPData
16 |
17 | format LCPData:
18 | type :u8
19 | length :u8
20 | data :[length]u8
21 |
22 | format IPCP:
23 | data :LCP
24 |
--------------------------------------------------------------------------------
/example/protobuf.bgn:
--------------------------------------------------------------------------------
1 |
2 | format Varint:
3 | value :u64
4 |
5 | fn decode():
6 | for:
7 | v := input.get()
8 | if v < 0x80:
9 | value = v
10 | return
11 | value = (value << 7) | u64(v & 0x7f)
12 |
13 |
14 | fn encode():
15 | for:
16 | v := u8(value & 0x7f)
17 | value = value >> 7
18 | if value == 0:
19 | output.put(v)
20 | return
21 | output.put(v | 0x80)
22 |
23 | enum WireType:
24 | Varint = 0
25 | Fixed64 = 1
26 | LengthDelimited = 2
27 | StartGroup = 3
28 | EndGroup = 4
29 | Fixed32 = 5
30 |
31 | format Field:
32 | id :Varint
33 | fn type() -> WireType:
34 | return WireType(id.value & 0x7)
35 | fn number() -> u64:
36 | return id.value >> 3
37 |
38 | match type():
39 | WireType.Varint => value :Varint
40 | WireType.Fixed64 => value :u64
41 | WireType.LengthDelimited:
42 | length :Varint
43 | value :[length]u8
44 | WireType.StartGroup => ..
45 | WireType.EndGroup => ..
46 | WireType.Fixed32 => value :u32
47 |
--------------------------------------------------------------------------------
/example/quic_transport_parameter.bgn:
--------------------------------------------------------------------------------
1 |
2 | qpkt ::= config.import("quic_varint.bgn")
3 |
4 | enum TransportParameterID:
5 | original_destination_connection_id = 0x0000
6 | max_idle_timeout = 0x0001
7 | stateless_reset_token = 0x0002
8 | max_packet_size = 0x0003
9 | initial_max_data = 0x0004
10 | initial_max_stream_data_bidi_local = 0x0005
11 | initial_max_stream_data_bidi_remote = 0x0006
12 | initial_max_stream_data_uni = 0x0007
13 | initial_max_streams_bidi = 0x0008
14 | initial_max_streams_uni = 0x0009
15 | ack_delay_exponent = 0x000a
16 | max_ack_delay = 0x000b
17 | disable_active_migration = 0x000c
18 | preferred_address = 0x000d
19 | active_connection_id_limit = 0x000e
20 | initial_source_connection_id = 0x000f
21 | retry_source_connection_id = 0x0010
22 | max_datagram_frame_size = 0x0011
23 |
24 |
25 | format TransportParameter:
26 | parameter_id: qpkt.VarInt
27 | length: qpkt.VarInt
28 | value: [length]qpkt.VarInt
29 |
--------------------------------------------------------------------------------
/example/quic_varint.bgn:
--------------------------------------------------------------------------------
1 |
2 | format VarInt:
3 | prefix :u2
4 | match prefix:
5 | 0 => value :u6
6 | 1 => value :u14
7 | 2 => value :u30
8 | 3 => value :u62
9 |
10 | fn u64() -> u64:
11 | return value
12 |
--------------------------------------------------------------------------------
/example/radius.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.url = "https://datatracker.ietf.org/doc/html/rfc8044"
3 |
4 | enum RadiusDataType:
5 | integer = 1
6 | enum_ = 2,"enum"
7 | time = 3
8 | text = 4
9 | string = 5
10 | concat = 6
11 | ifid = 7
12 | ipv4addr = 8
13 | ipv6addr = 9
14 | ipv6prefix = 10
15 | ipv4prefix = 11
16 | integer64 = 12
17 | tlv = 13
18 | vsa = 14
19 | extended = 15
20 | long_extended = 16
21 | evs = 17
22 |
23 |
24 |
25 | format Integer:
26 | value :u32
27 |
28 | format Enum:
29 | value :u32
--------------------------------------------------------------------------------
/example/rdp.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/5073f4ed-1e93-45e1-b039-6e30c385867c"
2 | input.endian = config.endian.little
3 |
4 | format ClientX224ConnectionRequest:
5 | tpktHeader :TPKTHeader
6 | x224Crq: X224Crq
7 | routing_token :LineEnded
8 | cookie :LineEnded
9 | rdp_neg_req :RDPNegReq
10 | if rdp_neg_req.flags.correlation_info_present == 1:
11 | rdp_correlation_info :RDPCorrelationInfo
12 |
13 |
14 | format LineEnded:
15 | data :[..]u8
16 | :"\r\n"
17 |
18 |
19 | format TPKTHeader:
20 | unknown :u32
21 |
22 | format X224Crq:
23 | data :[7]u8
24 |
25 | format RDPNegReq:
26 | type :u8(0x01)
27 | flags :RDPNegReqFlags
28 | length :u16
29 | requested_protocols :RDPNegReqRequestedProtocols
30 |
31 | enum RDPNegReqRequestedProtocols:
32 | :u32
33 | RDP = 0x00000000
34 | SSL = 0x00000001
35 | HYBRID = 0x00000002
36 | RDSTLS = 0x00000004
37 | HYBRIDEX = 0x00000008
38 | RDSAAD = 0x00000010
39 |
40 |
41 | format RDPNegReqFlags: # from lsb
42 | restricted_admin :u1
43 | restricted_authentication :u1
44 | correlation_info_present :u1
45 | reserved :u5
46 |
47 | format RDPCorrelationInfo:
48 | type :u8(0x06)
49 | flags :u8(0)
50 | length :u16(0x24)
51 | correlation_id :[16]u8
52 | reserved :[16]u8
53 |
54 | # TODO: add support for the other messages
--------------------------------------------------------------------------------
/example/rtp.bgn:
--------------------------------------------------------------------------------
1 |
2 | format RTPHeader:
3 | version :u2
4 | padding :u1
5 | extension :u1
6 | csrc_count :u4
7 | marker :u1
8 | payload_type :u7
9 | sequence_number :u16
10 | timestamp :u32
11 | ssrc :u32
12 | csrc_list :[csrc_count]u32
13 |
14 |
15 | format RTPExtensionHeader:
16 | profile :u16
17 | length :u16
18 | data :[length]u8
19 |
--------------------------------------------------------------------------------
/example/safetensor.bgn:
--------------------------------------------------------------------------------
1 |
2 | input.endian = config.endian.little
3 |
4 | config.url = "https://github.com/huggingface/safetensors/blob/main/safetensors/src/tensor.rs#L510"
5 |
6 | format SafeTensorHeader:
7 | header_len :ul64
8 | json_header :[header_len]u8
9 |
10 | format SafeTensor:
11 | header :SafeTensorHeader
12 | data :[..]u8
13 |
14 | # json serialized but this not supports json parsing
15 | state TensorInfo:
16 | dtype :DType
17 | shape :[]u64
18 | data_offset_begin :u64
19 | data_offset_end :u64
20 |
21 |
22 | fn getTensorSize(tensor: TensorInfo) -> u64:
23 | perElem := getByteSize(tensor.dtype)
24 | total := u64(1)
25 | for dim in tensor.shape:
26 | total *= dim
27 | return total * u64(perElem)
28 |
29 | enum DType:
30 | BOOL
31 | U8
32 | I8
33 | F8_E5M2
34 | F8_E4M3
35 | I16
36 | U16
37 | F16
38 | BF16
39 | I32
40 | U32
41 | F32
42 | F64
43 | I64
44 | U64
45 |
46 | fn getByteSize(dtype: DType) -> u8:
47 | return match dtype:
48 | DType.BOOL => 1
49 | DType.U8 => 1
50 | DType.I8 => 1
51 | DType.F8_E5M2 => 1
52 | DType.F8_E4M3 => 1
53 | DType.I16 => 2
54 | DType.U16 => 2
55 | DType.F16 => 2
56 | DType.BF16 => 2
57 | DType.I32 => 4
58 | DType.U32 => 4
59 | DType.F32 => 4
60 | DType.F64 => 8
61 | DType.I64 => 8
62 | DType.U64 => 8
63 |
64 |
--------------------------------------------------------------------------------
/example/simple.bgn:
--------------------------------------------------------------------------------
1 |
2 | format Data:
3 | data :[32]u8
4 |
--------------------------------------------------------------------------------
/example/srv6.bgn:
--------------------------------------------------------------------------------
1 | enum EndpointBehavior:
2 | :u16
3 | reserved
4 | end
5 | end_with_psp
6 | end_with_usp
7 | end_with_psp_and_usp
8 | end_x
9 | end_x_with_psp
10 | end_x_with_usp
11 | end_x_with_psp_and_usp
12 | end_t
13 | end_t_with_psp
14 | end_t_with_usp
15 | end_t_with_psp_and_usp
16 | unassigned
17 | end_b6_encaps
18 | end_bm
19 | end_dx6
20 | end_dx4
21 | end_dt6
22 | end_dt4
23 | end_dt46
24 | end_dx2
25 | end_dx2v
26 | end_dx2u
27 | end_dx2m
28 | reserved2
29 | unassigned2
30 | end_b6_encaps_red
31 | end_with_usd
32 | end_with_psp_and_usd
33 | end_with_usp_and_usd
34 | end_x_with_usd
35 | end_x_with_psp_and_usd
36 | end_x_with_usp_and_usd
37 | end_x_with_psp_usp_and_usd
38 | end_t_with_psp_and_usd
39 | end_t_with_usp_and_usd
40 | end_t_with_psp_usp_and_usd
41 |
42 | sid_defined_in_rfc8754 = 0x7fff
43 | reserved_for_private_use_begin = 0x8000
44 | reserved_for_private_use_end = 0xfffe
45 | opaque = 0xffff
--------------------------------------------------------------------------------
/example/stl.bgn:
--------------------------------------------------------------------------------
1 |
2 | format STL:
3 | header :[80]u8
4 | num_triangles :u32
5 | triangles :[num_triangles]Triangle
6 |
7 |
8 | format Triangle:
9 | normal :[3]f32
10 | vertices :[3]Vertex
11 | attr :u16
12 |
13 | format Vertex:
14 | x :f32
15 | y :f32
16 | z :f32
17 |
--------------------------------------------------------------------------------
/example/stp.bgn:
--------------------------------------------------------------------------------
1 | # spaning tree protocol
2 |
3 | format BridgeID:
4 | priority :u16
5 | mac :u48
6 |
7 | format BDPU:
8 | protocol_id :u16
9 | version :u8
10 | bpdu_type :u8
11 | flags :u8
12 | root_id :BridgeID
13 | root_path_cost :u32
14 | bridge_id :BridgeID
15 | port_id :u16
16 | message_age :u16
17 | max_age :u16
18 | hello_time :u16
19 | forward_delay :u16
20 |
--------------------------------------------------------------------------------
/example/stub.bgn:
--------------------------------------------------------------------------------
1 |
2 | format TEST_CLASS:
3 | data :[..]u8
4 |
--------------------------------------------------------------------------------
/example/stun.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum MessageType:
3 | :u16
4 | BindingRequest = 0x0001
5 | BindingResponse = 0x0101
6 | BindingErrorResponse = 0x0111
7 | SharedSecretRequest = 0x0002
8 | SharedSecretResponse = 0x0102
9 | SharedSecretErrorResponse = 0x0112
10 |
11 | enum StunAddrFamily:
12 | :u8
13 | IPv4 = 0x01
14 | IPv6 = 0x02
15 |
16 | format StunHeader:
17 | type :u16
18 | length :u16
19 | magic_cookie :u32(0x2112A442)
20 | transaction_id :[12]u8
21 |
22 | format Attribute:
23 | type :AttributeType
24 | length :u16
25 | value :[length]u8
26 |
27 | format MappedAddress:
28 | family :StunAddrFamily
29 | family == StunAddrFamily.IPv4 || family == StunAddrFamily.IPv6
30 | port :u16
31 | address :[family == StunAddrFamily.IPv4 ? 4: 16]u8
32 |
33 | format ChangeRequest:
34 | reserved1 :u29
35 | change_ip :u1
36 | change_port :u1
37 | reserved2 :u1
38 |
39 | format ErrorCode:
40 | reserved :u22
41 | class :u3
42 | number :u7
43 |
44 | enum AttributeType:
45 | :u16
46 | reserved = 0x0000
47 | mapped_address = 0x0001
48 | response_address = 0x0002
49 | change_request = 0x0003
50 | source_address = 0x0004
51 | changed_address = 0x0005
52 | user_name = 0x0006
53 | password = 0x0007
54 | message_integrity = 0x0008
55 | error_code = 0x0009
56 | unknown_attribute = 0x000a
57 | reflected_from = 0x000b
58 | realm = 0x0014
59 | nonce = 0x0015
60 | xor_mapped_address = 0x0020
61 |
--------------------------------------------------------------------------------
/example/swf_rect.bgn:
--------------------------------------------------------------------------------
1 |
2 | format SWFRect:
3 | len :u5 # maximum is 2^5-1 = 31
4 | x_min : [len]u1(config.type = u32)
5 | x_max : [len]u1(config.type = u32)
6 | y_min : [len]u1(config.type = u32)
7 | y_max : [len]u1(config.type = u32)
8 | padding :[(5 + len *4)%8]u1(input.align = 8) # padding to next byte
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/tar.bgn:
--------------------------------------------------------------------------------
1 |
2 | fn oct2int(oct :[]u8) -> u64:
3 | res := u64(0)
4 | for i := u64(0); i < oct.length; i = i + 1:
5 | oct[i] >= '0' && oct[i] <= '7'
6 | res = res * 8 + u64(oct[i] - u8('0'))
7 | return res
8 |
9 |
10 | format TarFile:
11 | name :[100]u8
12 | mode :[8]u8
13 | uid :[8]u8
14 | gid :[8]u8
15 | size :[12]u8
16 | mtime :[12]u8
17 | chksum :[8]u8
18 | type :u8
19 | linkname :[100]u8
20 | magic :"ustar\0"
21 | version :[2]u8
22 | uname :[32]u8
23 | gname :[32]u8
24 | devmajor :[8]u8
25 | devminor :[8]u8
26 | prefix :[155]u8
27 | padding :[12]u8
28 | len ::= oct2int(<[]u8>(size))
29 | data :[len]u8
30 |
--------------------------------------------------------------------------------
/example/tftp.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum OpCode:
3 | :u16
4 | RRQ = 1 # Read Request
5 | WRQ = 2 # Write Request
6 | DATA = 3 # Data
7 | ACK = 4 # Acknowledgment
8 | ERROR = 5 # Error
9 |
10 | format Packet:
11 | op :OpCode
12 | match op:
13 | OpCode.RRQ => rrq :Request
14 | OpCode.WRQ => wrq :Request
15 | OpCode.DATA => data :Data
16 | OpCode.ACK => ack :Ack
17 | OpCode.ERROR => error :Error
18 |
19 | format Request:
20 | fileName :[..]u8
21 | :"\0"
22 | mode :[..]u8
23 | :"\0"
24 |
25 | format Data:
26 | blockNumber :u16
27 | data :[..]u8
28 |
29 | format Ack:
30 | blockNumber :u16
31 |
32 | format Error:
33 | errorCode :u16
34 | errorMsg :[..]u8
35 | :"\0"
36 |
--------------------------------------------------------------------------------
/example/tor_prop220.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://gitlab.torproject.org/tpo/core/trunnel/-/blob/main/examples/prop220.trunnel?ref_type=heads"
2 | format TorEdCert:
3 | version :u8(1)
4 | cert_type :u8
5 | exp_field :u32
6 | cert_key_type :u8
7 | certified_key :[32]u8
8 | n_extensions :u8
9 | extensions :[n_extensions]TorEdCertExt
10 | signature :[64]u8
11 |
12 | CERTEXT_SIGNED_WITH_KEY ::= 4
13 |
14 | format TorEdCertExt:
15 | ext_len :u16
16 | ext_type :u8
17 | ext_flags :u8
18 | if ext_type == CERTEXT_SIGNED_WITH_KEY:
19 | signing_key :[32]u8
20 | else:
21 | ext_data :[ext_len]u8
22 |
23 | format CertRevocation:
24 | prefix :[8]u8
25 | version :u8(1)
26 | key_type :u8
27 | identity_key :[32]u8
28 | revoked_key :[32]u8
29 | published_time :u64
30 | n_extensions :u8
31 | extensions :[n_extensions]TorEdCertExt
32 | signature :[64]u8
33 |
34 | format CrossCertEdRSA:
35 | ed_key :[32]u8
36 | expiring_date :u32
37 | signature :[64]u8
38 |
39 | enum LinkSpecifierType:
40 | :u8
41 | IPv4 = 0x00
42 | IPv6 = 0x01
43 | LEGACY_ID = 0x02
44 | ED25519_ID = 0x03
45 |
46 | format LinkSpecifier:
47 | type :LinkSpecifierType
48 | len :u8
49 | if type == LinkSpecifierType.IPv4:
50 | ipv4 :[4]u8
51 | port :u16
52 | elif type == LinkSpecifierType.IPv6:
53 | ipv6 :[16]u8
54 | port :u16
55 | elif type == LinkSpecifierType.LEGACY_ID:
56 | legacy_id :[20]u8
57 | elif type == LinkSpecifierType.ED25519_ID:
58 | ed25519_id :[32]u8
59 |
--------------------------------------------------------------------------------
/example/tor_rend.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://gitlab.torproject.org/tpo/core/trunnel/-/blob/main/examples/tor-rend.trunnel?ref_type=heads"
2 |
3 |
4 | format EstablishIntroBody:
5 | key_len :u16
6 | key :[key_len]u8
7 | session_hash :[20]u8
8 | signature :[..]u8
9 |
10 | format IntroducelCell:
11 | pk_id :u8
12 | encrypted_part :[..]u8
13 |
14 | format IntroducelCellPlainText:
15 | version :u8
16 | match version:
17 | 1 => v1 :IntroducelCellBodyV1
18 | 2 => v2 :IntroducelCellBodyV2
19 | 3 => v3 :IntroducelCellBodyV3
20 | 4..=32 => error("invalid version")
21 | .. => v0 :IntroducelCellBodyV0
22 |
23 | format IntroducelCellBodyV0:
24 | rest_of_nickname :[19]u8
25 | rc :[20]u8
26 | dh_data :[128]u8
27 |
28 | format IntroducelCellBodyV1:
29 | rp_id :[42]u8
30 | rc :[20]u8
31 | dh_data :[128]u8
32 |
33 | format IntroducelCellBodyV2:
34 | rp_ip :u32
35 | rp_port :u16
36 | rp_id :[20]u8
37 | klen :u16
38 | onion_key :[klen]u8
39 | rc :[20]u8
40 | dh_data :[128]u8
41 |
42 | format IntroducelCellBodyV3:
43 | auth_type :u8
44 | if auth_type != 0:
45 | auth_len :u16
46 | auth_data :[auth_len]u8
47 | timestamp :u32
48 | rp_ip :u32
49 | rp_port :u16
50 | rp_id :[20]u8
51 | klen :u16
52 | onion_key :[klen]u8
53 | rc :[20]u8
54 | dh_data :[128]u8
55 |
56 | format Rendezvous1CellBody:
57 | rc :[20]u8
58 | dh :[128]u8
59 | kh :[20]u8
60 |
61 | format Rendezvous2CellBody:
62 | dh :[128]u8
63 | kh :[20]u8
64 |
--------------------------------------------------------------------------------
/example/tzdb.bgn:
--------------------------------------------------------------------------------
1 |
2 | format TZHeader:
3 | tzMagic: "TZif"
4 | tzVersion: u8
5 | tzReserved: [15]u8
6 | tzTimeIsUTCCount: u32
7 | tzTimeIsStdCount: u32
8 | tzTimeLeapCount: u32
9 | tzTimeCount :u32
10 | tzTypeCount: u32
11 | tzCharCount: u32
12 |
13 | format TZTime:
14 | tzTime: u32
15 |
16 | format TZType:
17 | tzGmtOffset: u32
18 | tzIsDst: u8
19 | tzAbbrIndex: u8
20 |
21 | format TZChar:
22 | tzChar: [..]u8
23 | :"\0"
24 |
25 | format TZLeap:
26 | tzLeapTime: u32
27 | tzLeapGmtOffset: u32
28 |
29 |
--------------------------------------------------------------------------------
/example/udp.bgn:
--------------------------------------------------------------------------------
1 |
2 |
3 | format UDPHeader:
4 | config.rfc = "https://datatracker.ietf.org/doc/html/rfc768"
5 | src_port :u16
6 | dst_port :u16
7 | length :u16
8 | checksum :u16
9 |
10 | format UDPDatagram:
11 | header :UDPHeader
12 | data :[header.length-8]u8
13 |
14 |
--------------------------------------------------------------------------------
/example/usb.bgn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | format USBPacket:
5 | sync :u8
6 | pid :u4
7 | pid_reverse :u4
8 | !pid == pid_reverse
9 | match pid:
10 | 0b0001 => data :StartOfFrame
11 |
12 |
13 | format StartOfFrame:
14 | frame :u11
15 | crc :u5
16 |
17 | format TokenPacket:
18 | addr :u7
19 | endp :u4
20 | crc :u5
21 |
--------------------------------------------------------------------------------
/example/vm_test/udp_test.bgn:
--------------------------------------------------------------------------------
1 |
2 | udp ::= config.import("../udp.bgn")
3 | quic ::= config.import("../quic_packet.bgn")
4 | varint ::= config.import("../quic_varint.bgn")
5 |
6 | format Test:
7 | quic.qstate.encrypted = true
8 | # UDP Header (rfc 768)
9 | udpHeader :udp.UDPHeader
10 | quicPacket :quic.QUICPackets(input = input.subrange(udpHeader.length - 8))
11 |
12 | format Test2:
13 | v1 :varint.VarInt
14 | v2 :varint.VarInt
15 | v3 :varint.VarInt
16 | v4 :varint.VarInt
17 | input.remain == 0
18 |
--------------------------------------------------------------------------------
/example/vrrp.bgn:
--------------------------------------------------------------------------------
1 | config.url = "https://tex2e.github.io/rfc-translater/html/rfc9568.html#5-1--VRRP-Packet-Format"
2 | format VRRPPacket:
3 | version :u4
4 | type :u4
5 | vrid :u8
6 | priority :u8
7 | addr_count :u8
8 | reserved :u4
9 | max_advertise_interval :u20
10 | checksum :u16
11 |
12 |
13 | format IPv4VrrpPacket:
14 | header :VRRPPacket
15 | addr :[header.addr_count][4]u8
16 |
17 | format IPv6VrrpPacket:
18 | header :VRRPPacket
19 | addr :[header.addr_count][16]u8
20 |
21 | enum VRRPState:
22 | INIT
23 | ACTIVE
24 | BACKUP
25 |
--------------------------------------------------------------------------------
/example/wasmos_def.txt:
--------------------------------------------------------------------------------
1 | struct tcpip_connect_fields {
2 | uint32_t dst_addr;
3 | uint16_t dst_port;
4 | };
5 | struct tcpip_connect_reply_fields {
6 | uint32_t sock;
7 | };
8 |
9 | struct tcpip_write_fields {
10 | int sock;
11 | uint8_t data[1024];
12 | size_t data_len;
13 | };
14 | struct tcpip_write_reply_fields {
15 | };
16 |
17 | struct tcpip_read_fields {
18 | int sock;
19 | };
20 | struct tcpip_read_reply_fields {
21 | uint8_t data[1024];
22 | size_t data_len;
23 | };
24 |
25 | struct echo_fields {
26 | uint8_t data[1024];
27 | size_t data_len;
28 | };
29 | struct echo_reply_fields {
30 | uint8_t data[1024];
31 | size_t data_len;
32 | };
33 |
34 | struct tcpip_data_fields {
35 | int sock;
36 | };
37 |
38 | struct tcpip_closed_fields {
39 | int sock;
40 | };
41 |
42 | struct tcpip_dns_resolve_fields {
43 | char hostname[256];
44 | };
45 | struct tcpip_dns_resolve_reply_fields {
46 | uint32_t addr;
47 | };
--------------------------------------------------------------------------------
/example/wave.bgn:
--------------------------------------------------------------------------------
1 |
2 | format WaveHeader:
3 | magic :"RIFF"
4 | chunkSize :u32
5 | magic2 :"WAVE"
6 | subChunk1Id :"fmt "
7 | subChunk1Size :u32
8 | audioFormat :u16
9 | numChannels :u16
10 | sampleRate :u32
11 | byteRate :u32
12 | blockAlign :u16
13 | bitsPerSample :u16
14 | subChunk2Id :"data"
15 | subChunk2Size :u32
16 |
17 | format Wave:
18 | header :WaveHeader
19 | data :[header.subChunk2Size]u8
20 |
--------------------------------------------------------------------------------
/example/webauthn_cosepubkey.bgn:
--------------------------------------------------------------------------------
1 |
2 | config.go.package="webauthn"
3 | config.word.map("Cose","COSE")
4 |
5 | enum COSEKeyType:
6 | Reserved = 0
7 | OctetKey = 1
8 | EllipticKey = 2
9 | RSAKey = 3
10 | Symmetric = 4
11 | HSSLMS = 5
12 |
13 |
14 | COSE_KEY_KEY_TYPE ::= 1
15 | COSE_KEY_ALGORITHM_IDENTIFIER ::= 3
16 |
17 | COSE_OKP_KEY_X_COORDINATE ::= -2
18 |
19 | COSE_EC_KEY_CRV ::= -1
20 | COSE_EC_KEY_X_COORDINATE ::= -2
21 | COSE_EC_KEY_Y_COORDINATE ::= -3
22 |
23 | COSE_RSA_KEY_N ::= -1
24 | COSE_RSA_KEY_E ::= -2
25 |
--------------------------------------------------------------------------------
/example/websocket.bgn:
--------------------------------------------------------------------------------
1 |
2 | enum OpCode:
3 | :u4
4 | ContinuationFrame = 0x0
5 | TextFrame = 0x1
6 | BinaryFrame = 0x2
7 | ConnectionClose = 0x8
8 | Ping = 0x9
9 | Pong = 0xA
10 |
11 | format Frame:
12 | FIN :u1
13 | RSV1 :u1
14 | RSV2 :u1
15 | RSV3 :u1
16 | Opcode :OpCode
17 | Mask :u1
18 | PayloadLength :u7
19 | match PayloadLength:
20 | 126 => ExtendedPayloadLength :u16
21 | 127 => ExtendedPayloadLength :u64
22 |
23 | if Mask == 1:
24 | MaskingKey :[4]u8
25 |
26 | len ::= available(ExtendedPayloadLength) ? # if ExtendedPayloadLength (u16 or u64) is available
27 | ExtendedPayloadLength : # use ExtendedPayloadLength
28 | PayloadLength # otherwise use PayloadLength
29 | Payload :[len]u8(input.xor = MaskingKey)
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/wire_data/capnproto.dat:
--------------------------------------------------------------------------------
1 | # Cap'n Proto format
2 | # little endian format
3 | # 0b00 /*magic*/ 0x0001 /*offset*/
4 | # 0x0002 /*sizeof data*/ 0x0003 /*sizeof pointer*/
5 | 0300 0200 0100 0000
6 | 0000 0000 0000 0000 # skip offset
7 | 6865 6c6c 6f20 776f # struct data?
8 | 726c 6420 0000 0000
9 |
--------------------------------------------------------------------------------
/example/wire_data/udp.dat:
--------------------------------------------------------------------------------
1 | # UDP Header
2 | ef12 01bb
3 | 0023 0000
4 | # Data
5 | c0
6 | 00 00 00 01 # version
7 | 00 # dst connection id
8 | # no data
9 | 00 # src connection id
10 | # no data
11 | 00 # token length
12 | # no token
13 | 12 # length
14 | 00 # packet number
15 | 01 # ping frame
16 | # Message Authentication Code (16 byte)
17 | 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
18 |
19 |
--------------------------------------------------------------------------------
/example/wire_data/unknwon_raspi.bgn:
--------------------------------------------------------------------------------
1 | format UnknownHeader:
2 | thirty_three :[2]u8
3 | three_zero :[3]u8
4 | seven_random :[7]u8
5 | eight_six_dd :[2]u8
6 | sixty :u8
7 | seven_random2 :[7]u8
8 | fe_byte_and_zero :[8]u8
9 | nine_random :[9]u8
10 | two :u8
11 | twenty_six_zero :[26]u8
12 |
13 | format UnknownHeader2:
14 | nine_header :[9]u8
15 | two_zero :[2]u8
16 | eight_four :[2]u8
17 | four_zero :[4]u8
18 | one :u8
19 | four_maybe_type_of_packet :[4]u8
20 | twenty_one_random :[21]u8
21 | maybe_flag :u8
22 | one2 :u8
23 | two_zero2 :[2]u8
24 | unknown_but_different_two :[2]u8
25 | two_three :u8
26 | two_same_thirty_five_random :[2][35]u8
--------------------------------------------------------------------------------
/example/wire_data/varint.dat:
--------------------------------------------------------------------------------
1 | # quic varint
2 | # prefix = 0 (8-bit data)
3 | 3A
4 | 12
5 | 24
6 | 3f
7 |
8 | # prefix = 1 (16-bit data)
9 | 40 85
10 | 40 F3
11 | 40 9B
12 | 7F FF
13 |
14 | # prefix = 2 (32-bit data)
15 | 80 01 2B 3D
16 | 80 04 E6 7F
17 | 80 00 AB CD
18 | BF FF FF FF
19 |
20 | # prefix = 3 (64-bit data)
21 | C0 12 34 56 78 9A BC DE
22 | C0 00 12 34 56 78 9A BC
23 | C0 98 76 54 32 1F ED CB
24 |
25 | FF FF FF FF FF FF FF FF
26 |
27 | # fastcgi varint
28 | # prefix = 0 (8-bit data)
29 | 7f
30 | # prefix = 1 (32-bit data)
31 | FF FF FF FF
32 |
--------------------------------------------------------------------------------
/example/wire_data/websocket.dat:
--------------------------------------------------------------------------------
1 | # WebSocket Frame
2 | 8 # fin=true rsv1-rsv3
3 | 1 # text frame
4 | 0 # mask = false
5 | f # payload len = 15
6 | # no extended len
7 | # no mask
8 | # payload 15 byte
9 | 68 65 6c 6c 6f 20 77 6f 72 6c 64 20 21 21 21
10 |
--------------------------------------------------------------------------------
/example/wireguard.bgn:
--------------------------------------------------------------------------------
1 |
2 | AEAD_LEN ::= 16
3 |
4 | format handshake_initiation:
5 | message_type :u8
6 | reserved_zero :[3]u8
7 | sender_index :u32
8 | unencrypted_ephemeral :[32]u8
9 | encrypted_static :[32+AEAD_LEN]u8
10 | encrypted_timestamp :[12+AEAD_LEN]u8
11 | mac1 :[16]u8
12 | mac2 :[16]u8
13 |
14 | format handshake_response:
15 | message_type :u8
16 | reserved_zero :[3]u8
17 | sender_index :u32
18 | receiver_index :u32
19 | unencrypted_ephemeral :[32]u8
20 | encrypted_nothing :[0+AEAD_LEN]u8
21 | mac1 :[16]u8
22 | mac2 :[16]u8
23 |
24 | # packet_data {
25 | # u8 message_type
26 | # u8 reserved_zero[3]
27 | # u32 receiver_index
28 | # u64 counter
29 | # u8 encrypted_encapsulated_packet[]
30 | # }
31 |
32 | format packet_data:
33 | message_type :u8
34 | reserved_zero :[3]u8
35 | receiver_index :u32
36 | counter :ul64
37 | encrypted_encapsulated_packet :[..]u8
38 |
39 | # packet_cookie_reply {
40 | # u8 message_type
41 | # u8 reserved_zero[3]
42 | # u32 receiver_index
43 | # u8 nonce[24]
44 | # u8 encrypted_cookie[AEAD_LEN(16)]
45 | # }
46 |
47 | format packet_cookie_reply:
48 | message_type :u8
49 | reserved_zero :[3]u8
50 | receiver_index :u32
51 | nonce :[24]u8
52 | encrypted_cookie :[16+AEAD_LEN]u8
53 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/on-keyday/brgen
2 |
3 | go 1.24
4 |
5 | require github.com/iancoleman/strcase v0.3.0
6 |
7 | require golang.org/x/net v0.40.0
8 |
9 | require (
10 | golang.org/x/sys v0.33.0
11 | sigs.k8s.io/yaml v1.4.0
12 | )
13 |
--------------------------------------------------------------------------------
/lsp/.vscodeignore:
--------------------------------------------------------------------------------
1 | **/src/**
2 | **/tsconfig.json
3 | **/*.ts
4 |
5 |
--------------------------------------------------------------------------------
/lsp/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 on-keyday (https://github.com/on-keyday)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lsp/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "version": "0.0.1",
4 | "description": "brgen language server client",
5 | "main": "./out/extension.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "watch": "tsc -b -w",
9 | "compile": "tsc -b",
10 | "vscode:prepublish": "npm run compile"
11 | },
12 | "author": "",
13 | "license": "MIT",
14 | "dependencies": {
15 | "vscode-languageclient": "^9.0.0"
16 | },
17 | "devDependencies": {
18 | "@types/node": "^22.0.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lsp/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "0.0.1",
4 | "description": "brgen language server",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "watch": "tsc -b -w",
9 | "compile": "tsc -b",
10 | "vscode:prepublish": "npm run compile"
11 | },
12 | "author": "",
13 | "license": "MIT",
14 | "dependencies": {
15 | "vscode-languageserver": "^9.0.0",
16 | "vscode-languageserver-textdocument": "^1.0.8"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:recommended", "group:allNonMajor"]
4 | }
5 |
--------------------------------------------------------------------------------
/script/clean.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | rmdir /Q /S %CD%\built
4 |
--------------------------------------------------------------------------------
/script/clone_utils.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | git clone https://github.com/on-keyday/utils --depth 1
4 | cd utils
5 | if "%2" == "" (
6 | set BUILD_TYPE=Debug
7 | ) else (
8 | set BUILD_TYPE=%2
9 | )
10 | if "%1" == "wasm-em" (
11 | call build wasm-em %BUILD_TYPE% futils
12 | ) else (
13 | call build shared %BUILD_TYPE% futils
14 | if "%S2J_USE_NETWORK%" == "1" (
15 | call build shared %BUILD_TYPE% fnet
16 | call build shared %BUILD_TYPE% fnetserv
17 | )
18 | )
19 | cd ..
20 |
--------------------------------------------------------------------------------
/script/clone_utils.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 | git clone https://github.com/on-keyday/utils --depth 1
3 | cd utils || exit 1
4 | BUILD_TYPE=$2
5 | if [ ! $BUILD_TYPE ]; then
6 | BUILD_TYPE=Debug
7 | fi
8 | if [ $1 = "wasm-em" ]; then
9 | . build wasm-em $BUILD_TYPE futils
10 | else
11 | . build shared $BUILD_TYPE futils
12 | if [ "$S2J_USE_NETWORK" = "1" ]; then
13 | . build shared $BUILD_TYPE fnet
14 | . build shared $BUILD_TYPE fnetserv
15 | fi
16 | fi
17 | cd ..
18 |
--------------------------------------------------------------------------------
/script/cmptest_debug.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | FUTILS_DIR=/c/workspace/utils_backup
3 | export FUTILS_DIR=$FUTILS_DIR
4 | ./build.sh
5 | tool/brgen -config test-brgen.json
6 | tool/cmptest -f ./ignore/example/test_info.json -c ./testkit/cmptest.json --print-fail-command --save-tmp-dir --as-vscode --clean-tmp
7 |
8 |
--------------------------------------------------------------------------------
/script/collect_licenses.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | licensed cache
3 | licensed status
4 | if [ $? -eq 0 ]; then
5 | echo "licensed status: OK"
6 | else
7 | echo "licensed status: FAIL"
8 | return 1
9 | fi
10 | if [ ! -d ./license_cache ]; then
11 | mkdir ./license_cache
12 | fi
13 | if [ ! -d ./license_cache/go ]; then
14 | mkdir ./license_cache/go
15 | fi
16 | if [ ! -d ./license_cache/web ]; then
17 | mkdir ./license_cache/web
18 | fi
19 | GOCREDITS=`go env GOPATH`/bin/gocredits
20 | $GOCREDITS -skip-missing > ./license_cache/go/credits.txt
21 | if [ $? -eq 0 ]; then
22 | echo "gocredits save: OK"
23 | else
24 | echo "gocredits save: FAIL"
25 | return 1
26 | fi
27 | cd web/doc
28 | $GOCREDITS -skip-missing > ../../license_cache/web/credits.txt
29 | RESULT=$?
30 | cd ../..
31 | if [ $RESULT -eq 0 ]; then
32 | echo "gocredits save: OK"
33 | else
34 | echo "gocredits save: FAIL"
35 | return 1
36 | fi
37 | cp ./script/license_note.txt ./license_cache/
38 | if [ $? -eq 0 ]; then
39 | echo "license_note.txt copy: OK"
40 | else
41 | echo "license_note.txt copy: FAIL"
42 | return 1
43 | fi
44 |
--------------------------------------------------------------------------------
/script/copy_bmgen_stub.py:
--------------------------------------------------------------------------------
1 | import pathlib as pl
2 | import shutil as sh
3 |
4 | if not pl.Path("./web/dev/src/lib/bmgen").exists():
5 | sh.copytree("./web/dev/stub/bmgen", "./web/dev/src/lib/bmgen")
6 |
--------------------------------------------------------------------------------
/script/copy_example.py:
--------------------------------------------------------------------------------
1 | import shutil
2 |
3 | shutil.copytree("./example", "./web/public/example", dirs_exist_ok=True)
4 |
5 | # list copied files recursively and filter by suffix .bgn and
6 | # write ./web/public/example/index.txt
7 | import os
8 | import pathlib
9 |
10 | with open("./web/public/example/index.txt", "w") as f:
11 | for root, dirs, files in os.walk("./web/public/example"):
12 | for file in files:
13 | if file.endswith(".bgn"):
14 | path = pathlib.Path(os.path.join(root, file))
15 | path = path.relative_to("./web/public")
16 | f.write(path.as_posix() + "\n")
17 |
--------------------------------------------------------------------------------
/script/dirty_patch.py:
--------------------------------------------------------------------------------
1 | TARGET = "src/tool/json2rust/pkg/json2rust.d.ts"
2 | with open(TARGET, "r") as f:
3 | text = f.read()
4 |
5 | text = text.replace("=> Array", "=> number[]")
6 |
7 | with open(TARGET, "w") as f:
8 | f.write(text)
9 |
--------------------------------------------------------------------------------
/script/export_tag.sh:
--------------------------------------------------------------------------------
1 |
2 | read RELEASE_TAG < ./script/tag.txt
3 |
4 | if [ -z "$RELEASE_TAG" ]; then
5 | echo "No tag found"
6 | exit 1
7 | fi
8 |
9 | echo "Exporting tag $RELEASE_TAG"
10 | export RELEASE_TAG
11 |
--------------------------------------------------------------------------------
/script/gen_deep.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | set OUTPUT_DIR=src/
4 | set DEEP_GEN=go run ./src/tool/gen/cpp_deep_copy
5 |
6 | tool\src2json --dump-types | %DEEP_GEN% /dev/stdout | clang-format > %OUTPUT_DIR%/core/ast/node/deep_copy.h
7 |
--------------------------------------------------------------------------------
/script/gen_enum.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | set INPUT_DIR=example/brgen_help
4 | set OUTPUT_DIR=src/
5 | set ENUM_GEN=go run ./src/tool/gen/enum_gen
6 |
7 | tool\src2json example/brgen_help/ast_enum.bgn | %ENUM_GEN% > %OUTPUT_DIR%/core/ast/node/ast_enum.h
8 | tool\src2json example/brgen_help/lexer_enum.bgn | %ENUM_GEN% > %OUTPUT_DIR%/core/lexer/lexer_enum.h
9 | tool\src2json example/brgen_help/vm_enum.bgn | %ENUM_GEN% > %OUTPUT_DIR%/vm/vm_enum.h
10 |
--------------------------------------------------------------------------------
/script/gen_large.py:
--------------------------------------------------------------------------------
1 | BASE_TEXT = """
2 | format Step%s:
3 | name: "step%s"
4 | value :u64
5 | step :u%s
6 |
7 | """
8 | import sys
9 | import textwrap
10 |
11 |
12 | def gen_large(count):
13 | for i in range(1, count):
14 | print(BASE_TEXT % (i, i, i))
15 |
16 |
17 | def gen_indent(count):
18 | indent = " "
19 | print(BASE_TEXT % (1, 1, 1))
20 | for i in range(2, count):
21 | print(textwrap.indent(BASE_TEXT % (i, i, i), indent))
22 | indent += " "
23 |
24 |
25 | if __name__ == "__main__":
26 | count = int(sys.argv[2])
27 | mode = sys.argv[1]
28 | match mode:
29 | case "flat":
30 | gen_large(count)
31 | case "nest":
32 | gen_indent(count)
33 | case _:
34 | raise ValueError("unknown mode")
35 |
--------------------------------------------------------------------------------
/script/gen_sample.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | tool\src2json %1 > ignore\sample.json
4 |
--------------------------------------------------------------------------------
/script/gen_samples.sh:
--------------------------------------------------------------------------------
1 | for file in example/*.bgn; do
2 | name=`basename $file`
3 | tool/src2json $file > example/s2j_test/${name}.json
4 | done
--------------------------------------------------------------------------------
/script/generate.py:
--------------------------------------------------------------------------------
1 | import subprocess as sp
2 |
3 | ret = sp.call(
4 | ["./tool/gen_ast2go", "./astlib/ast2go/ast/ast.go"],
5 | executable="./tool/gen_ast2go.exe",
6 | )
7 | print(ret)
8 | ret = sp.call(
9 | ["gofmt", "-w", "./astlib/ast2go/ast/ast.go"],
10 | )
11 | print(ret)
12 | ret = sp.call(
13 | ["./tool/gen_ast2ts", "./astlib/ast2ts/src/ast.ts"],
14 | executable="./tool/gen_ast2ts.exe",
15 | )
16 | print(ret)
17 | ret = sp.call(["tsc"], cwd="./astlib/ast2ts", shell=True)
18 | print(ret)
19 | if ret == 0:
20 | import shutil
21 |
22 | shutil.copy("./LICENSE", "./astlib/ast2ts/out/LICENSE")
23 | ret = sp.call(
24 | ["./tool/gen_ast2rust", "./astlib/ast2rust/core/src/ast.rs"],
25 | executable="./tool/gen_ast2rust.exe",
26 | )
27 | print(ret)
28 | ret = sp.call(
29 | ["./tool/gen_ast2py", "./astlib/ast2py/ast.py"],
30 | executable="./tool/gen_ast2py.exe",
31 | )
32 | print(ret)
33 |
34 | ret = sp.call(
35 | ["./tool/gen_ast2c", "./astlib/ast2c/ast.h", "./astlib/ast2c/ast.c"],
36 | executable="./tool/gen_ast2c.exe",
37 | )
38 |
39 | print(ret)
40 |
41 | ret = sp.call(
42 | ["./tool/gen_ast2csharp", "./astlib/ast2csharp/ast.cs"],
43 | executable="./tool/gen_ast2csharp.exe",
44 | )
45 |
46 | print(ret)
47 |
48 | ret = sp.call(
49 | ["./tool/gen_ast2dart", "./astlib/ast2dart/lib/ast.dart"],
50 | executable="./tool/gen_ast2dart.exe",
51 | )
52 |
53 | print(ret)
54 |
--------------------------------------------------------------------------------
/script/install_lsp.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd lsp
3 | call vsce package
4 | call code --install-extension ./brgen-lsp-0.0.1.vsix
5 | cd ../
6 |
--------------------------------------------------------------------------------
/script/license_note.txt:
--------------------------------------------------------------------------------
1 | This bundle contains license information for web, LSP, and Golang dependencies.
2 | Some are exclusively used in development or build processes (such as compilers),
3 | while others are integrated into the binary.
4 | However, counting and categorizing all dependencies based on their usage has proven challenging for me.
5 | The licenses for these libraries have been gathered using tools
6 | like licensed (https://github.com/github/licensed) and gocredits (https://github.com/Songmu/gocredits),
7 | and the author has personally verified them.
8 | It's important to note that the author is not a lawyer,
9 | so there might be gaps in the consideration of licenses.
10 | If any issues with the licenses are identified,
11 | please report them through GitHub Issues at https://github.com/on-keyday/brgen.
12 |
--------------------------------------------------------------------------------
/script/link_path.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export LD_LIBRARY_PATH=`pwd`/tool:$LD_LIBRARY_PATH
4 |
--------------------------------------------------------------------------------
/script/make_ast_doc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | ER_DIAGRAM=`./tool/gen_ast2mermaid stdout`
5 | FLOW_CHART=`./tool/gen_ast2mermaid -flow stdout | grep derive`
6 | JSON=`./tool/src2json --dump-types | jq`
7 |
8 |
9 | #echo "$ER_DIAGRAM"
10 | #echo "$FLOW_CHART"
11 | #echo "$JSON"
12 |
13 | #return
14 |
15 | DOC=$(cat <}}
71 |
72 | EOF
73 | )
74 |
75 |
76 | echo "$DOC" > ./web/doc/content/docs/ast.md
77 |
--------------------------------------------------------------------------------
/script/make_cpp_tests.sh:
--------------------------------------------------------------------------------
1 |
2 | if [ $# -lt 1 ]; then
3 | echo "Usage: $0 [run]"
4 | exit 1
5 | fi
6 |
7 | TEST_TARGETS=`cat $1 | jq -r '.generated_files[] | select(.suffix==".hpp") | "\(.dir) \(.base)"'`
8 |
9 | if [ `uname -o` == 'Msys' ]; then
10 | # replace \r\n to \n
11 | TEST_TARGETS=`echo -n "$TEST_TARGETS" | sed -e "s@\r\n@\n@"`
12 | fi
13 |
14 | MAKE_CPP_TEST_PATH=`cd $(dirname ${0}) && pwd`/make_cpp_test.sh
15 |
16 | echo "$MAKE_CPP_TEST_PATH"
17 | RUN_BUILD=$2
18 | IFS=$'\n'
19 | for TEST_TARGET in $TEST_TARGETS; do
20 | DIR=`echo $TEST_TARGET | cut -d ' ' -f 1`
21 | BASE=`echo $TEST_TARGET | cut -d ' ' -f 2`
22 | echo "make test for $DIR/$BASE.hpp"
23 | bash -C $MAKE_CPP_TEST_PATH $DIR $BASE $RUN_BUILD &
24 | done
25 | wait
26 | echo "all tests are done"
27 |
--------------------------------------------------------------------------------
/script/push_and_watch.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | git push
4 | ping -n 4 127.0.0.1>nul
5 | gh run watch -i1
6 |
--------------------------------------------------------------------------------
/script/tag.txt:
--------------------------------------------------------------------------------
1 | v0.0.7
--------------------------------------------------------------------------------
/script/tag_release.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | for /f %%a in (./script/tag.txt) do set RELEASE_TAG=%%a
5 | if "%RELEASE_TAG%"=="" (
6 | echo "tag.txt" not found
7 | exit /b 1
8 | )
9 | rem test
10 | echo %RELEASE_TAG%
11 | git tag -d %RELEASE_TAG%
12 | git push origin --delete %RELEASE_TAG%
13 | git add .
14 | git commit -m "release %RELEASE_TAG% %date% %time%"
15 | git tag %RELEASE_TAG%
16 | git push
17 | git push origin %RELEASE_TAG%
18 |
--------------------------------------------------------------------------------
/spec/brgen_test_info_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "type": "object",
4 | "description": "brgen(BinaRy encoder/decoder GENerator driver) output information file schema",
5 | "properties": {
6 | "total_count": {
7 | "type": "integer",
8 | "description": "Total count of output files"
9 | },
10 | "error_count": {
11 | "type": "integer",
12 | "description": "Count of output files with errors"
13 | },
14 | "time": {
15 | "type": "string",
16 | "description": "Time taken to generate output files"
17 | },
18 | "generated_files": {
19 | "type": "array",
20 | "description": "List of generated output files",
21 | "items": {
22 | "type": "object",
23 | "properties": {
24 | "dir": {
25 | "type": "string",
26 | "description": "Directory containing the output file"
27 | },
28 | "base": {
29 | "type": "string",
30 | "description": "Output file name without extension"
31 | },
32 | "suffix": {
33 | "type": "string",
34 | "description": "Output file extension"
35 | }
36 | }
37 | }
38 | }
39 | },
40 | "additionalProperties": false
41 | }
42 |
--------------------------------------------------------------------------------
/src/core/ast/ast.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "node/base.h"
4 | #include "node/expr.h"
5 | #include "node/statement.h"
6 | #include "node/type.h"
7 | #include "node/translated.h"
8 | #include "node/scope.h"
9 |
10 | namespace brgen::ast {
11 |
12 | template
13 | constexpr T* as(auto&& t) {
14 | Node* v = std::to_address(t);
15 | if constexpr (std::is_same_v) {
16 | return v;
17 | }
18 | else if constexpr (std::is_same_v || std::is_same_v ||
19 | std::is_same_v || std::is_same_v ||
20 | std::is_same_v) {
21 | if (v && (int(v->node_type) & int(T::node_type_tag)) == int(T::node_type_tag)) {
22 | return static_cast(v);
23 | }
24 | }
25 | else {
26 | if (v && v->node_type == T::node_type_tag) {
27 | return static_cast(v);
28 | }
29 | }
30 | return nullptr;
31 | }
32 |
33 | template
34 | constexpr auto cast_to(auto&& t) {
35 | assert(as(t) != nullptr);
36 | using T = std::decay_t;
37 | if constexpr (futils::helper::is_template_instance_of) {
38 | using V = typename futils::helper::template_instance_of_t::template param_at<0>;
39 | return std::static_pointer_cast(std::forward(t));
40 | }
41 | else {
42 | return static_cast(t);
43 | }
44 | }
45 |
46 | } // namespace brgen::ast
47 |
--------------------------------------------------------------------------------
/src/core/ast/kill_node.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 |
4 | #include "traverse.h"
5 |
6 | namespace brgen::ast {
7 | // for large scale of AST
8 | // destructor call stack is too deep that makes stack overflow
9 | // so we need to use this
10 | void kill_node(const std::shared_ptr& node) {
11 | if (auto p = ast::as(node); p && p->global_scope) {
12 | std::vector> stack;
13 | stack.push_back(std::move(p->global_scope));
14 | p->global_scope = nullptr;
15 | while (!stack.empty()) {
16 | auto s = std::move(stack.back());
17 | stack.pop_back();
18 | if (s->next) {
19 | if (s->next->prev.lock() == s) {
20 | stack.push_back(std::move(s->next));
21 | }
22 | s->next = nullptr;
23 | }
24 | if (s->branch) {
25 | stack.push_back(std::move(s->branch));
26 | s->branch = nullptr;
27 | }
28 | }
29 | }
30 | std::vector> stack;
31 | stack.push_back(node);
32 | while (!stack.empty()) {
33 | auto n = std::move(stack.back());
34 | stack.pop_back();
35 | traverse(n, [&](auto& v) {
36 | stack.push_back(std::move(v));
37 | v = nullptr;
38 | });
39 | }
40 | }
41 | } // namespace brgen::ast
42 |
--------------------------------------------------------------------------------
/src/core/ast/line_map.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 |
5 | namespace brgen::ast {
6 | struct LineMap {
7 | brgen::lexer::Loc loc;
8 | size_t line;
9 | };
10 |
11 | void as_json(LineMap& mp, auto&& obj) {
12 | auto field = obj.object();
13 | field("loc", mp.loc);
14 | field("line", mp.line);
15 | }
16 |
17 | } // namespace brgen::ast
--------------------------------------------------------------------------------
/src/core/ast/parse.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "ast.h"
4 | #include "stream.h"
5 |
6 | namespace brgen::ast {
7 | struct ParseOption {
8 | bool collect_comments = false;
9 | bool error_tolerant = false;
10 | };
11 | std::shared_ptr parse(Stream& stream, LocationError* err_or_warn, ParseOption option = {});
12 | } // namespace brgen::ast
13 |
--------------------------------------------------------------------------------
/src/core/ast/tool/metadata.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "../ast.h"
4 |
5 | namespace brgen::ast::tool {
6 | std::optional lookup_str_metadata(std::string_view name, std::vector>& md) {
7 | for (auto& m : md) {
8 | auto p = m.lock();
9 | if (p && p->name == name && p->values.size() == 1) {
10 | if (auto s = ast::as(p->values[0])) {
11 | auto input = s->value.substr(1, s->value.size() - 2);
12 | return futils::escape::unescape_str(input);
13 | }
14 | }
15 | }
16 | return std::nullopt;
17 | }
18 | } // namespace brgen::ast::tool
19 |
--------------------------------------------------------------------------------
/src/core/ast/tool/tmp_ident.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 |
5 | namespace brgen::ast::tool {
6 | void set_tmp_field_ident(size_t seq, const std::shared_ptr& f, const char* name_prefix = "tmp") {
7 | if (f->ident) return;
8 | auto ident = std::make_shared(f->loc, brgen::concat(name_prefix, brgen::nums(seq)));
9 | ident->base = f;
10 | f->ident = ident;
11 | f->ident->usage = IdentUsage::define_field;
12 | f->ident->constant_level = ConstantLevel::variable;
13 | }
14 | } // namespace brgen::ast::tool
15 |
--------------------------------------------------------------------------------
/src/core/common/debug.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "util.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace brgen {
11 |
12 | #define sdebugf(name) field_(#name, name)
13 | #define sdebugf_omit(name) field_(#name, name)
14 |
15 | using JSONWriter = futils::json::Stringer<>;
16 | } // namespace brgen
17 |
--------------------------------------------------------------------------------
/src/core/common/expected.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 |
5 | namespace brgen {
6 | using namespace futils::helper::either;
7 | namespace either = futils::helper::either;
8 |
9 | constexpr auto unexpect(auto&&... e) {
10 | return either::unexpected(e...);
11 | }
12 |
13 | } // namespace brgen
14 |
--------------------------------------------------------------------------------
/src/core/common/util.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace brgen {
10 | auto nums(auto v, int radix = 10) {
11 | return futils::number::to_string(v, radix);
12 | }
13 |
14 | using futils::strutil::append, futils::strutil::appends;
15 |
16 | inline std::optional unescape(std::string_view str_lit) {
17 | std::string mid;
18 | if (!futils::escape::unescape_str(str_lit.substr(1, str_lit.size() - 2), mid)) {
19 | return std::nullopt;
20 | }
21 | return mid;
22 | }
23 |
24 | template
25 | inline std::optional unescape_count(std::string_view str_lit) {
26 | futils::helper::CountPushBacker pb;
27 | futils::helper::IPushBacker ipb{pb};
28 | if (!futils::escape::unescape_str(str_lit.substr(1, str_lit.size() - 2), ipb)) {
29 | return std::nullopt;
30 | }
31 | return pb.count;
32 | }
33 |
34 | inline std::string escape(std::string_view str_lit) {
35 | return futils::escape::escape_str(str_lit, futils::escape::EscapeFlag::utf16 | futils::escape::EscapeFlag::hex);
36 | }
37 |
38 | inline std::string concat(auto&&... msg) {
39 | std::string buf;
40 | appends(buf, msg...);
41 | return buf;
42 | }
43 |
44 | } // namespace brgen
45 |
--------------------------------------------------------------------------------
/src/core/lexer/token.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include
5 | #include "lexer_enum.h"
6 | #include
7 |
8 | namespace brgen::lexer {
9 | using Pos = futils::comb2::Pos;
10 |
11 | using FileIndex = std::uint64_t;
12 |
13 | constexpr FileIndex builtin = 0;
14 |
15 | struct Loc {
16 | Pos pos;
17 | FileIndex file = 0; // file index
18 | size_t line = 0;
19 | size_t col = 0;
20 | };
21 |
22 | constexpr bool operator==(const Loc& lhs, const Loc& rhs) {
23 | return lhs.pos == rhs.pos && lhs.file == rhs.file && lhs.line == rhs.line && lhs.col == rhs.col;
24 | }
25 |
26 | constexpr void as_json(Loc l, auto&& buf) {
27 | auto field = buf.object();
28 | field("pos", [&] {
29 | auto field = buf.object();
30 | field("begin", l.pos.begin);
31 | field("end", l.pos.end);
32 | });
33 | field("file", l.file);
34 | field("line", l.line);
35 | field("col", l.col);
36 | }
37 |
38 | struct Token {
39 | Tag tag = Tag::unknown;
40 | std::string token;
41 | Loc loc;
42 | };
43 |
44 | constexpr void as_json(const Token& token, auto&& buf) {
45 | auto field = buf.object();
46 | field("tag", token.tag);
47 | field("token", token.token);
48 | field("loc", token.loc);
49 | }
50 |
51 | } // namespace brgen::lexer
52 |
--------------------------------------------------------------------------------
/src/core/middle/analyze_block_trait.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 |
5 | namespace brgen::middle {
6 | void analyze_block_trait(const std::shared_ptr&);
7 | }
--------------------------------------------------------------------------------
/src/core/middle/type_attribute.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 |
5 | namespace brgen::middle {
6 | void mark_recursive_reference(const std::shared_ptr& node);
7 | void analyze_bit_size_and_alignment(const std::shared_ptr& node);
8 | void detect_non_dynamic_type(const std::shared_ptr& node);
9 | }
10 |
--------------------------------------------------------------------------------
/src/core/middle/typing.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "../common/file.h"
4 | #include "../common/error.h"
5 | #include "../ast/ast.h"
6 |
7 | namespace brgen::middle {
8 | result analyze_type(std::shared_ptr& node, LocationError* warnings);
9 | }
10 |
--------------------------------------------------------------------------------
/src/test/core/ast_test.cpp:
--------------------------------------------------------------------------------
1 | #include "ast_test_component.h"
2 | #include
3 | #include
4 | #include
5 | using namespace brgen;
6 |
7 | int main(int argc, char** argv) {
8 | set_test_handler([](auto& prog, auto i, auto& fs) {
9 | JSONWriter d;
10 | d.value(prog);
11 | add_result(std::move(d));
12 | });
13 | ::testing::InitGoogleTest(&argc, argv);
14 | auto res = RUN_ALL_TESTS();
15 | save_result("ast_test_result.json");
16 | return res;
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/core/ast_test_component.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | extern futils::wrap::UtfOut& cerr;
11 |
12 | using Continuation = void (*)(std::shared_ptr& prog, brgen::File* input, brgen::FileSet& fs);
13 |
14 | // Function declarations with the AST_TEST_COMPONENT_API macro
15 | void set_test_handler(Continuation cont);
16 | void add_result(brgen::JSONWriter&& d);
17 | void save_result(const char* file);
18 |
--------------------------------------------------------------------------------
/src/test/core/derive_test.cpp:
--------------------------------------------------------------------------------
1 | /*license*/
2 |
3 | #include
4 | #include
5 |
6 | using namespace brgen;
7 |
8 | TEST(DeriveTest, Test1) {
9 | struct Dummy : ast::Member {
10 | Dummy()
11 | : ast::Member({}, ast::NodeType::member) {}
12 | };
13 | Dummy d;
14 | ASSERT_NE(ast::as(&d), nullptr);
15 | ASSERT_NE(ast::as(&d), nullptr);
16 | ASSERT_NE(ast::as(&d), nullptr);
17 |
18 |
19 | struct Dummy2 : ast::Literal {
20 | Dummy2()
21 | : ast::Literal({}, ast::NodeType::literal) {}
22 | };
23 |
24 | Dummy2 d2;
25 | ASSERT_NE(ast::as(&d2), nullptr);
26 | ASSERT_NE(ast::as(&d2), nullptr);
27 | ASSERT_NE(ast::as(&d2), nullptr);
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/core/from_json_test.cpp:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #include "ast_test_component.h"
3 | #include "middle_test.h"
4 | #include
5 | #include
6 | #include
7 | using namespace brgen;
8 |
9 | int main(int argc, char** argv) {
10 | set_test_handler([](auto a, auto in, auto fs) {
11 | LocationError warns;
12 | middle::test::apply_middle(warns, a)
13 | .transform_error(to_source_error(fs))
14 | .value();
15 | ast::JSONConverter m;
16 | m.encode(a);
17 | auto base = m.obj.out();
18 | add_result(std::move(m.obj));
19 | auto parsed = futils::json::parse(base);
20 | auto d = m.decode(parsed)
21 | .transform_error(to_source_error(fs))
22 | .value();
23 | m.encode(d);
24 | ASSERT_EQ(base, m.obj.out());
25 | });
26 | ::testing::InitGoogleTest(&argc, argv);
27 | auto res = RUN_ALL_TESTS();
28 | save_result("from_json_test_result.json");
29 | return res;
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/core/lexer_test.cpp:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #include
3 | #include
4 |
5 | TEST(LexerTest, LexerTest) {
6 | GTEST_ASSERT_TRUE(brgen::lexer::internal::check_lexer());
7 | }
8 |
--------------------------------------------------------------------------------
/src/test/core/middle_test.cpp:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #include "ast_test_component.h"
3 | #include "middle_test.h"
4 | #include
5 | using namespace brgen;
6 |
7 | int main(int argc, char** argv) {
8 | set_test_handler([](auto a, auto in, auto fs) {
9 | LocationError warns;
10 | middle::test::apply_middle(warns, a)
11 | .transform_error(to_source_error(fs))
12 | .value();
13 | JSONWriter d;
14 | d.value(a);
15 | add_result(std::move(d));
16 | });
17 | ::testing::InitGoogleTest(&argc, argv);
18 | auto res = RUN_ALL_TESTS();
19 | save_result("middle_test_result.json");
20 | return res;
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/core/middle_test.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include
5 |
6 | namespace brgen::middle::test {
7 | result apply_middle(LocationError& warn, std::shared_ptr& node) {
8 | middle::replace_assert(node);
9 | return middle::analyze_type(node, &warn).and_then([&] {
10 | brgen::middle::collect_unused_warnings(node, warn);
11 | return result{};
12 | });
13 | }
14 | } // namespace brgen::middle::test
15 |
--------------------------------------------------------------------------------
/src/test/core/typing_test.cpp:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #include "ast_test_component.h"
3 | #include
4 | #include
5 | #include
6 | using namespace brgen;
7 |
8 | int main(int argc, char** argv) {
9 | set_test_handler([](auto& a, File* input, FileSet& fs) {
10 | middle::analyze_type(a, nullptr).transform_error(to_source_error(fs)).value();
11 | JSONWriter d;
12 | d.value(*a);
13 | add_result(std::move(d));
14 | });
15 | ::testing::InitGoogleTest(&argc, argv);
16 | auto res = RUN_ALL_TESTS();
17 | save_result("typing_test_result.json");
18 | return res;
19 | }
--------------------------------------------------------------------------------
/src/test/test_tool/test_log_server/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "os"
6 |
7 | "golang.org/x/net/websocket"
8 | )
9 |
10 | func logging(fp *os.File, log chan string) {
11 | for {
12 | msg := <-log
13 | fp.WriteString(msg)
14 | }
15 | }
16 |
17 | func main() {
18 | file := os.Args[1]
19 | fp, err := os.Create(file)
20 | if err != nil {
21 | panic(err)
22 | }
23 | defer fp.Close()
24 | log := make(chan string)
25 | go logging(fp, log)
26 | serv := &websocket.Server{}
27 | serv.Handler = func(ws *websocket.Conn) {
28 | for {
29 | var msg string
30 | err := websocket.Message.Receive(ws, &msg)
31 | if err != nil {
32 | break
33 | }
34 | log <- msg
35 | }
36 | }
37 | http.Handle("/log", serv)
38 | http.ListenAndServe(":8080", nil)
39 | }
40 |
--------------------------------------------------------------------------------
/src/tool/brgen/config.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "encoding/json"
4 |
5 | type ArrayOrString []string
6 |
7 | func (a *ArrayOrString) UnmarshalJSON(b []byte) error {
8 | var arr []string
9 | if err := json.Unmarshal(b, &arr); err == nil {
10 | *a = arr
11 | return nil
12 | }
13 | var str string
14 | if err := json.Unmarshal(b, &str); err != nil {
15 | return err
16 | }
17 | *a = []string{str}
18 | return nil
19 | }
20 |
21 | type Output struct {
22 | Generator ArrayOrString `json:"generator"`
23 | OutputDir string `json:"output_dir"`
24 | Args []string `json:"args"`
25 | IgnoreMissing bool `json:"ignore_missing"`
26 | }
27 |
28 | type Warnings struct {
29 | DisableUntypedWarning bool `json:"disable_untyped"`
30 | DisableUnusedWarning bool `json:"disable_unused"`
31 | }
32 |
33 | type Config struct {
34 | Source2Json *string `json:"src2json"`
35 | LibSource2Json *string `json:"libs2j"`
36 | Suffix *string `json:"suffix"`
37 | TargetDirs []string `json:"input_dir"`
38 | Warnings Warnings `json:"warnings"`
39 | Output []*Output `json:"output"`
40 | TestInfo *string `json:"test_info_output"`
41 | }
42 |
--------------------------------------------------------------------------------
/src/tool/brgen/stdin_stream.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "io"
6 | "os/exec"
7 | "path"
8 | "path/filepath"
9 |
10 | "github.com/on-keyday/brgen/astlib/ast2go/request"
11 | )
12 |
13 | func (g *Generator) initStdinStream() error {
14 | cmdline := g.cmdline()
15 | cmd := exec.CommandContext(g.ctx, cmdline[0], cmdline[1:]...)
16 | cl, err := request.NewProcessClient(cmd)
17 | if err != nil {
18 | return err
19 | }
20 | g.stdinStream = cl
21 | return nil
22 | }
23 |
24 | func (g *Generator) handleStdinStreamRequest(req *Result) {
25 | stream := g.stdinStream.CreateStream()
26 | ext := filepath.Ext(req.Path)
27 | base := filepath.Base(req.Path)
28 | baseWithoutExt := base[:len(base)-len(ext)]
29 | err := stream.SendRequest(baseWithoutExt, req.Data)
30 | if err != nil {
31 | req.Err = err
32 | g.sendResult(req)
33 | return
34 | }
35 | for {
36 | resp, err := stream.ReceiveResponse()
37 | if err != nil {
38 | if err == io.EOF {
39 | break
40 | }
41 | req.Err = err
42 | g.sendResult(req)
43 | return
44 | }
45 | if resp.Status == request.ResponseStatus_Error {
46 | req.Err = errors.New(string(resp.ErrorMessage))
47 | g.sendResult(req)
48 | continue
49 | }
50 | if len(resp.Name) == 0 {
51 | req.Data = resp.Code
52 | req.Err = errors.New("empty name")
53 | g.sendResult(req)
54 | continue
55 | }
56 | if path.Ext(string(resp.Name)) == "" {
57 | req.Data = resp.Code
58 | req.Err = errors.New("no extension")
59 | g.sendResult(req)
60 | continue
61 | }
62 | g.sendGenerated(string(resp.Name), resp.Code)
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/tool/cmptest/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "cmptest"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | clap = { version = "4.5.4", features = ["derive"] }
10 | serde = { version="1.0.200" ,features = ["derive"]}
11 | serde_json = "1.0.116"
12 | ast2rust = {path ="../../../astlib/ast2rust/core" }
13 | regex = "1.10.4"
14 | rand = "0.9.0"
15 | tokio = { version = "1.37.0", features = ["full"] }
16 | colored = "3.0.0"
17 |
--------------------------------------------------------------------------------
/src/tool/common/em_main.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include
5 | #include
6 |
7 | int em_main(const char* cmdline, auto main_, auto... additional_args) {
8 | auto args = futils::view::make_cpy_splitview(cmdline, " ");
9 | futils::wrap::ArgvVector vec;
10 | for (size_t i = 0; i < args.size(); ++i) {
11 | std::string out;
12 | if (!futils::urlenc::decode(args[i], out)) {
13 | return 2;
14 | }
15 | vec.push_back(std::move(out));
16 | }
17 | int argc;
18 | char** argv;
19 | vec.arg(argc, argv);
20 | return main_(argc, argv, additional_args...);
21 | }
22 |
--------------------------------------------------------------------------------
/src/tool/common/generate.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "load_json.h"
4 | #include
5 | #include
6 |
7 | template
8 | int do_generate(const auto& flags, brgen::request::GenerateSource& req, T&& input, auto&& cb) {
9 | auto res = load_json(req.id, req.name, std::forward(input));
10 | if (!res) {
11 | return 1;
12 | }
13 | return cb(flags, req, res);
14 | }
15 |
16 | int generate_from_file(const auto& flags, auto&& cb) {
17 | if (flags.args.empty()) {
18 | print_error("no input file");
19 | return 1;
20 | }
21 | if (flags.args.size() > 1) {
22 | print_error("too many input files");
23 | return 1;
24 | }
25 | auto name = flags.args[0];
26 | futils::file::View view;
27 | if (!view.open(name)) {
28 | print_error("cannot open file ", name);
29 | return 1;
30 | }
31 | std::filesystem::path path{name};
32 | auto u8name = path.filename().replace_extension().generic_u8string();
33 | brgen::request::GenerateSource req;
34 | req.id = 0;
35 | req.name = std::string(reinterpret_cast(u8name.data()), u8name.size());
36 | send_as_text = true;
37 | return do_generate(flags, req, view, cb);
38 | }
39 |
--------------------------------------------------------------------------------
/src/tool/common/load_json.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "send.h"
4 | #include
5 | #include
6 |
7 | std::shared_ptr load_json(std::uint64_t id, auto&& name, auto&& input) {
8 | auto js = futils::json::parse(input);
9 | if (js.is_undef()) {
10 | send_error_and_end(id, "cannot parse json file: ", name);
11 | return nullptr;
12 | }
13 | brgen::ast::AstFile file;
14 | if (!futils::json::convert_from_json(js, file)) {
15 | send_error_and_end(id, "cannot convert json file to ast: ", name);
16 | return nullptr;
17 | }
18 | if (!file.ast) {
19 | send_error_and_end(id, "cannot convert json file to ast: ast is null: ", name);
20 | return nullptr;
21 | }
22 | brgen::ast::JSONConverter c;
23 | auto res = c.decode(*file.ast);
24 | if (!res) {
25 | send_error_and_end(id, "cannot decode json file: ", res.error().locations[0].msg);
26 | return nullptr;
27 | }
28 | if (!*res) {
29 | send_error_and_end(id, "cannot decode json file: ast is null: ", name);
30 | return nullptr;
31 | }
32 | return *res;
33 | }
--------------------------------------------------------------------------------
/src/tool/json2go/js.go:
--------------------------------------------------------------------------------
1 | //go:build js && wasm
2 |
3 | package main
4 |
5 | import (
6 | js "github.com/on-keyday/brgen/astlib/ast2go/js"
7 | )
8 |
9 | type makeGenerator struct{}
10 |
11 | func (m *makeGenerator) New() js.Generator {
12 | return NewGenerator()
13 | }
14 |
15 | func (m *makeGenerator) ResetFlag() {
16 | ResetFlag()
17 | }
18 |
19 | func setFunc() {
20 | js.SetGoFunc(&makeGenerator{})
21 | }
22 |
23 | func main() {
24 | c := make(chan struct{})
25 | setFunc()
26 | <-c
27 | }
28 |
--------------------------------------------------------------------------------
/src/tool/json2kaitai/js.go:
--------------------------------------------------------------------------------
1 | //go:build js && wasm
2 |
3 | package main
4 |
5 | import (
6 | js "github.com/on-keyday/brgen/astlib/ast2go/js"
7 | )
8 |
9 | type makeGenerator struct{}
10 |
11 | func (m *makeGenerator) New() js.Generator {
12 | return &Generator{}
13 | }
14 |
15 | func (m *makeGenerator) ResetFlag() {
16 |
17 | }
18 |
19 | func setFunc() {
20 | js.SetGoFunc(&makeGenerator{})
21 | }
22 |
23 | func main() {
24 | c := make(chan struct{})
25 | setFunc()
26 | <-c
27 | }
28 |
--------------------------------------------------------------------------------
/src/tool/json2kaitai/main.go:
--------------------------------------------------------------------------------
1 | //go:build !js || !wasm
2 |
3 | package main
4 |
5 | import (
6 | "encoding/json"
7 | "flag"
8 | "fmt"
9 | "os"
10 |
11 | "github.com/on-keyday/brgen/astlib/ast2go/ast"
12 | )
13 |
14 | func main() {
15 | flag.Parse()
16 | if *f {
17 | fmt.Println(`{
18 | "langs" : ["kaitai-struct"],
19 | "input" : "stdin",
20 | "suffix" : [".ksy"]
21 | }`)
22 | return
23 | }
24 | file := ast.AstFile{}
25 | if *filename != "" {
26 | f, err := os.Open(*filename)
27 | if err != nil {
28 | fmt.Fprintln(os.Stderr, err)
29 | os.Exit(1)
30 | return
31 | }
32 | defer f.Close()
33 | err = json.NewDecoder(f).Decode(&file)
34 | if err != nil {
35 | fmt.Fprintln(os.Stderr, err)
36 | os.Exit(1)
37 | return
38 | }
39 | } else {
40 | err := json.NewDecoder(os.Stdin).Decode(&file)
41 | if err != nil {
42 | fmt.Fprintln(os.Stderr, err)
43 | os.Exit(1)
44 | return
45 | }
46 | }
47 |
48 | g := &Generator{}
49 | out, err := g.GenerateAndFormat(&file)
50 | if err != nil {
51 | fmt.Fprintln(os.Stderr, err)
52 | os.Exit(1)
53 | return
54 | }
55 |
56 | os.Stdout.Write(out)
57 | }
58 |
--------------------------------------------------------------------------------
/src/tool/json2llvm/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "json2llvm"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | inkwell = { version="0.6.0", features = ["llvm17-0","llvm17-0-no-llvm-linking"] }
10 | ast2rust = { path ="../../../astlib/ast2rust/core" }
11 | serde = "1.0.200"
12 | serde_json = "1.0.116"
13 |
14 |
--------------------------------------------------------------------------------
/src/tool/json2llvm/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | println!("cargo:rustc-link-search=C:/workspace/LLVM/lib");
3 | println!("cargo:rustc-link-lib=LLVM-C");
4 | }
5 |
--------------------------------------------------------------------------------
/src/tool/json2llvm/src/main.rs:
--------------------------------------------------------------------------------
1 | mod generate;
2 | use ast2rust::ast;
3 | use generate::Error;
4 | use serde::Deserialize;
5 | use std::process::ExitCode;
6 |
7 | fn main() -> Result<(), Error> {
8 | let mut deserializer = serde_json::Deserializer::from_reader(std::io::stdin());
9 | let file = ast::AstFile::deserialize(&mut deserializer);
10 | if let Err(e) = file {
11 | return Err(Error::JSONError(e));
12 | }
13 | let file = file.unwrap();
14 | let prog = ast::parse_ast(file.ast.unwrap());
15 | if let Err(e) = prog {
16 | return Err(Error::ParseError(e));
17 | }
18 | let prog = prog.unwrap();
19 | let gen = generate::Generator::new(&prog);
20 | gen.generate()?;
21 | Ok(())
22 | }
23 |
--------------------------------------------------------------------------------
/src/tool/json2rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "json2rust"
3 | version = "0.1.0"
4 | edition = "2021"
5 | repository = "https://github.com/on-keyday/brgen"
6 | license = "MIT"
7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8 |
9 | [lib]
10 | crate-type = ["cdylib", "rlib"]
11 |
12 | [dependencies]
13 | anyhow = "1.0.86"
14 | ast2rust = {path ="../../../astlib/ast2rust/core" }
15 | ast2rust_macro = {path="../../../astlib/ast2rust/macros"}
16 | clap = { version = "4.5.4", features = ["derive"] }
17 | serde = "1.0.200"
18 | serde_json = "1.0.116"
19 | wasm-bindgen = "0.2.92"
20 |
21 |
--------------------------------------------------------------------------------
/src/tool/json2rust/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod generator;
2 | use ast2rust::ast;
3 | use serde::Deserialize;
4 | use wasm_bindgen::prelude::wasm_bindgen;
5 |
6 | #[wasm_bindgen]
7 | pub fn json2rust(input: &str) -> String {
8 | let mut deserializer = serde_json::Deserializer::from_str(input);
9 | let file = ast::AstFile::deserialize(&mut deserializer);
10 | if let Err(e) = file {
11 | return format!("error: {:?}", e);
12 | }
13 | let file = file.unwrap();
14 | let prog = ast::parse_ast(file.ast.unwrap());
15 | if let Err(e) = prog {
16 | return format!("error: {:?}", e);
17 | }
18 | let mut gen = generator::Generator::new(Vec::new());
19 | let prog = prog.unwrap();
20 | let b = gen.write_program(prog);
21 | if let Err(e) = b {
22 | return format!("error: {:?}", e);
23 | }
24 | let w = gen.get_mut_writer();
25 | String::from_utf8(w.clone()).unwrap()
26 | }
27 |
--------------------------------------------------------------------------------
/src/tool/json2spicy/spicy.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 |
4 | func main() {
5 |
6 | }
--------------------------------------------------------------------------------
/src/tool/json2ts/generate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | namespace json2ts {
4 | struct Flags {
5 | bool use_bigint = false;
6 | bool no_resize = false;
7 | bool javascript = false;
8 | bool enum_to_string = false;
9 | };
10 | std::string generate(const std::shared_ptr& p, Flags flags);
11 | } // namespace json2ts
12 |
--------------------------------------------------------------------------------
/src/tool/s2jgo/capability.go:
--------------------------------------------------------------------------------
1 | package s2jgo
2 |
3 | /*
4 | #define S2J_CAPABILITY_STDIN (1 << 0)
5 | #define S2J_CAPABILITY_NETWORK (1 << 1)
6 | #define S2J_CAPABILITY_FILE (1 << 2)
7 | #define S2J_CAPABILITY_ARGV (1 << 3)
8 | #define S2J_CAPABILITY_CHECK_AST (1 << 4)
9 | #define S2J_CAPABILITY_LEXER (1 << 5)
10 | #define S2J_CAPABILITY_PARSER (1 << 6)
11 | #define S2J_CAPABILITY_IMPORTER (1 << 7)
12 | #define S2J_CAPABILITY_AST_JSON (1 << 8)
13 | */
14 |
15 | type Capability uint64
16 |
17 | const (
18 | CAPABILITY_STDIN Capability = 1 << 0
19 | CAPABILITY_NETWORK Capability = 1 << 1
20 | CAPABILITY_FILE Capability = 1 << 2
21 | CAPABILITY_ARGV Capability = 1 << 3
22 | CAPABILITY_CHECK_AST Capability = 1 << 4
23 | CAPABILITY_LEXER Capability = 1 << 5
24 | CAPABILITY_PARSER Capability = 1 << 6
25 | CAPABILITY_IMPORTER Capability = 1 << 7
26 | CAPABILITY_AST_JSON Capability = 1 << 8
27 |
28 | CAPABILITY_ALL Capability = 0xffffffffffffffff
29 | )
30 |
--------------------------------------------------------------------------------
/src/tool/s2jgo/s2j_stub.go:
--------------------------------------------------------------------------------
1 | //go:build !windows && (!cgo || !linux && !darwin && !freebsd)
2 | package s2jgo
3 |
4 | import "errors"
5 |
6 | func Available() bool {
7 | return false
8 | }
9 |
10 | type src2JSON struct{}
11 |
12 | func load(_ string) (*src2JSON, error) {
13 | return nil, errors.New("not implemented")
14 | }
15 |
16 | func (s *src2JSON) CallIOCallback(args []string, cap Capability, cb func(data []byte, isStdErr bool)) error {
17 | return errors.New("not implemented")
18 | }
19 |
--------------------------------------------------------------------------------
/src/tool/s2jgo/s2j_test.go:
--------------------------------------------------------------------------------
1 | package s2jgo_test
2 |
3 | import (
4 | "io"
5 | "net/http"
6 | "os"
7 | "strings"
8 | "sync"
9 | "testing"
10 |
11 | "github.com/on-keyday/brgen/src/tool/s2jgo"
12 | )
13 |
14 | func TestLoad(t *testing.T) {
15 | os.Chdir("C:/workspace/shbrgen/brgen/tool")
16 | s2j, err := s2jgo.Load("C:/workspace/shbrgen/brgen/tool/libs2j.dll")
17 | if err != nil {
18 | t.Fatal(err)
19 | }
20 | var s sync.WaitGroup
21 | s.Add(1)
22 | go func() {
23 | err := s2j.CallIOCallback([]string{"src2json", "--via-http"}, s2jgo.CAPABILITY_ALL,
24 | func(data []byte, isStdErr bool) {
25 | if isStdErr {
26 | os.Stderr.Write(data)
27 | } else {
28 | os.Stdout.Write(data)
29 | }
30 | })
31 | if err != nil {
32 | return
33 | }
34 | s.Done()
35 | }()
36 | r, err := http.Get("http://localhost:8080/stat")
37 | if err != nil {
38 | t.Fatal(err)
39 | }
40 | io.Copy(os.Stdout, r.Body)
41 | r.Body.Close()
42 | r, err = http.Post("http://localhost:8080/parse", "application/json", strings.NewReader(`{"args":["../example/udp.bgn"]}`))
43 | if err != nil {
44 | t.Fatal(err)
45 | }
46 | io.Copy(os.Stdout, r.Body)
47 | r.Body.Close()
48 | r, err = http.Get("http://localhost:8080/stop")
49 | if err != nil {
50 | t.Fatal(err)
51 | }
52 | io.Copy(os.Stdout, r.Body)
53 | r.Body.Close()
54 | s.Wait()
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/tool/src2json/capi_export.h:
--------------------------------------------------------------------------------
1 | #if _WIN32
2 | #define S2J_EXPORT __declspec(dllexport)
3 | #else
4 | #define S2J_EXPORT
5 | #endif
6 |
--------------------------------------------------------------------------------
/src/tool/src2json/entry.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "capi.h"
4 |
5 | int src2json_main(int argc, char** argv, const Capability& cap);
6 |
--------------------------------------------------------------------------------
/src/tool/src2json/hook.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "../common/print.h"
4 |
5 | inline bool& is_worker_thread() {
6 | static thread_local bool is_worker = false;
7 | return is_worker;
8 | }
9 |
10 | inline futils::wrap::write_hook_fn& worker_hook() {
11 | static thread_local futils::wrap::write_hook_fn hook = nullptr;
12 | return hook;
13 | }
14 |
15 | inline std::string& worker_stdout_buffer() {
16 | static thread_local std::string buffer;
17 | return buffer;
18 | }
19 |
20 | inline std::string& worker_stderr_buffer() {
21 | static thread_local std::string buffer;
22 | return buffer;
23 | }
24 |
25 | inline futils::file::file_result cout_hook(futils::wrap::UtfOut& out, futils::view::rvec v) {
26 | if (is_worker_thread()) {
27 | worker_stdout_buffer().append(v.as_char(), v.size());
28 | return {};
29 | }
30 | if (worker_hook()) {
31 | return worker_hook()(out, v);
32 | }
33 | return out.write_no_hook(v);
34 | }
35 |
36 | inline futils::file::file_result cerr_hook(futils::wrap::UtfOut& out, futils::view::rvec v) {
37 | if (is_worker_thread()) {
38 | worker_stderr_buffer().append(v.as_char(), v.size());
39 | return {};
40 | }
41 | if (worker_hook()) {
42 | return worker_hook()(out, v);
43 | }
44 | return out.write_no_hook(v);
45 | }
--------------------------------------------------------------------------------
/src/tool/src2json/test.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include
5 |
6 | namespace brgen::test {
7 | // simplified version of src2json
8 | // this only parse success case, otherwise throw exception
9 | std::shared_ptr src2json(FileSet& fs);
10 | } // namespace brgen::test
11 |
--------------------------------------------------------------------------------
/src/tool/src2json/version.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 | #include "capi.h"
4 |
5 | #ifndef BRGEN_VERSION
6 | #define BRGEN_VERSION "0.0.0 (unversioned)"
7 | #endif
8 |
9 | #ifndef SRC2JSON_VERSION
10 | #define SRC2JSON_VERSION BRGEN_VERSION
11 | #endif
12 |
13 | constexpr auto lang_version = BRGEN_VERSION;
14 | constexpr auto src2json_version = SRC2JSON_VERSION;
15 |
16 | constexpr auto exit_ok = 0;
17 | constexpr auto exit_err = 1;
18 | constexpr auto err_invalid = 2;
19 |
20 | int src2json_main(int argc, char** argv, const Capability& cap);
21 |
22 | #ifdef S2J_USE_NETWORK
23 | int network_main(const char* port, bool unsafe_escape, const Capability& cap);
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/tool/ssagen/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/src/tool/ssagen/ssa/compile.go:
--------------------------------------------------------------------------------
1 | package ssa
2 |
3 | import (
4 | "github.com/on-keyday/brgen/astlib/ast2go/ast"
5 | )
6 |
7 | type Compiler struct {
8 | ssa []*Ssa
9 | }
10 |
11 | func (c *Compiler) Compile(p *ast.Program) {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/vm/compile.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include "vm.h"
5 |
6 | namespace brgen::vm {
7 | Code compile(const std::shared_ptr& prog);
8 | void print_code(futils::helper::IPushBacker<> out, const Code& code);
9 | } // namespace brgen::vm
10 |
--------------------------------------------------------------------------------
/src/vm/vm2/compile.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include
4 | #include
5 |
6 | namespace brgen::vm2 {
7 |
8 | void compile(const std::shared_ptr& node, futils::binary::writer& dst);
9 | }
--------------------------------------------------------------------------------
/src/writer/config.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 |
4 | namespace brgen::writer {
5 | struct Config {
6 | bool test_main = false;
7 | bool insert_bit_pos_debug_code = false;
8 | };
9 | } // namespace brgen::writer
10 |
--------------------------------------------------------------------------------
/src/writer/context.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 | #include "config.h"
4 | #include
5 |
6 | namespace brgen::writer {
7 | enum class WriteMode {
8 | unspec,
9 | encode,
10 | decode,
11 | };
12 | struct Context {
13 | WriteMode mode = WriteMode::unspec;
14 | bool def_done = false;
15 | Config config;
16 |
17 | private:
18 | auto do_exchange(auto& m, auto v) {
19 | auto old = m;
20 | m = v;
21 | return futils::helper::defer([=, &m] {
22 | m = old;
23 | });
24 | }
25 |
26 | public:
27 | auto set_write_mode(WriteMode m) {
28 | return do_exchange(mode, m);
29 | }
30 | };
31 | } // namespace brgen::writer
32 |
--------------------------------------------------------------------------------
/src/writer/writer.h:
--------------------------------------------------------------------------------
1 | /*license*/
2 | #pragma once
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace brgen::writer {
11 | using Writer = futils::code::CodeWriter;
12 |
13 | } // namespace brgen::writer
14 |
--------------------------------------------------------------------------------
/test.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | set BASE_PATH=%CD%
4 | set CTEST_OUTPUT_ON_FAILURE=1
5 | call build.bat
6 | ninja -C built/native/Debug test
7 |
--------------------------------------------------------------------------------
/testkit/cmptest.json:
--------------------------------------------------------------------------------
1 | {
2 | "inputs": [
3 | {
4 | "binary": "./example/wire_data/websocket.dat",
5 | "format_name": "Frame",
6 | "file_base": "websocket",
7 | "failure_case": false,
8 | "hex": true
9 | },
10 | {
11 | "binary": "./example/wire_data/websocket.dat",
12 | "format_name": "Frame",
13 | "file_base": "websocket",
14 | "failure_case": true,
15 | "hex": false
16 | },
17 | {
18 | "binary": "./example/wire_data/varint.dat",
19 | "format_name": "TestVarint",
20 | "file_base": "varint_test",
21 | "failure_case": false,
22 | "hex": true
23 | }
24 | ],
25 | "runners": [
26 | {
27 | "file": "./testkit/cpp/config.json"
28 | },
29 | {
30 | "file": "./testkit/go/config.json"
31 | },
32 | {
33 | "file": "./testkit/rust/config.json"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/testkit/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0)
2 | enable_testing()
3 |
4 | project(GeneratedCodeTest CXX)
5 |
6 | set(CMAKE_CXX_STANDARD 20)
7 |
8 | include_directories("${FUTILS_DIR}/src/include")
9 | link_directories("${FUTILS_DIR}/lib")
10 |
11 |
--------------------------------------------------------------------------------
/testkit/cpp/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "suffix": "hpp",
3 | "test_template": "./testkit/cpp/test_template.cpp",
4 | "replace_file_name": "stub.hpp",
5 | "replace_struct_name": "TEST_CLASS",
6 | "build_input_name": "test.cpp",
7 | "build_output_name": "test.exe",
8 | "build_command": [
9 | "python",
10 | "./testkit/cpp/setup.py",
11 | "$INPUT",
12 | "$OUTPUT",
13 | "$ORIGIN",
14 | "$TMPDIR",
15 | "$DEBUG"
16 | ],
17 | "run_command": ["$EXEC", "$INPUT", "$OUTPUT"]
18 | }
19 |
--------------------------------------------------------------------------------
/testkit/cpp/stub.hpp:
--------------------------------------------------------------------------------
1 | //Code generated by json2cpp2
2 | #pragma once
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | struct TEST_CLASS {
11 | ::futils::view::rvec data;
12 | bool encode(::futils::binary::writer& w) const ;
13 | bool decode(::futils::binary::reader& r);
14 | };
15 | inline bool TEST_CLASS::encode(::futils::binary::writer& w) const {
16 | if (!w.write(this->data)) {
17 | return false;
18 | }
19 | return true;
20 | }
21 | inline bool TEST_CLASS::decode(::futils::binary::reader& r) {
22 | if (r.remain().size() < 0) {
23 | return false;
24 | }
25 | if (!r.read(this->data, (r.remain().size() - 0))) {
26 | return false;
27 | }
28 | return true;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/testkit/go/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "suffix": "go",
3 | "test_template": "./testkit/go/test_template.go",
4 | "replace_file_name": "stub.go",
5 | "replace_struct_name": "TEST_CLASS",
6 | "build_input_name": "test.go",
7 | "build_output_name": "test.exe",
8 | "build_command": [
9 | "python",
10 | "./testkit/go/setup.py",
11 | "$INPUT",
12 | "$OUTPUT",
13 | "$ORIGIN",
14 | "$TMPDIR",
15 | "$DEBUG"
16 | ],
17 | "run_command": ["$EXEC", "$INPUT", "$OUTPUT"]
18 | }
19 |
--------------------------------------------------------------------------------
/testkit/go/setup.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import shutil
3 | import subprocess as sp
4 | import re
5 |
6 | INPUT = sys.argv[1]
7 | OUTPUT = sys.argv[2]
8 | ORIGIN = sys.argv[3]
9 | TMPDIR = sys.argv[4]
10 | DEBUG = True if sys.argv[5] == "true" else False
11 |
12 | # replace `package xxx\n` (xxx is any string) with `package main\n`
13 | COMPILED = re.compile("package .*\n")
14 |
15 | with open(INPUT, "r") as fp:
16 | TEXT = fp.read()
17 | if DEBUG:
18 | print(INPUT, "before replace")
19 | print(TEXT)
20 | TEXT = COMPILED.sub("package main", TEXT)
21 | if DEBUG:
22 | print(INPUT, "after replace")
23 | print(TEXT)
24 |
25 | with open(INPUT, "w") as fp:
26 | fp.write(TEXT)
27 |
28 | # copy test target
29 | shutil.copyfile(ORIGIN, TMPDIR + "/target.go")
30 | CMDLINE = ["go", "build", "-o", OUTPUT, "."]
31 | print(f"Run go mod")
32 | code = sp.call(
33 | ["go", "mod", "init", "test"],
34 | stdout=sys.stdout,
35 | stderr=sys.stderr,
36 | cwd=TMPDIR,
37 | )
38 | if code != 0:
39 | exit(code)
40 | print(f"Compiling {INPUT} to {OUTPUT} with {CMDLINE} ")
41 | code = sp.call(
42 | CMDLINE,
43 | stdout=sys.stdout,
44 | stderr=sys.stderr,
45 | cwd=TMPDIR,
46 | )
47 | if code != 0:
48 | exit(code)
49 |
--------------------------------------------------------------------------------
/testkit/go/test_class.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type TEST_CLASS struct {
4 | }
5 |
6 | func (t *TEST_CLASS) Decode(data []byte) (int, error) {
7 | return 0, nil
8 | }
9 |
10 | func (t *TEST_CLASS) Encode() ([]byte, error) {
11 | return nil, nil
12 | }
13 |
--------------------------------------------------------------------------------
/testkit/go/test_template.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | )
7 |
8 | func main() {
9 | inputFile := os.Args[1]
10 | outputFile := os.Args[2]
11 |
12 | input, err := os.ReadFile(inputFile)
13 | if err != nil {
14 | log.Println(err)
15 | os.Exit(2)
16 | }
17 |
18 | var t TEST_CLASS
19 |
20 | n, err := t.Decode(input)
21 |
22 | if err != nil {
23 | log.Println(err)
24 | os.Exit(1)
25 | }
26 |
27 | if n != len(input) {
28 | log.Printf("expect length %d but actual %d", len(input), n)
29 | os.Exit(1)
30 | }
31 |
32 | enc, err := t.Encode()
33 | if err != nil {
34 | log.Println(err)
35 | os.Exit(2)
36 | }
37 |
38 | err = os.WriteFile(outputFile, enc, 0o777)
39 | if err != nil {
40 | log.Println(err)
41 | os.Exit(2)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/testkit/rust/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "test"
7 | version = "0.1.0"
8 |
--------------------------------------------------------------------------------
/testkit/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "test"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testkit/rust/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "suffix": "rs",
3 | "test_template": "./testkit/rust/src/main.rs",
4 | "replace_file_name": "stub.hpp",
5 | "replace_struct_name": "TEST_CLASS",
6 | "build_input_name": "main.rs",
7 | "build_output_name": "test.exe",
8 | "build_command": [
9 | "python",
10 | "./testkit/rust/setup.py",
11 | "$INPUT",
12 | "$OUTPUT",
13 | "$ORIGIN",
14 | "$TMPDIR",
15 | "$DEBUG",
16 | "$CONFIG"
17 | ],
18 | "run_command": ["$EXEC", "$INPUT", "$OUTPUT"]
19 | }
20 |
--------------------------------------------------------------------------------
/testkit/rust/setup.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import subprocess as sp
4 | import pathlib as pl
5 | import shutil
6 | import platform as plt
7 |
8 | if len(sys.argv) != 7:
9 | exit(1)
10 |
11 | INPUT = sys.argv[1]
12 | OUTPUT = sys.argv[2]
13 | ORIGIN = sys.argv[3]
14 | TMPDIR = sys.argv[4]
15 | DEBUG = True if sys.argv[5] == "true" else False
16 | CONFIG = sys.argv[6]
17 |
18 | CONFIG_DIR = pl.Path(CONFIG).parent
19 |
20 |
21 | # run compiler for the test target
22 | # compiler output will be redirected to stdout and stderr
23 | os.mkdir(TMPDIR + "/src")
24 | shutil.copyfile(ORIGIN, TMPDIR + "/src/target.rs")
25 | shutil.copyfile(INPUT, TMPDIR + "/src/main.rs")
26 | shutil.copyfile(
27 | CONFIG_DIR.joinpath("Cargo.toml").absolute().as_posix(), TMPDIR + "/Cargo.toml"
28 | )
29 |
30 | # run cargo build
31 | suffix = ".exe" if plt.system() == "Windows" else ""
32 | build_mode = "Debug" if plt.system() == "Windows" else "debug"
33 | ret = sp.call(
34 | ["cargo", "build", "--manifest-path", TMPDIR + "/Cargo.toml"],
35 | stdout=sys.stdout,
36 | stderr=sys.stderr,
37 | )
38 |
39 | if ret != 0:
40 | exit(ret)
41 | print("Build successful")
42 |
43 |
44 | print("Copying", TMPDIR + f"/target/{build_mode}/test" + suffix, OUTPUT)
45 | shutil.copyfile(TMPDIR + f"/target/{build_mode}/test" + suffix, OUTPUT)
46 | os.chmod(OUTPUT, 0o755)
47 | exit(0)
48 |
--------------------------------------------------------------------------------
/testkit/rust/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::{fs, process::ExitCode};
2 |
3 | mod target;
4 |
5 | fn main() -> ExitCode {
6 | let args: Vec = std::env::args().collect();
7 | let input = match std::fs::read(&args[1]) {
8 | Ok(input) => input,
9 | Err(e) => {
10 | eprintln!("Error reading file: {}", e);
11 | return ExitCode::from(2);
12 | }
13 | };
14 | let decoded = match target::TEST_CLASS::decode_exact(&input[..]) {
15 | Ok(x) => x,
16 | Err(e) => {
17 | eprintln!("Error decoding: {}", e);
18 | return ExitCode::from(1);
19 | }
20 | };
21 | let mut output = Vec::new();
22 | match decoded.encode(&mut output) {
23 | Ok(_) => (),
24 | Err(e) => {
25 | eprintln!("Error encoding: {}", e);
26 | return ExitCode::from(2);
27 | }
28 | }
29 | fs::write(&args[2], &output).unwrap();
30 | ExitCode::from(0)
31 | }
32 |
--------------------------------------------------------------------------------
/web/dev/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@monaco-editor/react": "^4.6.0",
4 | "@types/emscripten": "^1.39.8",
5 | "@types/node": "^22.0.0",
6 | "assert": "^2.1.0",
7 | "ast2ts": "file:../../astlib/ast2ts/out",
8 | "destyle.css": "^4.0.0",
9 | "highlight.js": "^11.9.0",
10 | "json2rust": "file:../../src/tool/json2rust/pkg",
11 | "monaco-editor": "^0.52.0",
12 | "puppeteer": "^24.0.0",
13 | "react": "^19.0.0",
14 | "react-dom": "^19.0.0",
15 | "vscode-languageserver": "^9.0.1",
16 | "wasm-loader": "^1.3.0"
17 | },
18 | "devDependencies": {
19 | "@types/react": "^19.0.0",
20 | "@types/react-dom": "^19.0.0",
21 | "css-loader": "^7.0.0",
22 | "style-loader": "^4.0.0",
23 | "webpack": "^5.94.0",
24 | "webpack-bundle-analyzer": "^4.10.1",
25 | "webpack-cli": "^6.0.0"
26 | },
27 | "scripts": {
28 | "build": "tsc & webpack"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/web/dev/src/compiler-explorer/api.ts:
--------------------------------------------------------------------------------
1 | import { Configuration } from "./types"
2 |
3 | export const compileCpp = async (sourceCode :string) => {
4 | let config :Configuration = {
5 | source: sourceCode,
6 | options: {
7 | userArguments: "-O3 --std=c++20",
8 | compilerOptions: {
9 | skipAsm: false,
10 | executorRequest: false
11 | },
12 | filters: {
13 | binary: false,
14 | binaryObject: false,
15 | commentOnly: false,
16 | demangle: false,
17 | directives: false,
18 | execute: false,
19 | intel: false,
20 | labels: false,
21 | libraryCode: false,
22 | trim: false,
23 | debugCalls: false
24 | },
25 | tools: [],
26 | libraries: []
27 | },
28 | lang: "c++",
29 | allowStoreCodeDebug: false
30 | }
31 | console.log(config);
32 | const compiler = "clang1701";
33 | const compilerExplorerUrl = `https://godbolt.org/api/compiler/${compiler}/compile`;
34 | const response = await fetch(compilerExplorerUrl , {
35 | method: "POST",
36 | headers: {
37 | "Content-Type": "application/json",
38 | "Accept": "application/json"
39 | },
40 | body: JSON.stringify(config)
41 | });
42 | return await response.json();
43 | }
--------------------------------------------------------------------------------
/web/dev/src/compiler-explorer/types.ts:
--------------------------------------------------------------------------------
1 | export interface CompilerOptions {
2 | skipAsm: boolean;
3 | executorRequest: boolean;
4 | }
5 |
6 | export interface Filters {
7 | binary: boolean;
8 | binaryObject: boolean;
9 | commentOnly: boolean;
10 | demangle: boolean;
11 | directives: boolean;
12 | execute: boolean;
13 | intel: boolean;
14 | labels: boolean;
15 | libraryCode: boolean;
16 | trim: boolean;
17 | debugCalls: boolean;
18 | }
19 |
20 | export interface Tool {
21 | id: string;
22 | args: string;
23 | }
24 |
25 | export interface Library {
26 | id: string;
27 | version: string;
28 | }
29 |
30 | export interface Options {
31 | userArguments: string;
32 | compilerOptions: CompilerOptions;
33 | filters: Filters;
34 | tools: Tool[];
35 | libraries: Library[];
36 | }
37 |
38 | export interface Configuration {
39 | source: string;
40 | options: Options;
41 | lang?: string;
42 | allowStoreCodeDebug: boolean;
43 | }
44 |
--------------------------------------------------------------------------------
/web/dev/src/cpp_include.ts:
--------------------------------------------------------------------------------
1 | import { clear } from "console";
2 |
3 |
4 | const RAW_GIT_URL='https://raw.githubusercontent.com/on-keyday/utils/main/src/include'
5 |
6 | const fetchRawGitContent = async (path :string,progress :(t:string)=>void) => {
7 | const url = `${RAW_GIT_URL}/${path}`;
8 | const timer = setTimeout(() => {
9 | progress(path);
10 | },100);
11 | let res = await fetch(url);
12 | if(!res.ok) {
13 | clearTimeout(timer);
14 | throw new Error(`failed to fetch ${url}`);
15 | }
16 | const source = await res.text();
17 | clearTimeout(timer);
18 | return source;
19 | }
20 |
21 | const resolveInclude = async (text :string,progress :(path :string)=>void,included:string[] = []):Promise => {
22 | const include = /#include\s*<(.*\/.*)>/g;
23 | const matched = include.exec(text);
24 | if(!matched) return text;
25 | const path = matched[1];
26 | if(included.includes(path)) {
27 | console.log("duplicated include",path)
28 | const replaced = text.replace(matched[0],'');
29 | return await resolveInclude(replaced,progress,included);
30 | }
31 | const content = await fetchRawGitContent(path,progress);
32 | const removePragmaOnce = content.replace("#pragma once",'');
33 | const replaced = text.replace(matched[0], removePragmaOnce);
34 | return await resolveInclude(replaced,progress, [...included, path]);
35 | }
36 |
37 | export {resolveInclude,RAW_GIT_URL}
38 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/dummy_fs.ts:
--------------------------------------------------------------------------------
1 | import { MyEmscriptenModule } from "./emscripten_mod"
2 |
3 | export const fetchImportFile = async(mod :MyEmscriptenModule,sourceCode :string) => {
4 | const regex = /config\s*\.\s*import\s*\(.*\"(.*)\".*\)/g
5 | const matched = sourceCode.matchAll(regex);
6 | for(const match of matched) {
7 | const path = match[1];
8 | const check = decodeURIComponent(path);
9 | if(!check.endsWith(".bgn")|| check.includes("..")){
10 | continue;
11 | }
12 | const p = await fetch("../example/"+path);
13 | if(!p.ok){
14 | continue; // ignore non exist file
15 | }
16 | const text = await p.text();
17 | console.log("write",path);
18 | mod.FS.writeFile(path,text);
19 | }
20 | const actualOpen = mod.FS.open
21 | mod.FS.open = (path :string,...args) => {
22 | console.log("open",path);
23 | const got = actualOpen(path,...args);
24 | console.log("got",got);
25 | return got;
26 | }
27 | const actualMmap = mod.FS.mmap
28 | mod.FS.mmap = (...args) => {
29 | console.log("mmap",args);
30 | const got = actualMmap(...args);
31 | console.log("got",got);
32 | return got;
33 | }
34 | const actualStat = mod.FS.stat
35 | mod.FS.stat = (path :string) => {
36 | console.log("stat",path);
37 | const got = actualStat(path);
38 | console.log("got",got);
39 | return got;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/emscripten_mod.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export interface MyEmscriptenModule extends EmscriptenModule {
3 | ccall: typeof ccall;
4 | FS :typeof FS
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/file_select.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as stub from "./inputServiceStub.js"
3 |
4 |
5 |
6 |
7 | export interface FileCandidates {
8 | placeHolder :string;
9 | candidates :string[];
10 | }
11 |
12 | const registerFileSelectionCallback = (candidates :()=>Promise,select :(p :string)=>void) => {
13 | stub.cacheRef.fileCandidates = candidates;
14 | stub.cacheRef.fileSelected = (a: any) => {
15 | select(a?.id);
16 | };
17 | }
18 |
19 | export {registerFileSelectionCallback}
20 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/job_mgr.ts:
--------------------------------------------------------------------------------
1 |
2 | import {JobRequest,JobResult, RequestLanguage } from "./msg.js";
3 |
4 | export type TraceID = number|null;
5 | export class JobManager {
6 | #worker :Worker;
7 | #resolverMap = new Map void, reject : (reason :any) => void}>();
8 | #jobID = 0;
9 | constructor(worker :Worker){
10 | this.#worker = worker;
11 | this.#worker.onmessage = this.#onmessage.bind(this);
12 | this.#worker.onerror = this.#onerror.bind(this);
13 | }
14 |
15 | #onerror(e :ErrorEvent) {
16 | console.error(e);
17 | }
18 |
19 | #onmessage(e :MessageEvent) {
20 | const msg = e.data as JobResult;
21 | const resolver = this.#resolverMap.get(msg.jobID);
22 | if(resolver){
23 | this.#resolverMap.delete(msg.jobID);
24 | if(msg.code===0){
25 | resolver.resolve(msg);
26 | }else{
27 | resolver.reject(msg);
28 | }
29 | }
30 | }
31 |
32 | getRequest(traceID :TraceID,lang :RequestLanguage,sourceCode :string) :JobRequest {
33 | const id = this.#jobID;
34 | this.#jobID++;
35 | const req :JobRequest = {
36 | lang,
37 | traceID,
38 | jobID :id,
39 | sourceCode
40 | };
41 | return req;
42 | }
43 |
44 | doRequest(req :JobRequest) :Promise {
45 | return new Promise((resolve,reject) => {
46 | this.#resolverMap.set(req.jobID,{resolve,reject});
47 | this.#worker.postMessage(req);
48 | });
49 | }
50 | }
--------------------------------------------------------------------------------
/web/dev/src/s2j/request_queue.ts:
--------------------------------------------------------------------------------
1 |
2 | import { JobRequest, JobResult } from "./msg"
3 |
4 | export class RequestQueue {
5 | readonly #msgQueue: JobRequest[] = [];
6 | handler: ()=>void = ()=>{};
7 |
8 | constructor(requestHandler: ()=>void) {
9 | globalThis.onmessage = this.#onmessage.bind(this);
10 | this.handler = requestHandler;
11 | }
12 |
13 | #onmessage(e :MessageEvent) {
14 | this.#postRequest(e.data as JobRequest);
15 | this.handler();
16 | }
17 |
18 | #postRequest(ev: JobRequest) {
19 | console.time(`msg queueing ${ev.traceID}.${ev.jobID}`)
20 | this.#msgQueue.push(ev);
21 | }
22 |
23 | repostRequest(ev: JobRequest) {
24 | console.timeEnd(`msg handling ${ev.traceID}.${ev.jobID}`) // cancel previous
25 | console.log(`requeueing ${ev.traceID}.${ev.jobID}`)
26 | console.time(`msg queueing ${ev.traceID}.${ev.jobID}`)
27 | this.#msgQueue.push(ev);
28 | }
29 |
30 | popRequest(): JobRequest | undefined {
31 | const r = this.#msgQueue.shift();
32 | if(r !== undefined){
33 | console.timeEnd(`msg queueing ${r.traceID}.${r.jobID}`)
34 | console.time(`msg handling ${r.traceID}.${r.jobID}`)
35 | }
36 | return r;
37 | }
38 |
39 | postResult(msg: JobResult) {
40 | console.timeEnd(`msg handling ${msg.traceID}.${msg.jobID}`)
41 | console.time(`msg posting ${msg.traceID}.${msg.jobID}`)
42 | //this.#postQueue.push(msg);
43 | globalThis.postMessage(msg);
44 | console.timeEnd(`msg posting ${msg.traceID}.${msg.jobID}`)
45 | }
46 | }
--------------------------------------------------------------------------------
/web/dev/src/s2j/update.tsx:
--------------------------------------------------------------------------------
1 | import { JobResult } from "./msg";
2 |
3 | export class UpdateTracer{
4 | #traceID: number = 0;
5 | getTraceID(){
6 | return ++this.#traceID;
7 | }
8 | editorAlreadyUpdated (s :JobResult) {
9 | if(this.#traceID !== s.traceID){
10 | console.log(`already updated traceID: ${s.traceID} jobID: ${s.jobID}`);
11 | return true;
12 | }
13 | return false;
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/bmgen/bmgen_worker.ts:
--------------------------------------------------------------------------------
1 | import * as bmgen from "../../../lib/bmgen/bmgen.js";
2 | import { JobRequest, RequestLanguage } from "../../msg.js";
3 | import { EmWorkContext} from "../../em_work_ctx.js";
4 | import { MyEmscriptenModule } from "../../emscripten_mod.js";
5 |
6 | const bmgenModule = bmgen.default as EmscriptenModuleFactory;
7 |
8 | const requestCallback = (e:JobRequest, m:MyEmscriptenModule) => {
9 | switch (e.lang) {
10 | case RequestLanguage.BINARY_MODULE:
11 | m.FS.writeFile("/editor.json", e.sourceCode);
12 | if(e.arguments?.includes("--print-instructions")) {
13 | return ["bmgen","-i", "/editor.json"];
14 | }
15 | else {
16 | return ["bmgen","-i", "/editor.json","--base64","-o","-"];
17 | }
18 | default:
19 | return new Error("unknown message type");
20 | }
21 | }
22 |
23 | const bmgenWorker = new EmWorkContext(bmgenModule,requestCallback, () => {
24 | console.log("bmgen worker is ready");
25 | });
26 |
27 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/bmgen/util.ts:
--------------------------------------------------------------------------------
1 | export const base64ToUint8Array = (base64: string) => {
2 | const base64Characters =
3 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
4 | //const base64URLCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
5 |
6 | let cleanedBase64 = base64.replace(/-/g, "+").replace(/_/g, "/").trim();
7 | const padding = (4 - (cleanedBase64.length % 4)) % 4;
8 | cleanedBase64 += "=".repeat(padding);
9 |
10 | const rawLength = cleanedBase64.length;
11 | const decodedLength = (rawLength * 3) / 4 - padding;
12 |
13 | const uint8Array = new Uint8Array(decodedLength);
14 |
15 | let byteIndex = 0;
16 | for (let i = 0; i < rawLength; i += 4) {
17 | const encoded1 = base64Characters.indexOf(cleanedBase64[i]);
18 | const encoded2 = base64Characters.indexOf(cleanedBase64[i + 1]);
19 | const encoded3 = base64Characters.indexOf(cleanedBase64[i + 2]);
20 | const encoded4 = base64Characters.indexOf(cleanedBase64[i + 3]);
21 |
22 | if(encoded1 < 0 || encoded2 < 0 || encoded3 < 0 || encoded4 < 0) {
23 | return new Error("invalid base64 string");
24 | }
25 |
26 | const decoded1 = (encoded1 << 2) | (encoded2 >> 4);
27 | const decoded2 = ((encoded2 & 15) << 4) | (encoded3 >> 2);
28 | const decoded3 = ((encoded3 & 3) << 6) | encoded4;
29 |
30 | uint8Array[byteIndex++] = decoded1;
31 | if (encoded3 !== 64) uint8Array[byteIndex++] = decoded2;
32 | if (encoded4 !== 64) uint8Array[byteIndex++] = decoded3;
33 | }
34 |
35 | return uint8Array;
36 | };
37 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2c_worker.ts:
--------------------------------------------------------------------------------
1 | import * as json2c from "../../lib/json2c.js";
2 | import { JobRequest, RequestLanguage } from "../msg.js";
3 | import { EmWorkContext} from "../em_work_ctx.js";
4 | import { MyEmscriptenModule } from "../emscripten_mod.js";
5 |
6 |
7 | const json2cModule = json2c.default as EmscriptenModuleFactory;
8 |
9 |
10 | const requestCallback = (e:JobRequest, m:MyEmscriptenModule) => {
11 | switch (e.lang) {
12 | case RequestLanguage.C:
13 | m.FS.writeFile("/editor.json", e.sourceCode);
14 | return ["json2c", "/editor.json", "--no-color"];
15 | default:
16 | return new Error("unknown message type");
17 | }
18 | }
19 |
20 |
21 | const j2c_ctx = new EmWorkContext(json2cModule,requestCallback, () => {
22 | console.log("json2c worker is ready");
23 | });
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2cpp2_worker.ts:
--------------------------------------------------------------------------------
1 | import * as json2cpp2 from "../../lib/json2cpp2.js";
2 | import { JobRequest, RequestLanguage } from "../msg.js";
3 | import { EmWorkContext} from "../em_work_ctx.js";
4 | import { MyEmscriptenModule } from "../emscripten_mod.js";
5 |
6 | const json2cpp2Module = json2cpp2.default as EmscriptenModuleFactory;
7 |
8 | const requestCallback = (e:JobRequest, m:MyEmscriptenModule) => {
9 | switch (e.lang) {
10 | case RequestLanguage.CPP:
11 | m.FS.writeFile("/editor.json", e.sourceCode);
12 | return ["json2cpp2", "/editor.json", "--no-color"];
13 | default:
14 | return new Error("unknown message type");
15 | }
16 | }
17 |
18 | const j2c2_ctx = new EmWorkContext(json2cpp2Module,requestCallback, () => {
19 | console.log("json2cpp2 worker is ready");
20 | });
21 |
22 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2go_worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | export { };
4 |
5 | import { JobRequest, RequestLanguage } from "../msg.js";
6 | import { GoWorkContext} from "../go_work_ctx.js";
7 |
8 |
9 |
10 |
11 | const requestCallback = (e:JobRequest) => {
12 | switch (e.lang) {
13 | case RequestLanguage.GO:
14 | return e.sourceCode;
15 | default:
16 | return new Error("unknown message type");
17 | }
18 | }
19 |
20 |
21 | const j2go_ctx = new GoWorkContext(
22 | fetch(new URL("../../lib/json2go.wasm",import.meta.url)).then((r) => r.arrayBuffer()),
23 | requestCallback, () => {
24 | console.log("json2go worker is ready");
25 | });
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2kaitai_worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | export { };
4 |
5 | import { JobRequest, RequestLanguage } from "../msg.js";
6 | import { GoWorkContext} from "../go_work_ctx.js";
7 |
8 |
9 |
10 |
11 | const requestCallback = (e:JobRequest) => {
12 | switch (e.lang) {
13 | case RequestLanguage.KAITAI_STRUCT:
14 | return e.sourceCode;
15 | default:
16 | return new Error("unknown message type");
17 | }
18 | }
19 |
20 |
21 | const j2go_ctx = new GoWorkContext(
22 | fetch(new URL("../../lib/json2kaitai.wasm",import.meta.url)).then((r) => r.arrayBuffer()),
23 | requestCallback, () => {
24 | console.log("json2go worker is ready");
25 | });
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2rust_worker.ts:
--------------------------------------------------------------------------------
1 |
2 | import _wbg_init, { InitOutput, json2rust } from "json2rust"
3 | import { JobRequest, JobResult } from "../msg";
4 |
5 | let _mod :InitOutput | null = null;
6 |
7 | const getWasmModule = async () => {
8 | if (_mod) return _mod;
9 | const mod = await _wbg_init();
10 | if(_mod !== null) return _mod;
11 | _mod = mod;
12 | return _mod;
13 | }
14 |
15 | globalThis.onmessage = async(ev) => {
16 | const data = ev.data as JobRequest;
17 | await getWasmModule();
18 | try {
19 | const result = json2rust(data.sourceCode);
20 | const res :JobResult = {
21 | lang: data.lang,
22 | jobID: data.jobID,
23 | traceID: data.traceID,
24 | originalSourceCode: data.sourceCode,
25 | code: 0,
26 | stdout: result,
27 | stderr: ""
28 | }
29 | globalThis.postMessage(res);
30 | } catch(e) {
31 | console.error(e)
32 | const res :JobResult = {
33 | lang: data.lang,
34 | jobID: data.jobID,
35 | traceID: data.traceID,
36 | originalSourceCode: data.sourceCode,
37 | code: 1,
38 | stdout: "",
39 | stderr: (e as any).toString()
40 | }
41 | globalThis.postMessage(res);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/json2ts_worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as json2ts from "../../lib/json2ts.js";
4 | import { JobRequest, RequestLanguage } from "../msg.js";
5 | import { EmWorkContext} from "../em_work_ctx.js";
6 | import { MyEmscriptenModule } from "../emscripten_mod.js";
7 |
8 |
9 | const json2tsModule = json2ts.default as EmscriptenModuleFactory;
10 |
11 |
12 | const requestCallback = (e:JobRequest, m:MyEmscriptenModule) => {
13 | switch (e.lang) {
14 | case RequestLanguage.TYPESCRIPT:
15 | m.FS.writeFile("/editor.json", e.sourceCode);
16 | return ["json2ts", "/editor.json", "--no-color"];
17 | default:
18 | return new Error("unknown message type");
19 | }
20 | };
21 |
22 | const j2ts_ctx = new EmWorkContext(json2tsModule,requestCallback, () => {
23 | console.log("json2ts worker is ready");
24 | });
25 |
26 |
--------------------------------------------------------------------------------
/web/dev/src/s2j/worker/src2json_worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | export { };
4 |
5 | import * as src2json from "../../lib/src2json.js";
6 | import { RequestLanguage, JobRequest } from "../msg.js";
7 | import { EmWorkContext} from "../em_work_ctx.js";
8 | import { MyEmscriptenModule } from "../emscripten_mod.js";
9 | import { fetchImportFile } from "../dummy_fs.js";
10 |
11 |
12 |
13 | const src2jsonModule = src2json.default as EmscriptenModuleFactory;
14 |
15 |
16 | const requestCallback = async (e:JobRequest, m:MyEmscriptenModule) => {
17 | switch(e.lang) {
18 | case RequestLanguage.JSON_AST:
19 | await fetchImportFile(m,e.sourceCode);
20 | return ["src2json","--argv",e.sourceCode,"--no-color","--print-json","--print-on-error"];
21 | case RequestLanguage.JSON_DEBUG_AST:
22 | await fetchImportFile(m,e.sourceCode);
23 | return ["src2json","--argv",e.sourceCode,"--no-color","--print-json","--print-on-error","--debug-json"];
24 | case RequestLanguage.TOKENIZE:
25 | return ["src2json","--argv",e.sourceCode,"--no-color","--print-json","--print-on-error","--lexer"];
26 | default:
27 | return new Error("unknown message type");
28 | }
29 | }
30 |
31 | const ctx = new EmWorkContext(src2jsonModule,requestCallback,() => {
32 | console.log("src2json worker is ready")
33 | });
34 |
35 |
36 |
--------------------------------------------------------------------------------
/web/dev/src/save-data/save.ts:
--------------------------------------------------------------------------------
1 |
2 | export const save =async (baseUrl :string,sourceCode :string,config :any) => {
3 | const data = JSON.stringify({
4 | sourceCode,
5 | config
6 | });
7 | return await fetch(`${baseUrl}/save`,{
8 | method: 'POST',
9 | body: data,
10 | headers: {
11 | 'Content-Type': 'application/json'
12 | }
13 | }).then(response => {
14 | if (!response.ok) {
15 | throw new Error('not saved correctly');
16 | }
17 | return;
18 | })
19 | }
20 |
21 | export const load = async (baseUrl :string) => {
22 | return await fetch(`${baseUrl}/load`).then(response => {
23 | if (!response.ok) {
24 | throw new Error('not loaded correctly');
25 | }
26 | return response.json() as Promise<{sourceCode: string, config: any}>;
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/web/dev/src/types.ts:
--------------------------------------------------------------------------------
1 | export const enum ElementID {
2 | CONTAINER1 = "container1",
3 | CONTAINER2 = "container2",
4 | TITLE_BAR = "title_bar",
5 | LANGUAGE_SELECT = "language-select",
6 | COPY_BUTTON = "copy-button",
7 | GITHUB_LINK = "github-link",
8 | BALL = "ball",
9 | BALL_BOUND = "ball-bound",
10 | INPUT_LIST = "input-list",
11 | }
12 |
13 | export const enum ConfigKey {
14 | COMMON_FILE_NAME ="file_name",
15 | COMMON_SAVE_LOCATION = "save_url",
16 | CPP_SOURCE_MAP = "source_map",
17 | CPP_EXPAND_INCLUDE = "expand_include",
18 | CPP_USE_ERROR = "use_error",
19 | CPP_USE_RAW_UNION = "use_raw_union",
20 | CPP_CHECK_OVERFLOW = "check_overflow",
21 | CPP_COMPILE_VIA_API = "compile_via_api",
22 | CPP_USE_CONSTEXPR = "use_constexpr",
23 | CPP_ENUM_STRINGER = "enum_stringer",
24 | CPP_ADD_VISIT = "add_visit",
25 | GO_OMIT_MUST_ENCODE = "omit_must_encode",
26 | GO_OMIT_DECODE_EXACT = "omit_decode_exact",
27 | GO_OMIT_VISITOR= "omit_visitors",
28 | GO_OMIT_MARSHAL_JSON = "omit_marshal_json",
29 | TS_JAVASCRIPT = "javascript",
30 | C_MULTI_FILE = "multi_file",
31 | C_OMIT_ERROR_CALLBACK = "omit_error",
32 | C_USE_MEMCPY = "use_memcpy",
33 | C_ZERO_COPY = "zero_copy",
34 |
35 | BM_PRINT_INSTRUCTION = "print_instruction",
36 | RUST2_USE_ASYNC = "use_async",
37 | RUST2_USE_COPY_ON_WRITE_VEC = "copy_on_write_vec",
38 | }
--------------------------------------------------------------------------------
/web/dev/stub/bmgen/bm2cpp.js:
--------------------------------------------------------------------------------
1 | export default function bmgen() {
2 | throw new Error("Not implemented");
3 | }
4 |
--------------------------------------------------------------------------------
/web/dev/stub/bmgen/bm2rust.js:
--------------------------------------------------------------------------------
1 | export default function bmgen() {
2 | throw new Error("Not implemented");
3 | }
4 |
--------------------------------------------------------------------------------
/web/dev/stub/bmgen/bm_caller.js:
--------------------------------------------------------------------------------
1 | export const BM_LANGUAGES = [];
2 |
3 | export const generateBMCode = (ui, traceID, lang, sourceCode) => {};
4 |
5 | export const setBMUIConfig = (config) => {};
6 |
7 | export const BM_LSP_LANGUAGES = {};
8 |
--------------------------------------------------------------------------------
/web/dev/stub/bmgen/bmgen.js:
--------------------------------------------------------------------------------
1 | export default function bmgen() {
2 | throw new Error("Not implemented");
3 | }
4 |
--------------------------------------------------------------------------------
/web/dev/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2022",
4 | "module": "ES2022",
5 | "sourceMap": true,
6 | "outDir": "./out",
7 | "rootDir": "./src",
8 | "allowJs": true,
9 | "strict": true,
10 | "lib": ["ES2022","DOM"],
11 | "paths": {},
12 | "moduleResolution": "Node",
13 | "jsx": "react-jsx"
14 | },
15 | "include": ["**/*.ts", "**/*.tsx"],
16 | }
--------------------------------------------------------------------------------
/web/dev/wasmCopy.js.txt:
--------------------------------------------------------------------------------
1 | const { copyFile } = require("fs");
2 | const path = require("path");
3 | const copyWasm = (p) => {
4 | copyFile(
5 | path.resolve(__dirname, "src/lib/", p),
6 | path.resolve(__dirname, "out/lib/", p),
7 | (err) => {
8 | if (err) {
9 | console.log(err);
10 | }
11 | }
12 | );
13 | };
14 |
15 | copyWasm("src2json.wasm");
16 | //copyWasm("json2cpp.wasm");
17 | copyWasm("json2cpp2.wasm");
18 | copyWasm("json2go.wasm");
19 | copyWasm("json2c.wasm");
20 | copyWasm("json2ts.wasm");
21 | copyWasm("json2kaitai.wasm");
22 |
23 | // for rebrgen
24 | copyWasm("bmgen/bmgen.wasm");
25 |
--------------------------------------------------------------------------------
/web/dev/webpack.config.js:
--------------------------------------------------------------------------------
1 | const process = require("process");
2 | const path = require("path");
3 |
4 | require("./wasmCopy");
5 |
6 | let mode = "development";
7 | if (process.env.WEB_PRODUCTION === "production") {
8 | mode = "production";
9 | }
10 |
11 | module.exports = {
12 | mode: mode,
13 | entry: path.resolve(__dirname, "out/index.js"),
14 | resolve: {
15 | extensions: [".ts", ".tsx", ".js"],
16 | },
17 | module: {
18 | rules: [
19 | {
20 | test: /\.(ts|tsx)$/,
21 | loader: "ts-loader",
22 | },
23 | {
24 | test: /\.css$/,
25 | use: ["style-loader", "css-loader"],
26 | },
27 | ],
28 | },
29 | output: {
30 | filename: "index.js",
31 | path: path.resolve(__dirname, "../public/script"),
32 | assetModuleFilename: "[name][ext]",
33 | },
34 | stats: {
35 | errorDetails: true,
36 | },
37 | };
38 |
39 | if (mode === "development") {
40 | module.exports.devtool = "hidden-source-map";
41 | }
42 |
--------------------------------------------------------------------------------
/web/doc/.hugo_build.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/on-keyday/brgen/950489741469a370ab244f44f59ae6732914cb37/web/doc/.hugo_build.lock
--------------------------------------------------------------------------------
/web/doc/archetypes/default.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = '{{ replace .File.ContentBaseName "-" " " | title }}'
3 | date = {{ .Date }}
4 | draft = true
5 | +++
6 |
--------------------------------------------------------------------------------
/web/doc/content/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = 'Brgen Document'
3 | date = 2023-12-29T13:20:08+09:00
4 | draft = false
5 | +++
6 |
7 | # Brgen Document
8 |
9 | brgen - BinaRy encoder/decoder GENerator のドキュメントです
10 |
11 | TODO(on-keyday): ドキュメント整備
12 |
13 | [開発ページ(GitHub)](https://github.com/on-keyday/brgen)
14 |
15 | [Web Playground](https://on-keyday.github.io/brgen)
16 |
17 | [Overview](https://on-keyday.github.io/brgen/doc/docs/overview)
18 | [Setup](https://on-keyday.github.io/brgen/doc/docs/setup)
19 |
20 | ドキュメントに間違いを見つけた場合や追加したい場合は GitHub Issue で報告するか、修正して Pull Request をしてください。
21 | PR する場合はブランチ名に`doc/`というプリフィックスをつけてください。
22 |
--------------------------------------------------------------------------------
/web/doc/content/docs/change.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Language Change"
3 | weight: 1
4 | # bookFlatSection: false
5 | # bookToc: true
6 | # bookHidden: false
7 | # bookCollapseSection: false
8 | # bookComments: false
9 | # bookSearchExclude: false
10 | ---
11 |
12 | # 言語仕様変更記録
13 |
14 | 言語仕様の変更記録 (24/02/07 ~)
15 |
16 | # 24/01/23 (転記)
17 |
18 | - resolve_primitive_cast を parser の機能に移動、それに伴い --not-resolve-cast オプションを 削除
19 |
20 | ## 24/02/07
21 |
22 | - const_variable を immutable_variable に変更
23 | - 語の意味の明確化
24 |
25 | ## 24/3/??
26 |
27 | - loop 文を for 文に
28 | - for 文に for in 構文を追加
29 |
30 | ## 24/5
31 |
32 | - match 文の条件節において`,`を使ったものを特別扱いする構文を追加
33 |
--------------------------------------------------------------------------------
/web/doc/content/docs/for_ai.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "For AI write"
3 | weight: 1
4 | # bookFlatSection: false
5 | # bookToc: true
6 | # bookHidden: false
7 | # bookCollapseSection: false
8 | # bookComments: false
9 | # bookSearchExclude: false
10 | ---
11 |
12 | # For AI write
13 |
14 | 生成系 AI に brgen フォーマットで書かせるためのテンプレート(TODO(on-keyday): お試し、要改善)
15 |
16 | ## 仕様ベース
17 |
18 | ```
19 | 上記の仕様を元に以下の形式でフォーマットを記述してください。
20 |
21 | # これはコメントです
22 | format A: # これはフォーマット宣言です。Aはフォーマット名を表します。より仕様にあった名前をつけることが推奨されます。
23 | .. # フィールドが何も無い場合はインデントして`..`を書いてください
24 |
25 | format B:
26 | a :u8 # フィールドは「変数名 :型名」で定義します。これは符号なし8bit整数型のフィールドを定義しています。
27 | b :s16 # これは符号あり16ビット整数型のフィールドです。なお次に述べる例外のない限りはビッグエンディアンとして解釈します
28 | c :ul32 # これはリトルエンディアン符号なし32bit整数型のフィールドです。整数型は[us][bl]?[0-9]*
29 |
30 | format C:
31 | fixed_array :[32]u8 # これは配列型のフィールドです。この配列はバイナリデータ表現上では長さ情報を含まず単に32バイトのバイト列のみに変換されます
32 | len :u8
33 | data :[len]u8 # これも配列型です。配列型の長さには単純な数値のみでなく他のフィールドや後述する変数、四則演算やビット演算などの式を使えます。
34 |
35 | format D:
36 | type :u8
37 | if type == 1: # これは条件分岐です。条件分岐を用いることでさまざまな
38 | len :u8
39 | else:
40 | len :u32
41 |
42 | data :[len]u32 # また条件分岐内で定義したフィールドはunionとなり、外側のスコープで使用することも可能です
43 |
44 | match type: # こちらも同じく条件分岐として使えます
45 | 1 => additional_data :u8 # =>を使った形式では単一のフィールドのみを記せます
46 | 2: # :を使った形式では複数のフィールドを記せます
47 | additional_data_len :u8
48 | additional_data :[additional_data_len]u8
49 |
50 | format E:
51 | prefix :u8
52 | data [..]u8 # これは末尾終端パターンです。この場合、dataは入力終端までのデータを表します
53 |
54 | format F:
55 | prefix :u16
56 | data :[..]u8 # このような場合、dataは末尾2バイトを除いた入力データすべてを表します
57 | authentication_code :u16
58 |
59 | ```
60 |
--------------------------------------------------------------------------------
/web/doc/content/docs/generator_dev.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Generator Dev"
3 | weight: 1
4 | # bookFlatSection: false
5 | # bookToc: true
6 | # bookHidden: false
7 | # bookCollapseSection: false
8 | # bookComments: false
9 | # bookSearchExclude: false
10 | ---
11 |
12 | # Generator の開発
13 |
14 | ジェネレーターの開発に関するメモ
15 |
16 | ジェネレーターは必ずしも brgen(lang)の全機能に対応している必要はない。
17 | このリポジトリ付属のジェネレーターはひととおりできるよう対応していくつもりではあるが、
18 | いくつかのパターンには対応できない可能性もある。
19 | その場合は、ぜひ自分でジェネレーターを書いて、その要件を満たすコードを生成できるようにしてほしい。
20 |
21 | ## 基本的な流れ
22 |
23 | 以下擬似コード
24 |
25 | ```py
26 | import ast2py as ast
27 |
28 | def generate_root(prog :ast.Program):
29 | for element in prog.elements:
30 | if isinstance(element,ast.Format):
31 | generate_format(element)
32 |
33 | def generate_format(fmt :ast.Format)
34 | generate_definition(fmt.struct_type)
35 | if fmt.encode_fn is not None:
36 | generate_encoder(fmt.encode_fn.body)
37 | else:
38 | generate_encoder(fmt.body)
39 |
40 | if fmt.decode_fn is not None:
41 | generate_decoder(fmt.decode_fn.body)
42 | else:
43 | generate_decoder(fmt.body)
44 |
45 | def generate_definition(block :ast.IndentBlock):
46 | ...
47 | ```
48 |
49 | ## 開発用ツール
50 |
51 | core/ast/tool(C++)や ast2go/gen(Go) ディレクトリ内にいくつか便利なツールが用意されている
52 |
53 | tool/stringer.h/Stringer クラス(C++)|gen/gen.go/ExprStringer クラス(Go) - Expr 型ノードをその言語の式の文字列に変換する
54 |
55 | tool/sort.h/FormatSorter クラス - Format を AST から抽出して依存関係の順に並び替える(トポロジカルソート)
56 |
57 | ## その他メモ
58 |
59 | Union 実装時にブロックに入ったところで場合分けしたい場合、
60 | IndentBlock(もしくは ScopedStatement)の StructType が StructUnion に登録されているものになるのでそこから対応を探すというように実装するとよい。
61 |
--------------------------------------------------------------------------------
/web/doc/content/docs/metadata.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Metadata"
3 | weight: 1
4 | # bookFlatSection: false
5 | # bookToc: true
6 | # bookHidden: false
7 | # bookCollapseSection: false
8 | # bookComments: false
9 | # bookSearchExclude: false
10 | ---
11 |
12 | # メタデータ
13 |
14 | ジェネレーター共通のメタデータについて述べる。
15 |
16 | ## 共通
17 |
18 | ### 元の URL のメタデータ
19 |
20 | ```
21 | config.url = "https://example.com"
22 | ```
23 |
24 | ### RFC を指定する。
25 |
26 | ```
27 | config.rfc = "https://example.com/url/to/rfc"
28 | ```
29 |
30 | `config.url`を推奨する
31 |
32 | ### 文字列マッピングを指定する
33 |
34 | 生成先コードで特別扱いしたい文字列のマッピング情報を追加する。
35 | 識別子の名前で使われる。
36 |
37 | ```
38 | config.word.map("Id","ID")
39 | ```
40 |
41 | ### フォーマットの順序を変更する
42 |
43 | C++などコード生成時に言語が識別子の宣言順序を厳密に気にするような言語(~~C か C++くらいしかもはやそんな言語は存在しないが~~)のために
44 | ジェネレーター側でトポロジカルソートもどきで順序をソートしているが、再帰的な型などはどうしても正しい順序で生成できないことがあるためそれを補正するためのもの。
45 |
46 | ```
47 | format After:
48 | config.order.after = "Object"
49 | y :Object
50 |
51 | format Object:
52 | x :u8
53 | ```
54 |
55 | この場合定義が`format Object`で生成されたものの直後に挿入される
56 |
57 | ## 言語固有
58 |
59 | ### C++
60 |
61 | #### 名前空間名を指定
62 |
63 | ```
64 | config.cpp.namespace = "namespace name"
65 | ```
66 |
67 | 名前空間名の整合性については保証しない
68 |
69 | #### バイト列の型を指定
70 |
71 | ```
72 | config.cpp.bytes_type = "byte type name"
73 | ```
74 |
75 | バイト列(`[]u8`)の型を指定。デフォルトは`::futils::view::rvec`
76 |
77 | #### 動的配列の型を指定
78 |
79 | ```
80 | config.cpp.vector_type = "vector type"
81 | ```
82 |
83 | 動的配列(`[]T`(T は u8 以外の任意の型))の型を指定。デフォルトは`std::vector`
84 |
85 | ### Go
86 |
87 | #### パッケージ名を指定
88 |
89 | ```
90 | config.go.package = "package name"
91 | ```
92 |
--------------------------------------------------------------------------------
/web/doc/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/on-keyday/brgen/web/doc
2 |
3 | go 1.21
4 |
5 | require github.com/alex-shpak/hugo-book v0.0.0-20241009212754-7c78a39c531a // indirect
6 |
--------------------------------------------------------------------------------
/web/doc/go.sum:
--------------------------------------------------------------------------------
1 | github.com/alex-shpak/hugo-book v0.0.0-20231204233341-118997fa920e h1:vOzQO2BCcgZ+M5W5KkhRHWiryNX/4RuA0iJprMrMUH4=
2 | github.com/alex-shpak/hugo-book v0.0.0-20231204233341-118997fa920e/go.mod h1:L4NMyzbn15fpLIpmmtDg9ZFFyTZzw87/lk7M2bMQ7ds=
3 | github.com/alex-shpak/hugo-book v0.0.0-20241009212754-7c78a39c531a h1:GiRJQYc9Bt8H59/e0w/97i46Ql39CUIdDQjHikd9scA=
4 | github.com/alex-shpak/hugo-book v0.0.0-20241009212754-7c78a39c531a/go.mod h1:L4NMyzbn15fpLIpmmtDg9ZFFyTZzw87/lk7M2bMQ7ds=
5 |
--------------------------------------------------------------------------------
/web/doc/hugo.toml:
--------------------------------------------------------------------------------
1 | baseURL = 'https://on-keyday.github.io/brgen/doc'
2 | languageCode = 'en-us'
3 | title = 'Brgen Document'
4 | publishDir = '../public/doc'
5 |
6 | enableGitInfo = true
7 |
8 | [param]
9 | BookRepo = 'https://on-keyday.github.io/brgen/doc'
10 |
11 | [module]
12 | [[module.imports]]
13 | path = 'github.com/alex-shpak/hugo-book'
14 |
15 | [security]
16 | [security.funcs]
17 | getenv = ['^HUGO_', '^CI$','^RELEASE_TAG$']
18 |
--------------------------------------------------------------------------------
/web/doc/layouts/shortcodes/mermaid.html:
--------------------------------------------------------------------------------
1 |
16 |
38 |
--------------------------------------------------------------------------------