Add 'vendor/tree-sitter-ruby/' from commit 'f1ff02772248786ed2ed08d827de2555912e777e'

git-subtree-dir: vendor/tree-sitter-ruby
git-subtree-mainline: fc8a9f8d50
git-subtree-split: f1ff027722
pull/70/head
Wilfred Hughes 2021-11-20 00:39:11 +07:00
commit 562634e6bc
42 changed files with 399640 additions and 0 deletions

@ -0,0 +1,2 @@
/src/** linguist-vendored

@ -0,0 +1,8 @@
Checklist:
- [ ] All tests pass in CI.
- [ ] There are sufficient tests for the new fix/feature.
- [ ] Grammar rules have not been renamed unless absolutely necessary.
- [ ] The conflicts section hasn't grown too much.
- [ ] The parser size hasn't grown too much (check the value of STATE_COUNT in src/parser.c).

@ -0,0 +1,31 @@
name: Build/test
on:
push:
branches:
- "**"
pull_request:
branches:
- master
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- run: npm install
- run: npm test
test_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- run: npm install
- run: npm run-script test-windows

@ -0,0 +1,8 @@
Cargo.lock
node_modules
build
*.log
package-lock.json
test.rb
examples/ruby_spec
/target/

@ -0,0 +1,5 @@
test
build
script
examples
target

@ -0,0 +1,31 @@
[package]
name = "tree-sitter-ruby"
description = "Ruby grammar for the tree-sitter parsing library"
version = "0.19.0"
authors = [
"Douglas Creager <dcreager@dcreager.net>",
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
]
license = "MIT"
readme = "bindings/rust/README.md"
keywords = ["incremental", "parsing", "ruby"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-ruby"
edition = "2018"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "0.19"
[build-dependencies]
cc = "1.0"

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Rob Rix
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,10 @@
tree-sitter-ruby
================
[![build](https://github.com/tree-sitter/tree-sitter-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/tree-sitter/tree-sitter-ruby/actions/workflows/ci.yml)
Ruby grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
#### References
* [AST Format of the Whitequark parser](https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md)

@ -0,0 +1,19 @@
{
"targets": [
{
"target_name": "tree_sitter_ruby_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"src/parser.c",
"bindings/node/binding.cc",
"src/scanner.cc"
],
"cflags_c": [
"-std=c99",
]
}
]
}

@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_ruby();
namespace {
NAN_METHOD(New) {}
void Init(Local<Object> exports, Local<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_ruby());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("ruby").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_ruby_binding, Init)
} // namespace

@ -0,0 +1,19 @@
try {
module.exports = require("../../build/Release/tree_sitter_ruby_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_ruby_binding");
} catch (error2) {
if (error2.code !== 'MODULE_NOT_FOUND') {
throw error2;
}
throw error1
}
}
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

@ -0,0 +1,37 @@
# tree-sitter-ruby
This crate provides a Ruby grammar for the [tree-sitter][] parsing library.
To use this crate, add it to the `[dependencies]` section of your `Cargo.toml`
file. (Note that you will probably also need to depend on the
[`tree-sitter`][tree-sitter crate] crate to use the parsed result in any useful
way.)
``` toml
[dependencies]
tree-sitter = "0.17"
tree-sitter-ruby = "0.16"
```
Typically, you will use the [language][language func] function to add this
grammar to a tree-sitter [Parser][], and then use the parser to parse some code:
``` rust
let code = r#"
def double(x)
x * 2
end
"#;
let mut parser = Parser::new();
parser.set_language(tree_sitter_ruby::language()).expect("Error loading Ruby grammar");
let parsed = parser.parse(code, None);
```
If you have any questions, please reach out to us in the [tree-sitter
discussions] page.
[Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
[language func]: https://docs.rs/tree-sitter-ruby/*/tree_sitter_ruby/fn.language.html
[Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
[tree-sitter]: https://tree-sitter.github.io/
[tree-sitter crate]: https://crates.io/crates/tree-sitter
[tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions

@ -0,0 +1,34 @@
use std::env;
use std::path::Path;
extern crate cc;
fn main() {
let src_dir = Path::new("src");
let mut c_config = cc::Build::new();
c_config.include(&src_dir);
c_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
c_config.compile("parser");
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
if env::var("TARGET").unwrap() == "wasm32-wasi" {
cpp_config.flag_if_supported("-fno-exceptions");
}
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
cpp_config.compile("scanner");
}

@ -0,0 +1,72 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2020, tree-sitter-ruby authors.
// See the LICENSE file in this repo for license details.
// ------------------------------------------------------------------------------------------------
//! This crate provides a Ruby grammar for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this grammar to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! use tree_sitter::Parser;
//!
//! let code = r#"
//! def double(x)
//! x * 2
//! end
//! "#;
//! let mut parser = Parser::new();
//! parser.set_language(tree_sitter_ruby::language()).expect("Error loading Ruby grammar");
//! let parsed = parser.parse(code, None);
//! # let parsed = parsed.unwrap();
//! # let root = parsed.root_node();
//! # assert!(!root.has_error());
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter::Language;
extern "C" {
fn tree_sitter_ruby() -> Language;
}
/// Returns the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
unsafe { tree_sitter_ruby() }
}
/// The source of the Ruby tree-sitter grammar description.
pub const GRAMMAR: &'static str = include_str!("../../grammar.js");
/// The syntax highlighting query for this language.
pub const HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights.scm");
/// The local-variable syntax highlighting query for this language.
pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
/// The symbol tagging query for this language.
pub const TAGGING_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading Ruby grammar");
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,37 @@
{
"name": "tree-sitter-ruby",
"version": "0.19.0",
"description": "Ruby grammar for tree-sitter",
"main": "bindings/node",
"keywords": [
"parser",
"lexer"
],
"author": "Rob Rix",
"license": "MIT",
"dependencies": {
"nan": "^2.14.1",
"prebuild-install": "^5.0.0"
},
"devDependencies": {
"prebuild": "^10.0.1",
"tree-sitter-cli": "^0.19.1"
},
"scripts": {
"install": "prebuild-install || node-gyp rebuild",
"prebuild": "prebuild -r electron -t 3.0.0 -t 4.0.0 -t 4.0.4 -t 5.0.0 --strip && prebuild -t 8.16.0 -t 10.12.0 --strip",
"prebuild:upload": "prebuild --upload-all",
"test": "tree-sitter test && script/parse-examples",
"test-windows": "tree-sitter test"
},
"repository": "https://github.com/tree-sitter/tree-sitter-ruby",
"tree-sitter": [
{
"scope": "source.ruby",
"file-types": [
"rb"
],
"injection-regex": "ruby"
}
]
}

@ -0,0 +1,154 @@
; Keywords
[
"alias"
"and"
"begin"
"break"
"case"
"class"
"def"
"do"
"else"
"elsif"
"end"
"ensure"
"for"
"if"
"in"
"module"
"next"
"or"
"rescue"
"retry"
"return"
"then"
"unless"
"until"
"when"
"while"
"yield"
] @keyword
((identifier) @keyword
(#match? @keyword "^(private|protected|public)$"))
; Function calls
((identifier) @function.method.builtin
(#eq? @function.method.builtin "require"))
"defined?" @function.method.builtin
(call
method: [(identifier) (constant)] @function.method)
; Function definitions
(alias (identifier) @function.method)
(setter (identifier) @function.method)
(method name: [(identifier) (constant)] @function.method)
(singleton_method name: [(identifier) (constant)] @function.method)
; Identifiers
[
(class_variable)
(instance_variable)
] @property
((identifier) @constant.builtin
(#match? @constant.builtin "^__(FILE|LINE|ENCODING)__$"))
(file) @constant.builtin
(line) @constant.builtin
(encoding) @constant.builtin
(hash_pattern_norest
"**" @operator
) @constant.builtin
((constant) @constant
(#match? @constant "^[A-Z\\d_]+$"))
(constant) @constructor
(self) @variable.builtin
(super) @variable.builtin
(block_parameter (identifier) @variable.parameter)
(block_parameters (identifier) @variable.parameter)
(destructured_parameter (identifier) @variable.parameter)
(hash_splat_parameter (identifier) @variable.parameter)
(lambda_parameters (identifier) @variable.parameter)
(method_parameters (identifier) @variable.parameter)
(splat_parameter (identifier) @variable.parameter)
(keyword_parameter name: (identifier) @variable.parameter)
(optional_parameter name: (identifier) @variable.parameter)
((identifier) @function.method
(#is-not? local))
(identifier) @variable
; Literals
[
(string)
(bare_string)
(subshell)
(heredoc_body)
(heredoc_beginning)
] @string
[
(simple_symbol)
(delimited_symbol)
(hash_key_symbol)
(bare_symbol)
] @string.special.symbol
(regex) @string.special.regex
(escape_sequence) @escape
[
(integer)
(float)
] @number
[
(nil)
(true)
(false)
]@constant.builtin
(interpolation
"#{" @punctuation.special
"}" @punctuation.special) @embedded
(comment) @comment
; Operators
[
"="
"=>"
"->"
] @operator
[
","
";"
"."
] @punctuation.delimiter
[
"("
")"
"["
"]"
"{"
"}"
"%w("
"%i("
] @punctuation.bracket

@ -0,0 +1,27 @@
((method) @local.scope
(#set! local.scope-inherits false))
[
(lambda)
(block)
(do_block)
] @local.scope
(block_parameter (identifier) @local.definition)
(block_parameters (identifier) @local.definition)
(destructured_parameter (identifier) @local.definition)
(hash_splat_parameter (identifier) @local.definition)
(lambda_parameters (identifier) @local.definition)
(method_parameters (identifier) @local.definition)
(splat_parameter (identifier) @local.definition)
(keyword_parameter name: (identifier) @local.definition)
(optional_parameter name: (identifier) @local.definition)
(identifier) @local.reference
(assignment left: (identifier) @local.definition)
(operator_assignment left: (identifier) @local.definition)
(left_assignment_list (identifier) @local.definition)
(rest_assignment (identifier) @local.definition)
(destructured_left_assignment (identifier) @local.definition)

@ -0,0 +1,64 @@
; Method definitions
(
(comment)* @doc
.
[
(method
name: (_) @name) @definition.method
(singleton_method
name: (_) @name) @definition.method
]
(#strip! @doc "^#\\s*")
(#select-adjacent! @doc @definition.method)
)
(alias
name: (_) @name) @definition.method
(setter
(identifier) @ignore)
; Class definitions
(
(comment)* @doc
.
[
(class
name: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.class
(singleton_class
value: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.class
]
(#strip! @doc "^#\\s*")
(#select-adjacent! @doc @definition.class)
)
; Module definitions
(
(module
name: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.module
)
; Calls
(call method: (identifier) @name) @reference.call
(
[(identifier) (constant)] @name @reference.call
(#is-not? local)
(#not-match? @name "^(lambda|load|require|require_relative|__FILE__|__LINE__)$")
)

@ -0,0 +1,5 @@
examples/ruby_spec/command_line/fixtures/bad_syntax.rb
examples/ruby_spec/command_line/fixtures/freeze_flag_required_diff_enc.rb
examples/ruby_spec/core/enumerable/shared/inject.rb
examples/ruby_spec/language/fixtures/freeze_magic_comment_required_diff_enc.rb
examples/ruby_spec/language/string_spec.rb

@ -0,0 +1,39 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
function checkout_at() {
repo=$1; url=$2; sha=$3
if [ ! -d "$repo" ]; then
git clone "https://github.com/$url" "$repo"
fi
pushd "$repo"
git fetch && git reset --hard "$sha"
popd
}
checkout_at "examples/ruby_spec" "ruby/spec" "c3e6b9017926f44a76e2b966c4dd35fa84c4cd3b"
# TODO: Fix these known issues:
# - [ ] String literals delimited with `=`, e.g. `%=hi=`
# - [ ] Issue with << operator mistaken for heredocs, e.g. `send(@method){|r,i| r<<i}`
# - [ ] defined as local var, e.g. `defn.send(@method, defined)`
# - [ ] Unicode character in symbols, variables, etc, e.g. `:êad`
# - [ ] Unicode characters in constants, e.g. `CS_CONSTλ = :const_unicode`
known_failures="$(cat script/known_failures.txt)"
tree-sitter parse -q \
'examples/**/*.rb' \
$(for file in $known_failures; do echo "!${file}"; done)
example_count=$(find examples -name '*.rb' | wc -l)
failure_count=$(wc -w <<< "$known_failures")
success_count=$(( $example_count - $failure_count ))
success_percent=$(bc -l <<< "100*${success_count}/${example_count}")
printf \
"Successfully parsed %d of %d example files (%.1f%%)\n" \
$success_count $example_count $success_percent

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,223 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value, \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -0,0 +1,84 @@
========
comments
========
# anything else here should be ignored
---
(program (comment))
===================
empty block comment
===================
=begin
=end
---
(program (comment))
======================
one-line block comment
======================
=begin
whatever
=end
---
(program (comment))
======================================
block comment with comment after begin
======================================
=begin rdoc
=end
---
(program (comment))
=========================
multi-line block comments
=========================
=begin
whatever
multiple lines of whatever
=end
---
(program (comment))
=========================
multi-line block comments followed by standard comment
=========================
=begin
whatever
multiple lines of whatever
=end
# Another comment
---
(program (comment) (comment))
=========================
multi-line block comments with almost end
=========================
=begin
=e
=en
=end
---
(program (comment))

@ -0,0 +1,636 @@
=====================
empty while statement
=====================
while foo do
end
---
(program (while
condition: (identifier)
body: (do)))
================
while without do
================
while foo
end
---
(program (while
condition: (identifier)
body: (do)))
=========================
while statement with body
=========================
while foo do
bar
end
---
(program (while
condition: (identifier)
body: (do (identifier))))
=====================
empty until statement
=====================
until foo bar do
end
---
(program (until
condition: (call
method: (identifier)
arguments: (argument_list (identifier)))
body: (do)))
=========================
until statement with body
=========================
until foo do
bar
end
---
(program (until
(identifier)
(do (identifier))))
==================
empty if statement
==================
if foo
end
---
(program (if
condition: (identifier)))
=======================
empty if/else statement
=======================
if foo then
else
end
if true then ;; 123; end
---
(program
(if
condition: (identifier)
consequence: (then)
alternative: (else))
(if
condition: (true)
consequence: (then
(empty_statement)
(empty_statement)
(integer))))
==================================
single-line if then else statement
==================================
if foo then bar else quux end
---
(program (if (identifier) (then (identifier)) (else (identifier))))
========
if elsif
========
if foo
bar
elsif quux
baz
end
---
(program
(if (identifier) (then (identifier))
(elsif (identifier) (then (identifier)))))
=============
if elsif else
=============
if foo
bar
elsif quux
baz
else
bat
end
---
(program
(if (identifier)
(then (identifier))
(elsif
(identifier)
(then (identifier))
(else (identifier)))))
======================
empty unless statement
======================
unless foo
end
---
(program (unless (identifier)))
================================
empty unless statement with then
================================
unless foo then
hi
end
---
(program
(unless
condition: (identifier)
consequence: (then
(identifier))))
================================
empty unless statement with else
================================
unless foo
else
end
---
(program
(unless
condition: (identifier)
alternative: (else)))
===
for
===
for x in y do
f
end
for x, in y
f
end
for x, *y in z do
f
end
for (k, v) in y do
f
end
---
(program
(for
pattern: (identifier)
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(identifier))
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(identifier)
(rest_assignment (identifier)))
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(destructured_left_assignment
(identifier)
(identifier)))
value: (in (identifier))
body: (do (identifier))))
==============
for without do
==============
for x in y
f
end
---
(program (for
pattern: (identifier)
value: (in (identifier))
body: (do (identifier))))
==============
next
==============
for x in y
next
end
---
(program (for (identifier) (in (identifier)) (do (next))))
==============
retry
==============
for x in y
retry
end
---
(program (for
pattern: (identifier)
value: (in (identifier))
body: (do (retry))))
==============
break
==============
while b
break
end
---
(program (while (identifier) (do (break))))
==============
redo
==============
while b
redo
end
---
(program (while (identifier) (do (redo))))
===========
empty begin
===========
begin
end
---
(program (begin))
===============
begin with body
===============
begin
foo
end
---
(program (begin (identifier)))
===============
begin with else
===============
begin
foo
else
bar
end
---
(program
(begin (identifier)
(else (identifier))))
===============
begin with ensure
===============
begin
foo
ensure
bar
end
---
(program
(begin (identifier)
(ensure (identifier))))
=======================
begin with empty rescue
=======================
begin
rescue
end
begin
rescue then
end
begin
rescue
bar
end
---
(program
(begin (rescue))
(begin (rescue (then)))
(begin (rescue (then (identifier)))))
===========================
begin with rescue with args
===========================
begin
rescue x
end
begin
rescue x then
end
begin
rescue x
bar
end
begin
rescue => x
bar
end
begin
rescue x, y
bar
end
begin
rescue Error => x
end
begin
rescue Error => x
bar
end
---
(program
(begin (rescue (exceptions (identifier))))
(begin (rescue (exceptions (identifier)) (then)))
(begin (rescue (exceptions (identifier)) (then (identifier))))
(begin (rescue (exception_variable (identifier)) (then (identifier))))
(begin (rescue (exceptions (identifier) (identifier)) (then (identifier))))
(begin (rescue (exceptions (constant)) (exception_variable (identifier))))
(begin (rescue (exceptions (constant)) (exception_variable (identifier)) (then (identifier)))))
===========================
begin with rescue with splat args
===========================
begin
rescue *args
end
---
(program (begin (rescue (exceptions (splat_argument (identifier))))))
=================
rescue modifier
=================
foo rescue nil
if foo rescue nil
elsif bar rescue nil
end
unless foo rescue nil
end
---
(program
(rescue_modifier (identifier) (nil))
(if (rescue_modifier (identifier) (nil)) (elsif (rescue_modifier (identifier) (nil))))
(unless (rescue_modifier (identifier) (nil))))
============================
begin with all the trimmings
============================
begin
foo
rescue x
retry
else
quux
ensure
baz
end
---
(program
(begin (identifier)
(rescue (exceptions (identifier)) (then (retry)))
(else (identifier))
(ensure (identifier))))
======
return
======
return foo
---
(program (return (argument_list (identifier))))
====================
return without value
====================
return
---
(program (return))
====
case
====
case foo
when bar
end
---
(program
(case (identifier)
(when (pattern (identifier)))))
==============
case with else
==============
case foo
when bar
else
end
case key
when bar
else; leaf
end
---
(program
(case
(identifier)
(when (pattern (identifier)))
(else))
(case
(identifier)
(when (pattern (identifier)))
(else (identifier))))
==============================
case with multiple when blocks
==============================
case a
when b
c
when d
e
else
f
end
---
(program
(case (identifier)
(when (pattern (identifier)) (then (identifier)))
(when (pattern (identifier)) (then (identifier)))
(else (identifier))))
==============================
case without line break
==============================
case a when b
c end
---
(program
(case (identifier)
(when
(pattern
(identifier))
(then
(identifier)))))
==============================
case with splat parameter in when
==============================
case a
when *foo
c
end
---
(program
(case
(identifier)
(when
(pattern (splat_argument (identifier)))
(then (identifier)))))
==============
case with assignment
==============
x = case foo
when bar
else
end
---
(program (assignment (identifier)
(case (identifier)
(when (pattern (identifier)))
(else))))
==============
case with expression
==============
x = case foo = bar | baz
when bar
else
end
---
(program (assignment (identifier)
(case (assignment (identifier) (binary (identifier) (identifier)))
(when (pattern (identifier)))
(else))))

@ -0,0 +1,621 @@
============
empty method
============
def foo
end
def foo?
end
def foo!
end
---
(program
(method (identifier))
(method (identifier))
(method (identifier)))
=====================
method with body
=====================
def foo
bar
end
---
(program (method (identifier) (identifier)))
=====================
"end"-less method
=====================
def foo = bar
def foo() = bar
def foo(x) = bar
def Object.foo = bar
def Object.foo (x) = bar
def foo() = bar rescue (print "error")
---
(program
(method (identifier) (identifier))
(method (identifier) (method_parameters) (identifier))
(method (identifier) (method_parameters (identifier)) (identifier))
(singleton_method (constant) (identifier) (identifier))
(singleton_method (constant) (identifier) (method_parameters (identifier)) (identifier))
(method (identifier) (method_parameters)
(rescue_modifier
(identifier)
(parenthesized_statements (call (identifier) (argument_list (string (string_content)))))
)
)
)
===========================
method as attribute setter
===========================
def foo=
end
---
(program (method (setter (identifier))))
==============================
method definition of operators
==============================
def `(a)
"`"
end
def -@(a)
end
def %(a)
end
def ..(a)
end
def !~(a)
end
---
(program
(method (operator) (method_parameters (identifier)) (string (string_content)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier))))
===================================================
method with forward slash name and regex ambiguity
===================================================
puts /(/
def /(name)
end
def / name
end
---
(program
(call (identifier) (argument_list (regex (string_content))))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier))))
===========================
method with call to super
===========================
def foo
super
end
def foo
bar.baz { super }
end
def foo
super.bar a, b
end
---
(program
(method (identifier) (super))
(method
(identifier)
(call (identifier) (identifier) (block (super))))
(method
(identifier)
(call (super) (identifier) (argument_list (identifier) (identifier)))))
===========================
method with args
===========================
def foo(bar)
end
def foo(bar); end
def foo(bar) end
---
(program
(method (identifier) (method_parameters (identifier)))
(method (identifier) (method_parameters (identifier)))
(method (identifier) (method_parameters (identifier))))
================================
method with unparenthesized args
================================
def foo bar
end
---
(program (method (identifier) (method_parameters (identifier))))
=========================
method with multiple args
=========================
def foo(bar, quux)
end
---
(program (method (identifier) (method_parameters (identifier) (identifier))))
=========================================
method with multiple unparenthesized args
=========================================
def foo bar, quux
end
---
(program (method (identifier) (method_parameters (identifier) (identifier))))
=========================================
method with keyword parameters
=========================================
def foo(bar: nil, baz:)
end
---
(program
(method (identifier)
(method_parameters
(keyword_parameter (identifier) (nil))
(keyword_parameter (identifier)))))
=========================================
method with default parameters
=========================================
def foo(bar = nil)
end
def foo(bar=nil)
end
---
(program
(method (identifier)
(method_parameters (optional_parameter (identifier) (nil))))
(method (identifier)
(method_parameters (optional_parameter (identifier) (nil)))))
=========================================
method with interesting params
=========================================
def foo(*options)
end
def foo(x, *options)
end
def foo(x, *options, y)
end
def foo(**options)
end
def foo(name:, **)
end
def foo(&block)
end
def foo(...)
super(...)
end
def foo(a, b, ...)
bar(b, ...)
end
---
(program
(method (identifier) (method_parameters (splat_parameter (identifier))))
(method (identifier) (method_parameters (identifier) (splat_parameter (identifier))))
(method (identifier) (method_parameters (identifier) (splat_parameter (identifier)) (identifier)))
(method (identifier) (method_parameters (hash_splat_parameter (identifier))))
(method (identifier) (method_parameters (keyword_parameter (identifier)) (hash_splat_parameter)))
(method (identifier) (method_parameters (block_parameter (identifier))))
(method (identifier) (method_parameters (forward_parameter))
(call (super) (argument_list (forward_argument)))
)
(method (identifier) (method_parameters (identifier) (identifier) (forward_parameter))
(call (identifier) (argument_list (identifier) (forward_argument)))
)
)
=========================================
singleton method
=========================================
def self.foo
end
---
(program (singleton_method (self) (identifier)))
=========================================
singleton method with body
=========================================
def self.foo
bar
end
---
(program (singleton_method (self) (identifier) (identifier)))
=========================================
singleton method with arg
=========================================
def self.foo(bar)
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier))))
=========================================
singleton method with un-parenthesized arg
=========================================
def self.foo bar
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier))))
=========================================
singleton method with args
=========================================
def self.foo(bar, baz)
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier))))
=========================================
singleton method with un-parenthesized args
=========================================
def self.foo bar, baz
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier))))
===========
empty class
===========
class Foo
end
class Foo; end
class Foo::Bar
end
class ::Foo::Bar
end
class Cß
end
---
(program
(class (constant))
(class (constant))
(class (scope_resolution (constant) (constant)))
(class (scope_resolution (scope_resolution (constant)) (constant)))
(class (constant)))
==============
empty subclass
==============
class Foo < Bar
end
---
(program (class (constant) (superclass (constant))))
==================================
empty subclass of namespaced class
==================================
class Foo < Bar::Quux
end
class Foo < ::Bar
end
class Foo < Bar::Baz.new(foo)
end
---
(program
(class
(constant)
(superclass (scope_resolution (constant) (constant))))
(class
(constant)
(superclass (scope_resolution (constant))))
(class
(constant)
(superclass (call (scope_resolution (constant) (constant)) (identifier) (argument_list (identifier))))))
=======================================
unparenthesized call as superclass
=======================================
class A < B.new \
:c,
:d
end
---
(program (class
name: (constant)
superclass: (superclass (call
receiver: (constant)
method: (identifier)
arguments: (argument_list
(simple_symbol)
(simple_symbol))))))
===============
class with body
===============
class Foo
def bar
end
end
---
(program (class (constant) (method (identifier))))
=========================================
class within dynamically-computed module
=========================================
class foo()::Bar
end
---
(program (class (scope_resolution (call (identifier) (argument_list)) (constant))))
===============
singleton class
===============
class << self
end
class <<self
end
class << Foo
end
class << Foo::Bar
end
---
(program
(singleton_class (self))
(singleton_class (self))
(singleton_class (constant))
(singleton_class (scope_resolution (constant) (constant))))
============
empty module
============
module Foo
end
module Foo::Bar
end
---
(program
(module (constant))
(module (scope_resolution (constant) (constant))))
================
module with body
================
module Foo
def bar
end
end
---
(program (module (constant) (method (identifier))))
========================
module without semicolon
========================
module Foo end
---
(program (module (constant)))
=======
__END__
=======
word
__END__
word
x
ab
d
---
(program (identifier) (uninterpreted))
==============================
module with class with methods
==============================
module A
class B < C
include D::E.f.g
attr_reader :h
# i
def j
k
end
def self.l
end
end
end
---
(program (module (constant)
(class (constant) (superclass (constant))
(call (identifier) (argument_list
(call
(call
(scope_resolution (constant) (constant))
(identifier))
(identifier))))
(call (identifier) (argument_list (simple_symbol)))
(comment)
(method (identifier) (identifier))
(singleton_method (self) (identifier)))))
===========
empty BEGIN block
===========
BEGIN {
}
---
(program (begin_block))
===========
BEGIN block
===========
baz
BEGIN {
foo
}
bar
---
(program (identifier) (begin_block (identifier)) (identifier))
===========
empty END block
===========
END {
}
---
(program (end_block))
===========
END block
===========
baz
END {
foo
}
bar
---
(program (identifier) (end_block (identifier)) (identifier))

@ -0,0 +1,42 @@
==========================
Heredocs with errors
==========================
joins(<<~SQL(
b
SQL
c
---
(program
(call
method: (identifier)
(ERROR (heredoc_beginning))
arguments: (argument_list
(heredoc_body (heredoc_content) (heredoc_end))
(identifier)
(MISSING ")"))))
====================================
Heredocs
====================================
joins(<<-SQL
b
SQL
)
------------------------------------
(program
(call
method: (identifier)
arguments: (argument_list
(heredoc_beginning)
(heredoc_body (heredoc_content) (heredoc_end))
)
)
)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,23 @@
=================
CRLF line endings
=================
puts 'hi'
x = foo()
---
(program
(call (identifier) (argument_list (string (string_content))))
(assignment (identifier) (call (identifier) (argument_list))))
=======================
CRLF multiline comments
=======================
=begin
=end
---
(program (comment))

File diff suppressed because it is too large Load Diff

@ -0,0 +1,300 @@
================
pattern matching
================
case expr
in 5 then true
else false
end
case expr
in x unless x < 0
then true
in x if x < 0
then true
else false
end
case expr
in 5
in 5,
in 1, 2
in 1, 2,
in 1, 2, 3
in 1, 2, 3,
in 1, 2, 3, *
in 1, *x, 3
in *
in *, 3, 4
in *, 3, *
in *a, 3, *b
in a:
in a: 5
in a: 5,
in a: 5, b:, **
in a: 5, b:, **map
in a: 5, b:, **nil
in **nil
in [5]
in [5,]
in [1, 2]
in [1, 2,]
in [1, 2, 3]
in [1, 2, 3,]
in [1, 2, 3, *]
in [1, *x, 3]
in [*]
in [*, 3, 4]
in [*, 3, *]
in [*a, 3, *b]
in {a:}
in {a: 5}
in {a: 5,}
in {a: 5, b:, **}
in {a: 5, b:, **map}
in {a: 5, b:, **nil}
in {**nil}
in {}
in []
end
-----
(program
(case_match (identifier)
(in_clause
(integer)
(then (true))
)
(else (false)))
(case_match (identifier)
(in_clause
(pattern_variable (identifier))
(unless_guard (binary (identifier) (integer)))
(then (true))
)
(in_clause
(pattern_variable (identifier))
(if_guard (binary (identifier) (integer)))
(then (true))
)
(else (false))
)
(case_match (identifier)
(in_clause (integer))
(in_clause (array_pattern (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (array_pattern_rest (identifier)) (integer)))
(in_clause (array_pattern (array_pattern_rest)))
(in_clause (array_pattern (array_pattern_rest) (integer) (integer)))
(in_clause (find_pattern (array_pattern_rest) (integer) (array_pattern_rest)))
(in_clause (find_pattern (array_pattern_rest (identifier)) (integer) (array_pattern_rest (identifier))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_rest)))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_rest (identifier))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_norest)))
(in_clause (hash_pattern (hash_pattern_norest)))
(in_clause (array_pattern (integer)))
(in_clause (array_pattern (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (integer) (integer) (array_pattern_rest)))
(in_clause (array_pattern (integer) (array_pattern_rest (identifier)) (integer)))
(in_clause (array_pattern (array_pattern_rest)))
(in_clause (array_pattern (array_pattern_rest) (integer) (integer)))
(in_clause (find_pattern (array_pattern_rest) (integer) (array_pattern_rest)))
(in_clause (find_pattern (array_pattern_rest (identifier)) (integer) (array_pattern_rest (identifier))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_rest)))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_rest (identifier))))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol) (integer)) (pattern_pair (hash_key_symbol)) (hash_pattern_norest)))
(in_clause (hash_pattern (hash_pattern_norest)))
(in_clause (hash_pattern))
(in_clause (array_pattern))
)
)
=====================
more pattern matching
=====================
case expr
in 5
in ^foo
in var
in "string"
in %w(foo bar)
in %i(foo bar)
in /.*abc[0-9]/
in 5 .. 10
in .. 10
in 5 ..
in 5 => x
in 5 | ^foo | var | "string"
in Foo
in Foo::Bar
in ::Foo::Bar
in nil | self | true | false | __LINE__ | __FILE__ | __ENCODING__
in -> x { x == 10 }
in :foo
in :"foo bar"
in -5 | +10
end
--------
(program
(case_match (identifier)
(in_clause (integer))
(in_clause (variable_reference_pattern (identifier)))
(in_clause (pattern_variable (identifier)))
(in_clause (string (string_content)))
(in_clause (string_array (bare_string (string_content)) (bare_string (string_content))))
(in_clause (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content))))
(in_clause (regex (string_content)))
(in_clause (pattern_range (integer) (integer)))
(in_clause (pattern_range (integer)))
(in_clause (pattern_range (integer)))
(in_clause (as_pattern (integer) (identifier)))
(in_clause
(alternative_pattern
(integer)
(variable_reference_pattern (identifier))
(pattern_variable (identifier))
(string (string_content))
)
)
(in_clause (pattern_constant (constant)))
(in_clause (pattern_constant_resolution (pattern_constant (constant)) (constant)))
(in_clause (pattern_constant_resolution (pattern_constant_resolution (constant)) (constant)))
(in_clause
(alternative_pattern
(nil)
(self)
(true)
(false)
(line)
(file)
(encoding)
)
)
(in_clause (lambda (lambda_parameters (identifier)) (block (binary (identifier) (integer)))))
(in_clause (simple_symbol))
(in_clause (delimited_symbol (string_content)))
(in_clause
(alternative_pattern
(unary (integer))
(unary (integer))
)
)
)
)
==============
array patterns
==============
case expr
in [];
in [x];
in [x, ];
in Foo::Bar[];
in Foo();
in Bar(*);
in Bar(a, b, *c, d, e);
end
--------------
(program
(case_match (identifier)
(in_clause (array_pattern))
(in_clause (array_pattern (pattern_variable (identifier))))
(in_clause (array_pattern (pattern_variable (identifier)) (array_pattern_rest)))
(in_clause (array_pattern (pattern_constant_resolution (pattern_constant (constant)) (constant))))
(in_clause (array_pattern (pattern_constant (constant))))
(in_clause (array_pattern (pattern_constant (constant)) (array_pattern_rest)))
(in_clause
(array_pattern
(pattern_constant (constant))
(pattern_variable (identifier))
(pattern_variable (identifier))
(array_pattern_rest (identifier))
(pattern_variable (identifier))
(pattern_variable (identifier))
)
)
)
)
=============
find patterns
=============
case expr
in [*, x, *];
in [*x, 1, 2, *y];
in Foo::Bar[*, 1, *];
in Foo(*, Bar, *);
end
-------------
(program
(case_match (identifier)
(in_clause (find_pattern (array_pattern_rest) (pattern_variable (identifier)) (array_pattern_rest)))
(in_clause (find_pattern (array_pattern_rest (identifier)) (integer) (integer) (array_pattern_rest (identifier))))
(in_clause (find_pattern
(pattern_constant_resolution (pattern_constant (constant)) (constant))
(array_pattern_rest)
(integer)
(array_pattern_rest))
)
(in_clause (find_pattern (pattern_constant (constant)) (array_pattern_rest) (pattern_constant (constant)) (array_pattern_rest)))
)
)
=============
hash patterns
=============
case expr
in {};
in {x:};
in Foo::Bar[ x:1 ];
in Foo::Bar[ x:1, a:, **rest ];
in Foo( y:);
in Bar( ** );
in Bar( a: 1, **nil);
end
-------------
(program (case_match (identifier)
(in_clause (hash_pattern))
(in_clause (hash_pattern (pattern_pair (hash_key_symbol))))
(in_clause (hash_pattern
(pattern_constant_resolution (pattern_constant (constant)) (constant))
(pattern_pair (hash_key_symbol) (integer))
))
(in_clause (hash_pattern
(pattern_constant_resolution (pattern_constant (constant)) (constant))
(pattern_pair (hash_key_symbol) (integer))
(pattern_pair (hash_key_symbol))
(hash_pattern_rest (identifier))
))
(in_clause (hash_pattern (pattern_constant (constant)) (pattern_pair (hash_key_symbol))))
(in_clause (hash_pattern (pattern_constant (constant)) (hash_pattern_rest)))
(in_clause (hash_pattern (pattern_constant (constant)) (pattern_pair (hash_key_symbol) (integer)) (hash_pattern_norest)))
)
)

@ -0,0 +1,9 @@
==================================
Single CR characters as whitespace
==================================
puts "hi"
---
(program (call (identifier) (argument_list (string (string_content)))))

@ -0,0 +1,92 @@
====================
conditional modifier
====================
foo if bar
return if false
return true if foo bar
return nil if foo
---
(program
(if_modifier
(identifier)
(identifier))
(if_modifier
(return)
(false))
(if_modifier
(return (argument_list (true)))
(call (identifier) (argument_list (identifier))))
(if_modifier
(return (argument_list (nil)))
(identifier)))
==============
while modifier
==============
foo while bar
---
(program (while_modifier
body: (identifier)
condition: (identifier)))
===============
unless modifier
===============
foo unless bar
---
(program (unless_modifier
body: (identifier)
condition: (identifier)))
==============
until modifier
==============
foo until bar
---
(program (until_modifier (identifier) (identifier)))
========
alias
========
alias :foo :bar
alias foo bar
alias $FOO $&
alias foo +
---
(program
(alias (simple_symbol) (simple_symbol))
(alias (identifier) (identifier))
(alias (global_variable) (global_variable))
(alias (identifier) (operator)))
========
undef
========
undef :foo
undef foo
undef +
undef :foo, :bar
---
(program
(undef (simple_symbol))
(undef (identifier))
(undef (operator))
(undef (simple_symbol) (simple_symbol)))

@ -0,0 +1,33 @@
require "a"
# ^ function.method.builtin
class Car < Vehicle
# <- keyword
# ^ constructor
def init(id)
# <- keyword
# ^ function.method
@id = id
# <- property
# ^ variable.parameter
yield
# <- keyword
return
# <- keyword
next
# <- keyword
end
private
# ^ keyword
public
# ^ keyword
protected
# ^ keyword
end
# <- keyword

@ -0,0 +1,24 @@
class MyClass
# ^ constructor
ELEMENT8 = 8
# ^ constant
ELEMENT16 = 16
# ^ constant
def OtherClass
# ^ function.method
@other.OtherClass(Something.new).inspect
# ^ property
# ^ function.method
# ^ constructor
# ^ function.method
# ^ function.method
end
end
if __FILE__ == $0
# ^ constant.builtin
end

@ -0,0 +1,36 @@
"hello"
# ^ string
%(hello)
# ^ string
%w(hello goodbye)
# ^ string
# ^ string
:hello
# ^ string.special.symbol
%s(hello)
# ^ string.special.symbol
%I(hello goodbye)
# ^ string.special.symbol
# ^ string.special.symbol
/hello/
# ^ string.special.regex
%r(hello)
# ^ string.special.regex
12345
# ^ number
12.345
# ^ number
nil
# ^ constant.builtin
true
# ^ constant.builtin
TRUE
# ^ constant.builtin
false
# ^ constant.builtin
FALSE
# ^ constant.builtin

@ -0,0 +1,18 @@
expr = [false | __LINE__ | __FILE__ | __ENCODING__]
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
case expr
in {a: 5, b:, **nil}
# ^ operator
# ^ constant.builtin
in [false | __LINE__ | __FILE__ | __ENCODING__]
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
else
end

@ -0,0 +1,48 @@
one = 1
# <- variable
def two()
three = one
# ^ variable
# ^ function.method
four = three
# ^ variable
# ^ variable
four.each do |i|
puts i, three, five
# ^ variable.parameter
# ^ variable (because blocks are closures)
# ^ function.method
end
four.each do |(a, b), c: d, e = f|
# ^ variable.parameter
# ^ variable.parameter
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ function.method
puts a, b, c, d, e, f
# ^ variable.parameter
# ^ variable.parameter
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ function.method
end
five ||= 1
# ^ variable
six -> (seven) { eight(seven, five) }
# ^ function.method
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ variable
seven
# ^ function.method (because the `seven` above was in the scope of the lambda)
end