Skip to content

Offer the playground in the pkgdown site #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
branches: [main, master, playground]
pull_request:
branches: [main, master]
release:
Expand Down
113 changes: 113 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repository Overview

tree-sitter-r is an R grammar implementation for [tree-sitter](https://github.com/tree-sitter/tree-sitter), a parser generator tool and incremental parsing library. This repository provides:

1. The core grammar implementation for the R language
2. Node.js bindings for use in JavaScript/TypeScript projects
3. Rust bindings for use in Rust projects
4. R package bindings for use in R projects

The grammar precisely implements R language syntax with a few documented deviations, focusing on providing a useful syntax tree structure for tooling.

## Common Development Commands

### Core Grammar Development

```bash
# Install dependencies
npm install

# Build the grammar and generate parser
tree-sitter generate

# Start the tree-sitter playground for testing
npm run start

# Run parser tests
tree-sitter test

# Generate WASM build
tree-sitter build --wasm
```

### Node.js Package

```bash
# Install dependencies
npm install

# Run Node bindings tests
node --test bindings/node/*_test.js

# Build Node bindings
node-gyp rebuild
```

### Rust Crate

```bash
# Build Rust crate
cargo build

# Test Rust crate
cargo test
```

### R Package

```bash
# Build and check R package
cd bindings/r
R CMD build .
R CMD check treesitter.r_*.tar.gz

# Run R package tests
cd bindings/r
R -e 'devtools::test()'
```

## Repository Structure

- `/grammar.js` - The main grammar definition file defining R syntax rules
- `/src/` - Contains parser implementation files generated by tree-sitter
- `parser.c` - The core parser implementation
- `scanner.c` - Custom scanner for handling context-sensitive tokens
- `/bindings/` - Language-specific bindings
- `/bindings/node/` - Node.js bindings
- `/bindings/rust/` - Rust bindings
- `/bindings/r/` - R package implementation
- `/test/` - Test files for the grammar
- `/test/corpus/` - Syntax test cases
- `/test/highlight/` - Syntax highlighting test cases
- `/test/tags/` - Symbol tagging test cases

## Architecture

The tree-sitter-r project follows the standard tree-sitter architecture:

1. **Grammar Definition**: The core of the project is the `grammar.js` file that defines the grammar rules for parsing R code. It defines all language constructs like expressions, statements, operators, etc.

2. **Generated Parser**: The tree-sitter CLI uses the grammar definition to generate the actual parser implementation in C, which is stored in `src/parser.c`.

3. **Custom Scanner**: For handling context-sensitive aspects of the R syntax, a custom scanner is implemented in `src/scanner.c`. This handles special cases that cannot be expressed using the grammar alone.

4. **Language Bindings**: The project provides bindings for Node.js, Rust, and R, allowing the parser to be used from these languages.

5. **Tests**: Comprehensive tests in the `/test` directory verify the grammar works as expected with different R constructs.

## Working with the Grammar

When modifying the grammar:

1. Edit `grammar.js` to make your changes to the grammar definition
2. Run `tree-sitter generate` to regenerate the parser
3. Test your changes with `tree-sitter test`
4. Use `npm run start` to launch the playground for interactive testing

## Known Grammar Deviations

As noted in the README, there are a few intentional deviations from the R grammar, particularly around how `]]` tokens are handled. See the README.md for details.
1 change: 1 addition & 0 deletions bindings/r/.Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
^cran-comments\.md$
^[\.]?air\.toml$
^\.vscode$
^playground$
24 changes: 21 additions & 3 deletions bindings/r/_pkgdown.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
url: ~

url: https://jennybc.github.io/tree-sitter-r/
development:
mode: auto

template:
package: tidytemplate
bootstrap: 5
includes:
in_header: |
<link href="playground/assets/playground.css" rel="stylesheet">
assets: playground
navbar:
structure:
left:
- intro
- reference
- articles
- tutorials
- playground
right:
- search
- github
components:
playground:
text: Playground
href: playground/index.html

167 changes: 167 additions & 0 deletions bindings/r/pkgdown/assets/playground/assets/playground.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* Basic playground CSS */
:root {
--primary-color: #0550ae;
--bg-color: #ffffff;
--text-color: #333333;
--border-color: #cccccc;
--highlight-color: #e3f2fd;
--error-color: #f44336;
}

body.dark-theme {
--primary-color: #4f83cc;
--bg-color: #1e1e1e;
--text-color: #eaeaea;
--border-color: #555555;
--highlight-color: #284766;
--error-color: #ff6b6b;
}

.playground {
display: flex;
flex-direction: column;
height: calc(100vh - 100px);
min-height: 500px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

.playground-header {
padding: 10px;
font-size: 16px;
font-weight: bold;
border-bottom: 1px solid var(--border-color);
}

.playground-body {
display: flex;
flex: 1;
overflow: hidden;
}

.playground-section {
display: flex;
flex-direction: column;
overflow: hidden;
border-right: 1px solid var(--border-color);
}

.playground-section:last-child {
border-right: none;
}

.playground-section-header {
padding: 5px 10px;
background-color: #f5f5f5;
border-bottom: 1px solid var(--border-color);
font-weight: bold;
font-size: 14px;
}

body.dark-theme .playground-section-header {
background-color: #2d2d2d;
}

.playground-section-content {
flex: 1;
overflow: auto;
position: relative;
}

/* Code editor section */
.code-section {
width: 50%;
}

/* Tree output section */
.tree-section {
width: 50%;
}

/* Optional query section */
.query-section {
width: 100%;
height: 150px;
flex: 0 0 auto;
border-top: 1px solid var(--border-color);
border-right: none;
}

/* Tree nodes */
.tree-row {
padding: 2px 0;
cursor: pointer;
font-family: monospace;
white-space: nowrap;
}

.tree-row:hover {
background-color: var(--highlight-color);
}

.field-name {
color: #9a6700;
}

body.dark-theme .field-name {
color: #d9bf8c;
}

.node-type {
color: #004d40;
}

body.dark-theme .node-type {
color: #4db6ac;
}

.anonymous-node-type {
color: #7d7d7d;
font-style: italic;
}

.tree-node-position {
color: #7d7d7d;
font-size: 80%;
}

/* CodeMirror customizations */
.CodeMirror {
height: 100%;
font-family: monospace;
font-size: 14px;
}

/* Error message */
.error-message {
color: var(--error-color);
padding: 10px;
font-family: monospace;
white-space: pre-wrap;
font-size: 14px;
}

/* Query captures */
.capture-node {
background-color: rgba(86, 156, 214, 0.2);
}

/* Media queries for responsive layout */
@media (max-width: 768px) {
.playground-body {
flex-direction: column;
}

.code-section, .tree-section {
width: 100%;
height: 50%;
}

.playground-section {
border-right: none;
border-bottom: 1px solid var(--border-color);
}

.playground-section:last-child {
border-bottom: none;
}
}
Loading