mirror of https://github.com/Wilfred/difftastic/
Add 'vendor/tree-sitter-perl/' from commit 'bbf86084d9b7eb4768f3fb9fe094b3e0600057b1'
git-subtree-dir: vendor/tree-sitter-perl git-subtree-mainline:pull/263/head80429e9697git-subtree-split:bbf86084d9
commit
79ee12013c
@ -0,0 +1,8 @@
|
||||
# node stuffs
|
||||
node_modules/
|
||||
.npmrc
|
||||
|
||||
# some build stuff
|
||||
9.3.5/
|
||||
bin/
|
||||
build/
|
||||
@ -0,0 +1,17 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/src"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"bareword",
|
||||
"prec"
|
||||
],
|
||||
"files.associations": {
|
||||
"vector": "cpp"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "tree-sitter-perl"
|
||||
description = "perl grammar for the tree-sitter parsing library"
|
||||
version = "0.0.1"
|
||||
keywords = ["incremental", "parsing", "perl"]
|
||||
categories = ["parsing", "text-editors"]
|
||||
repository = "https://github.com/tree-sitter/tree-sitter-javascript"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
build = "bindings/rust/build.rs"
|
||||
include = [
|
||||
"bindings/rust/*",
|
||||
"grammar.js",
|
||||
"queries/*",
|
||||
"src/*",
|
||||
]
|
||||
|
||||
[lib]
|
||||
path = "bindings/rust/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
tree-sitter = "0.17"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Ganesan
|
||||
|
||||
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,13 @@
|
||||
# tree-sitter-perl
|
||||
a perl parser for javascript
|
||||
|
||||
## To generate the parser output
|
||||
`npm run generate`
|
||||
|
||||
## Tests
|
||||
|
||||
`npm run test`
|
||||
|
||||
## Run examples
|
||||
|
||||
`npm run example`
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_perl_binding",
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"src/parser.c",
|
||||
"src/scanner.cc",
|
||||
"bindings/node/binding.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_perl();
|
||||
|
||||
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_perl());
|
||||
|
||||
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("perl").ToLocalChecked());
|
||||
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||
}
|
||||
|
||||
NODE_MODULE(tree_sitter_perl_binding, Init)
|
||||
|
||||
} // namespace
|
||||
@ -0,0 +1,19 @@
|
||||
try {
|
||||
module.exports = require("../../build/Release/tree_sitter_perl_binding");
|
||||
} catch (error1) {
|
||||
if (error1.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error1;
|
||||
}
|
||||
try {
|
||||
module.exports = require("../../build/Debug/tree_sitter_perl_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,40 @@
|
||||
fn main() {
|
||||
let src_dir = std::path::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);
|
||||
|
||||
// If your language uses an external scanner written in C,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
let scanner_path = src_dir.join("scanner.c");
|
||||
c_config.file(&scanner_path);
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
*/
|
||||
|
||||
c_config.compile("parser");
|
||||
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||
|
||||
// If your language uses an external scanner written in C++,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
let mut cpp_config = cc::Build::new();
|
||||
cpp_config.cpp(true);
|
||||
cpp_config.include(&src_dir);
|
||||
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);
|
||||
cpp_config.compile("scanner");
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
*/
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
//! This crate provides perl language support for the [tree-sitter][] parsing library.
|
||||
//!
|
||||
//! Typically, you will use the [language][language func] function to add this language to a
|
||||
//! tree-sitter [Parser][], and then use the parser to parse some code:
|
||||
//!
|
||||
//! ```
|
||||
//! let code = "";
|
||||
//! let mut parser = tree_sitter::Parser::new();
|
||||
//! parser.set_language(tree_sitter_perl::language()).expect("Error loading perl grammar");
|
||||
//! let tree = parser.parse(code, None).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! [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_perl() -> Language;
|
||||
}
|
||||
|
||||
/// Get 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_perl() }
|
||||
}
|
||||
|
||||
/// 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");
|
||||
|
||||
// Uncomment these to include any queries that this grammar contains
|
||||
|
||||
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
|
||||
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
|
||||
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
|
||||
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_can_load_grammar() {
|
||||
let mut parser = tree_sitter::Parser::new();
|
||||
parser
|
||||
.set_language(super::language())
|
||||
.expect("Error loading perl language");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package BaseModule::YeaThis;
|
||||
|
||||
use parent 'PerlModule';
|
||||
|
||||
$foo::bar = 1;
|
||||
|
||||
BaseModule::YeaThis->new->hello();
|
||||
|
||||
my $simple = SimpleModule->new();
|
||||
|
||||
my $parent_call = $self->SUPER::Something($string);
|
||||
|
||||
|
||||
my $event = {
|
||||
user_id => Data::UUID->new->Something($dbh, {}),
|
||||
};
|
||||
|
||||
|
||||
my $output = {
|
||||
some_property => BaseModule::AtSomeWhere::GetSomething(121, {
|
||||
KEY => $var->{there},
|
||||
}),
|
||||
};
|
||||
|
||||
my $object_return = BaseModule::AtSomeWhere::GetSomething(121, {
|
||||
KEY => $var->{there}->{here},
|
||||
})->SomeOtherSub('hahaha');
|
||||
|
||||
=pod
|
||||
=head1 Heading Text
|
||||
=head2 Heading Text
|
||||
=head3 Heading Text
|
||||
=head4 Heading Text
|
||||
=over indentlevel
|
||||
=item stuff
|
||||
=back
|
||||
=begin format
|
||||
=end format
|
||||
=for format text...
|
||||
=encoding type
|
||||
=end
|
||||
|
||||
print "Well hello beautiful";
|
||||
@ -0,0 +1,95 @@
|
||||
package PerlModule;
|
||||
|
||||
use 5.006;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp ();
|
||||
|
||||
use vars qw{$VERSION};
|
||||
BEGIN {
|
||||
$VERSION = '1.04';
|
||||
|
||||
# Optional stacktrace support
|
||||
eval "require Devel::StackTrace";
|
||||
}
|
||||
|
||||
# my $another = BaseModule::YeaThis->new()->hello();
|
||||
|
||||
# eval {
|
||||
# package hello;
|
||||
# };
|
||||
|
||||
new();
|
||||
getTrace();
|
||||
toString();
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
bless {}, $class;
|
||||
}
|
||||
|
||||
my $output = BaseModule::YeaThis::hello('first', {
|
||||
hello => 'beautiful'
|
||||
});
|
||||
|
||||
|
||||
sub getTrace {
|
||||
$_[0]->{Trace};
|
||||
}
|
||||
|
||||
# sub fillTrace {
|
||||
# my $self = shift;
|
||||
# $self->{Trace} = Devel::StackTrace->new(
|
||||
# ignore_class => [__PACKAGE__, @_],
|
||||
# ) if $Devel::StackTrace::VERSION;
|
||||
# }
|
||||
|
||||
sub getCarp {
|
||||
$_[0]->{Carp};
|
||||
}
|
||||
|
||||
# sub fillCarp {
|
||||
# my $self = shift;
|
||||
# my $msg = shift;
|
||||
# $Carp::Internal{ __PACKAGE__ . "" }++;
|
||||
# local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
# $self->{Carp} = Carp::longmess($msg);
|
||||
# $Carp::Internal{ __PACKAGE__ . "" }--;
|
||||
# }
|
||||
|
||||
sub getMessage {
|
||||
$_[0]->{Message};
|
||||
}
|
||||
|
||||
sub setMessage {
|
||||
$_[0]->{Message} = $_[1];
|
||||
}
|
||||
|
||||
sub fillTest {
|
||||
my $self = shift;
|
||||
my $builder = shift;
|
||||
my $prev_test = $builder->current_test;
|
||||
$self->{Test} = $prev_test;
|
||||
my @tests = $builder->details;
|
||||
my $prev_test_name = $prev_test ? $tests[$prev_test - 1]->{name} : "";
|
||||
$self->{TestName} = $prev_test_name;
|
||||
}
|
||||
|
||||
sub getTest {
|
||||
$_[0]->{Test};
|
||||
}
|
||||
|
||||
sub getTestName {
|
||||
$_[0]->{TestName};
|
||||
}
|
||||
|
||||
# sub toString {
|
||||
# my $self = shift;
|
||||
# return <<EOM;
|
||||
# Previous test $self->{Test} '$self->{TestName}'
|
||||
# $self->{Carp}
|
||||
# EOM
|
||||
# }
|
||||
|
||||
|
||||
1;
|
||||
@ -0,0 +1,78 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# sub hello {
|
||||
# if (1) {
|
||||
# return true;
|
||||
# }
|
||||
# }
|
||||
|
||||
# hello();
|
||||
|
||||
if (1) {
|
||||
print "if condition\n";
|
||||
}
|
||||
# comments comments everywhere
|
||||
# comments comments everywhere
|
||||
elsif(1) {
|
||||
print "meow\n";
|
||||
}
|
||||
# comments comments everywhere
|
||||
# comments comments everywhere
|
||||
elsif(1) {
|
||||
print "another one\n";
|
||||
}
|
||||
# comments comments everywhere
|
||||
# comments comments everywhere
|
||||
else {
|
||||
print "else print this\n";
|
||||
}
|
||||
|
||||
unless(0) {
|
||||
print "unless\n";
|
||||
}
|
||||
elsif(1) {
|
||||
print "meow\n";
|
||||
}
|
||||
elsif(1) {
|
||||
print "another one\n";
|
||||
}
|
||||
else {
|
||||
print "else print this\n";
|
||||
}
|
||||
|
||||
# my $num = rand();
|
||||
|
||||
# given ($num) {
|
||||
# when (1) {
|
||||
# say "is larger than 0.7";
|
||||
# }
|
||||
# when ($_ > 0.4) {
|
||||
# say "$_ is larger than 0.4";
|
||||
# }
|
||||
# default {
|
||||
# say "$_ is something else";
|
||||
# }
|
||||
# }
|
||||
|
||||
# my $i = 0;
|
||||
# MEOW: while ($i < 10) {
|
||||
# print "hello $i";
|
||||
|
||||
# next MEOW;
|
||||
|
||||
# $i++;
|
||||
# }
|
||||
|
||||
# standalone blocks
|
||||
{
|
||||
print "hello";
|
||||
} continue {
|
||||
print "con\n";
|
||||
}
|
||||
|
||||
my @array = ("dsf");
|
||||
|
||||
my $tern_out = (1 == 1) ? ("terry") : ((2 * 28) + 1);
|
||||
|
||||
print $tern_out;
|
||||
@ -0,0 +1,12 @@
|
||||
use feature 'switch';
|
||||
use v5.14;
|
||||
use Try::Tiny;
|
||||
|
||||
|
||||
try {
|
||||
my $a = 1;
|
||||
print "tying..\n";
|
||||
}
|
||||
catch {
|
||||
print "catch block";
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
use feature 'signatures';
|
||||
|
||||
sub simple {
|
||||
# my @args = @_;
|
||||
print "this is simple\n";
|
||||
my $variable = 1;
|
||||
|
||||
print $variable;
|
||||
return;
|
||||
}
|
||||
|
||||
print "hello world!\n";
|
||||
|
||||
my $hello = "hello";
|
||||
|
||||
print $hello;
|
||||
|
||||
simple;
|
||||
simple();
|
||||
simple('hola');
|
||||
|
||||
sub foo : Expose ($left, $right) {
|
||||
return $left + $right;
|
||||
}
|
||||
|
||||
foo();
|
||||
print "\n";
|
||||
my @chars = map chr, qw(1 2 3);
|
||||
print "chars..." . Dumper \@chars;
|
||||
|
||||
map chr, qw(1 2 30);
|
||||
@ -0,0 +1,25 @@
|
||||
# hash needs its own sweet example file
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
|
||||
my $simple = SimpleModule->new();
|
||||
|
||||
|
||||
my $event = {
|
||||
user_id => Data::UUID->new->Something($simple, {}),
|
||||
};
|
||||
|
||||
|
||||
my $output = {
|
||||
some_property => BaseModule::AtSomeWhere::GetSomething(121, {
|
||||
KEY => $var->{there},
|
||||
}),
|
||||
};
|
||||
|
||||
my $ter = {
|
||||
first => 'something here',
|
||||
hello() ? (second => 1) : (third => 'ternary false'),
|
||||
};
|
||||
|
||||
print Dumper $ter->{first};
|
||||
@ -0,0 +1,25 @@
|
||||
use strict 'refs';
|
||||
use warnings;
|
||||
use if $] < 5.008, "utf8";
|
||||
use if WANT_WARNINGS, warnings => qw(all);
|
||||
|
||||
use constant PI => 4 * atan2(1, 1);
|
||||
use constant DEBUG , 0; # comma (,) is also used instead of '=>'
|
||||
|
||||
print "Pi equals ", PI, "...\n";
|
||||
|
||||
use constant {
|
||||
SEC => 0,
|
||||
MIN => 1,
|
||||
HOUR => 2,
|
||||
MDAY => 3,
|
||||
MON => 4,
|
||||
YEAR => 5,
|
||||
WDAY => 6,
|
||||
YDAY => 7,
|
||||
ISDST => 8,
|
||||
};
|
||||
|
||||
use constant WEEKDAYS => qw(
|
||||
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
|
||||
);
|
||||
@ -0,0 +1,23 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
|
||||
foreach my $value (qw( cat dog bird flight superman )) {
|
||||
print $value . "\n";
|
||||
}
|
||||
|
||||
my $setting = {
|
||||
open => 1,
|
||||
close => 2,
|
||||
run => 3,
|
||||
awesome => 'yes',
|
||||
};
|
||||
my %final;
|
||||
foreach my $key (woof()) {
|
||||
$final{IRONMAN}{$key} = $setting->{$key};
|
||||
|
||||
print Dumper \%final;
|
||||
|
||||
}
|
||||
|
||||
sub woof {}
|
||||
@ -0,0 +1,8 @@
|
||||
# ellipsis
|
||||
{ ... }
|
||||
sub foo { ... }
|
||||
...;
|
||||
sub somemeth {
|
||||
my $self = shift;
|
||||
...;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
use Data::Dumper;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $ls_args = '-a';
|
||||
my $ls_command = qx /ls $ls_args/;
|
||||
|
||||
|
||||
# print Dumper $ls_command;
|
||||
|
||||
my @array = qw / s6df 32 DF /;
|
||||
|
||||
# print Dumper \@array;
|
||||
|
||||
my $string = 'a simple string';
|
||||
$string = 'string with # in it';
|
||||
$string = 'string with escape \' sequence';
|
||||
$string =~ m/Simple/is;
|
||||
my $baa = 'bbb';
|
||||
$_ = "AAA bbb AAA";
|
||||
print "Found bbb\n" if m/$baa/;
|
||||
|
||||
# Printing the String
|
||||
print "Before: $`\n";
|
||||
print "Matched: $&\n";
|
||||
print "After: $'\n";
|
||||
|
||||
|
||||
my $rex = qr/my.STRING/is;
|
||||
|
||||
print "rex..\n" . $rex;
|
||||
|
||||
my $subs = 'my here string';
|
||||
$subs =~ s/my.STRING/foo/is;
|
||||
|
||||
print "\n substitute is.. \n" . $subs;
|
||||
|
||||
my $trans = "hello";
|
||||
$trans =~ tr/h-l/H-L/c;
|
||||
|
||||
print "\n tr is.. \n" . $trans;
|
||||
@ -0,0 +1,90 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
|
||||
sub hello {
|
||||
return 'hello';
|
||||
}
|
||||
|
||||
# single declaration and initialization
|
||||
my $a;
|
||||
|
||||
my @array;
|
||||
|
||||
my $number = 3010; # number
|
||||
|
||||
my $negative_number = -18;
|
||||
|
||||
my $floating_number = 5.5;
|
||||
|
||||
my $floating_negative_number = -7.455;
|
||||
|
||||
my $string = 'hello'; # single quoted string
|
||||
my $empty_string = '';
|
||||
|
||||
my $double_quoted_string = "meow";
|
||||
|
||||
my $scientific_notation = 16.12E14;
|
||||
|
||||
my $hexa_decimal = 0xffff;
|
||||
|
||||
my $octal = 0577;
|
||||
|
||||
|
||||
my @array2 = ('m\'eow', 'woof', 'burp',);
|
||||
|
||||
my @number_array = ( 1, 2, 3, 8 );
|
||||
|
||||
my @mixed_array = ($octal, 4, 'dog', 4 * 7);
|
||||
|
||||
print "mixed". Dumper(\@mixed_array);
|
||||
|
||||
my @empty_array = ();
|
||||
|
||||
|
||||
# multi declarations and initialization
|
||||
|
||||
# my ($b, $c) = ();
|
||||
|
||||
my $array_ref = ['string', 123, "double string"];
|
||||
|
||||
my $hash = {
|
||||
'cat' => 'meow',
|
||||
"cow" => 'moo',
|
||||
dog => 'woof',
|
||||
};
|
||||
|
||||
my %hash = (
|
||||
believer => 'i am',
|
||||
at => 'important things',
|
||||
first_things => 1,
|
||||
seconds_things => 2,
|
||||
);
|
||||
|
||||
my $hash2 = {
|
||||
name => 'dog',
|
||||
sound => 'woof',
|
||||
};
|
||||
|
||||
$hash->{ wag } = 'tail';
|
||||
$hash->{inner}->{prop1} = 'secret';
|
||||
$hash->{inner}->{prop2}->[0.3] = 'secret2';
|
||||
|
||||
# type glob
|
||||
local *something = \$hash;
|
||||
*somethingelse = *something;
|
||||
print Dumper *somethingelse;
|
||||
|
||||
|
||||
print Dumper $hash;
|
||||
|
||||
|
||||
my @array5 = (1, 3, 6);
|
||||
|
||||
$array5[5] = 23;
|
||||
|
||||
my $prev_test = 10;
|
||||
$array5[$prev_test - 1]->{name} = 1;
|
||||
|
||||
|
||||
print Dumper(\@array5);
|
||||
@ -0,0 +1,31 @@
|
||||
use strict 'refs';
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
use Try::Tiny;
|
||||
|
||||
my $var = 'some string';
|
||||
|
||||
# my $hashref = {
|
||||
# someThing => 'hey hey',
|
||||
# };
|
||||
|
||||
# my %hash = (
|
||||
# makes => 'sense',
|
||||
# );
|
||||
|
||||
|
||||
print 'one\'s true \\love';
|
||||
|
||||
print "\na simple string $var and $hash->{someThing}, haha\n";
|
||||
|
||||
print qq /jkj/;
|
||||
|
||||
print qq {\n {df {fsdf {dsf }}} ( im on vacation};
|
||||
|
||||
print qq {sdf $hashref->{someThing} im on vacation};
|
||||
|
||||
print qq{$var is better than no string\n};
|
||||
|
||||
print qq{\nDoes this make $hash{makes}, really?};
|
||||
|
||||
print qq {hello{ dsf {ds {\}}}}};
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@ganezdragon/tree-sitter-perl",
|
||||
"version": "0.2.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
|
||||
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
|
||||
},
|
||||
"tree-sitter-cli": {
|
||||
"version": "0.19.4",
|
||||
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.19.4.tgz",
|
||||
"integrity": "sha512-p2kxjuoQeauXBu5eE+j7c5BMCRXmc17EiAswnnWn3ieUlHXBkA0Z7vRnaCSElDR34MhZnSgqgzuuzQk0cDqCjw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "@ganezdragon/tree-sitter-perl",
|
||||
"version": "0.3.0",
|
||||
"description": "a tree-sitter for perl language.",
|
||||
"main": "bindings/node",
|
||||
"scripts": {
|
||||
"generate": "tree-sitter generate",
|
||||
"test": "tree-sitter test",
|
||||
"example": "tree-sitter parse examples/*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com/"
|
||||
},
|
||||
"keywords": [
|
||||
"perl",
|
||||
"parser",
|
||||
"nodejs"
|
||||
],
|
||||
"repository": "git://github.com/ganezdragon/tree-sitter-perl.git",
|
||||
"author": "ganezdragon",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nan": "^2.14.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tree-sitter-cli": "^0.19.4"
|
||||
},
|
||||
"tree-sitter": [
|
||||
{
|
||||
"scope": "source.perl",
|
||||
"file-types": [
|
||||
"pl"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
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,590 @@
|
||||
#include <tree_sitter/parser.h>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
using std::vector;
|
||||
using std::memcpy;
|
||||
|
||||
enum TokenType {
|
||||
START_DELIMITER,
|
||||
END_DELIMITER,
|
||||
STRING_CONTENT,
|
||||
STRING_SINGLE_QUOTED_CONTENT,
|
||||
STRING_QQ_QUOTED_CONTENT,
|
||||
STRING_DOUBLE_QUOTED_CONTENT,
|
||||
START_DELIMITER_QW,
|
||||
ELEMENT_IN_QW,
|
||||
END_DELIMITER_QW,
|
||||
START_DELIMITER_REGEX,
|
||||
REGEX_PATTERN,
|
||||
END_DELIMITER_REGEX,
|
||||
START_DELIMITER_SEARCH_REPLACE,
|
||||
SEARCH_REPLACE_CONTENT,
|
||||
SEPARATOR_DELIMITER_SEARCH_REPLACE,
|
||||
END_DELIMITER_SEARCH_REPLACE,
|
||||
START_DELIMITER_TRANSLITERATION,
|
||||
TRANSLITERATION_CONTENT,
|
||||
SEPARATOR_DELIMITER_TRANSLITERATION,
|
||||
END_DELIMITER_TRANSLITERATION,
|
||||
POD_CONTENT,
|
||||
};
|
||||
|
||||
struct Delimiter {
|
||||
|
||||
int32_t get_end_delimiter() {
|
||||
return end_delimiter;
|
||||
}
|
||||
|
||||
int32_t end_delimiter;
|
||||
};
|
||||
|
||||
struct Scanner {
|
||||
Scanner() {
|
||||
// assert(sizeof(Delimiter) == sizeof(char));
|
||||
deserialize(NULL, 0);
|
||||
}
|
||||
|
||||
unsigned serialize(char *buffer) {
|
||||
size_t no_of_bytes = 0;
|
||||
|
||||
// size_t delimiter_count = delimiter_stack.size();
|
||||
// if (delimiter_count > UINT8_MAX) delimiter_count = UINT8_MAX;
|
||||
// buffer[no_of_bytes++] = delimiter_count;
|
||||
|
||||
// if (delimiter_count > 0) {
|
||||
// memcpy(&buffer[no_of_bytes], delimiter_stack.data(), delimiter_count);
|
||||
// }
|
||||
// no_of_bytes += delimiter_count;
|
||||
|
||||
return no_of_bytes;
|
||||
}
|
||||
|
||||
void deserialize(const char *buffer, unsigned length) {
|
||||
// delimiter_stack.clear();
|
||||
|
||||
// if (length > 0) {
|
||||
// size_t no_of_bytes = 0;
|
||||
|
||||
// size_t delimiter_count = (uint8_t)buffer[no_of_bytes++];
|
||||
// delimiter_stack.resize(delimiter_count);
|
||||
// if (delimiter_count > 0) {
|
||||
// memcpy(delimiter_stack.data(), &buffer[no_of_bytes], delimiter_count);
|
||||
// }
|
||||
// no_of_bytes += delimiter_count;
|
||||
// }
|
||||
}
|
||||
|
||||
bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
||||
// on ERROR, external scanner is called with all valid_symbols to be true.
|
||||
// so for our usecase we need this logic.
|
||||
// ref - https://github.com/tree-sitter/tree-sitter/issues/1128
|
||||
if (
|
||||
valid_symbols[START_DELIMITER]
|
||||
&& valid_symbols[END_DELIMITER]
|
||||
&& valid_symbols[STRING_CONTENT]
|
||||
&& valid_symbols[STRING_SINGLE_QUOTED_CONTENT]
|
||||
&& valid_symbols[STRING_QQ_QUOTED_CONTENT]
|
||||
&& valid_symbols[STRING_DOUBLE_QUOTED_CONTENT]
|
||||
&& valid_symbols[START_DELIMITER_QW]
|
||||
&& valid_symbols[END_DELIMITER_QW]
|
||||
&& valid_symbols[START_DELIMITER_REGEX]
|
||||
&& valid_symbols[REGEX_PATTERN]
|
||||
&& valid_symbols[END_DELIMITER_REGEX]
|
||||
&& valid_symbols[START_DELIMITER_SEARCH_REPLACE]
|
||||
&& valid_symbols[SEARCH_REPLACE_CONTENT]
|
||||
&& valid_symbols[SEPARATOR_DELIMITER_SEARCH_REPLACE]
|
||||
&& valid_symbols[END_DELIMITER_SEARCH_REPLACE]
|
||||
&& valid_symbols[START_DELIMITER_TRANSLITERATION]
|
||||
&& valid_symbols[TRANSLITERATION_CONTENT]
|
||||
&& valid_symbols[SEPARATOR_DELIMITER_TRANSLITERATION]
|
||||
&& valid_symbols[END_DELIMITER_TRANSLITERATION]
|
||||
&& valid_symbols[POD_CONTENT]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (valid_symbols[STRING_SINGLE_QUOTED_CONTENT]) {
|
||||
|
||||
// end when you reach the final single quote '
|
||||
if (lexer->lookahead == '\'') {
|
||||
lexer->mark_end(lexer);
|
||||
advance(lexer);
|
||||
return false;
|
||||
}
|
||||
// check for escaped single quote \'
|
||||
else if (lexer->lookahead == '\\') {
|
||||
lexer->result_symbol = STRING_SINGLE_QUOTED_CONTENT;
|
||||
advance(lexer);
|
||||
|
||||
if (lexer->lookahead == '\'') {
|
||||
advance(lexer);
|
||||
}
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// some exit conditions
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
lexer->result_symbol = STRING_SINGLE_QUOTED_CONTENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: handle qqqSTRINGq; - this should throw error
|
||||
if (valid_symbols[START_DELIMITER]) {
|
||||
return parse_start_delimiter(lexer, START_DELIMITER);
|
||||
}
|
||||
|
||||
if (valid_symbols[STRING_QQ_QUOTED_CONTENT]) {
|
||||
return parse_delimited_and_interpolated_content(lexer, STRING_QQ_QUOTED_CONTENT, END_DELIMITER);
|
||||
}
|
||||
|
||||
if (valid_symbols[STRING_DOUBLE_QUOTED_CONTENT]) {
|
||||
if (lexer->lookahead == '"') {
|
||||
lexer->mark_end(lexer);
|
||||
advance(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// oh boy! the interpolation
|
||||
if (lexer->lookahead == '$') {
|
||||
return handle_interpolation(lexer, STRING_DOUBLE_QUOTED_CONTENT);
|
||||
}
|
||||
// escape sequences, only basic support as of now
|
||||
if (lexer->lookahead == '\\') {
|
||||
return handle_escape_sequence(lexer, STRING_DOUBLE_QUOTED_CONTENT);
|
||||
}
|
||||
|
||||
// some exit conditions
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
lexer->result_symbol = STRING_DOUBLE_QUOTED_CONTENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid_symbols[START_DELIMITER_QW]) {
|
||||
return parse_start_delimiter(lexer, START_DELIMITER_QW);
|
||||
}
|
||||
|
||||
if (valid_symbols[ELEMENT_IN_QW]) {
|
||||
run_over_spaces(lexer);
|
||||
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
lexer->result_symbol = END_DELIMITER_QW;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// exit condition
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (
|
||||
lexer->lookahead != ' '
|
||||
&& lexer->lookahead != '\t'
|
||||
&& lexer->lookahead != '\r'
|
||||
&& lexer->lookahead != '\n'
|
||||
&& lexer->lookahead != get_end_delimiter()
|
||||
) {
|
||||
lexer->result_symbol = ELEMENT_IN_QW;
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid_symbols[START_DELIMITER_REGEX]) {
|
||||
return parse_start_delimiter(lexer, START_DELIMITER_REGEX);
|
||||
}
|
||||
if (valid_symbols[REGEX_PATTERN]) {
|
||||
return parse_delimited_and_interpolated_content(lexer, REGEX_PATTERN, END_DELIMITER_REGEX);
|
||||
}
|
||||
|
||||
if (valid_symbols[START_DELIMITER_SEARCH_REPLACE]) {
|
||||
return parse_start_delimiter(lexer, START_DELIMITER_SEARCH_REPLACE);
|
||||
}
|
||||
|
||||
if (valid_symbols[SEARCH_REPLACE_CONTENT]) {
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
return process_separator_delimiter(lexer, SEPARATOR_DELIMITER_SEARCH_REPLACE, END_DELIMITER_SEARCH_REPLACE);
|
||||
}
|
||||
else {
|
||||
// oh boy! the interpolation
|
||||
if (lexer->lookahead == '$') {
|
||||
return handle_interpolation(lexer, SEARCH_REPLACE_CONTENT);
|
||||
}
|
||||
// escape sequences, only basic support as of now
|
||||
if (lexer->lookahead == '\\') {
|
||||
return handle_escape_sequence(lexer, SEARCH_REPLACE_CONTENT);
|
||||
}
|
||||
|
||||
// some exit conditions
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// handling nested delimiters qq { hello { from { the}}};
|
||||
if (lexer->lookahead == start_delimiter_char) {
|
||||
lexer->result_symbol = SEARCH_REPLACE_CONTENT;
|
||||
advance(lexer);
|
||||
return scan_nested_delimiters(lexer, SEARCH_REPLACE_CONTENT);
|
||||
}
|
||||
|
||||
lexer->result_symbol = SEARCH_REPLACE_CONTENT;
|
||||
advance(lexer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_symbols[START_DELIMITER_TRANSLITERATION]) {
|
||||
return parse_start_delimiter(lexer, START_DELIMITER_TRANSLITERATION);
|
||||
}
|
||||
if (valid_symbols[TRANSLITERATION_CONTENT]) {
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
return process_separator_delimiter(lexer, SEPARATOR_DELIMITER_TRANSLITERATION, END_DELIMITER_TRANSLITERATION);
|
||||
}
|
||||
|
||||
// exit condition
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// escape sequence
|
||||
if (lexer->lookahead == '\\') {
|
||||
lexer->result_symbol = TRANSLITERATION_CONTENT;
|
||||
advance(lexer);
|
||||
// self end delimiter
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// handling nested delimiters qq { hello { from { the}}};
|
||||
if (lexer->lookahead == start_delimiter_char) {
|
||||
lexer->result_symbol = TRANSLITERATION_CONTENT;
|
||||
advance(lexer);
|
||||
return scan_nested_delimiters(lexer, TRANSLITERATION_CONTENT);
|
||||
}
|
||||
|
||||
lexer->result_symbol = TRANSLITERATION_CONTENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid_symbols[POD_CONTENT]) {
|
||||
|
||||
while (lexer->lookahead) {
|
||||
lexer->result_symbol = POD_CONTENT;
|
||||
|
||||
// if it is =cut that marks the end of pod content
|
||||
if (lexer->lookahead == '=') {
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == 'c') {
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == 'u') {
|
||||
lexer->advance(lexer, false);
|
||||
if (lexer->lookahead == 't') {
|
||||
lexer->advance(lexer, false);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
}
|
||||
|
||||
// or if it end of the file also, mark the end of pod content
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse_delimited_and_interpolated_content(TSLexer *lexer, TokenType token_type, TokenType ending_delimiter) {
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
lexer->result_symbol = ending_delimiter;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// oh boy! the interpolation
|
||||
if (lexer->lookahead == '$') {
|
||||
return handle_interpolation(lexer, token_type);
|
||||
}
|
||||
// escape sequences, only basic support as of now
|
||||
if (lexer->lookahead == '\\') {
|
||||
return handle_escape_sequence(lexer, token_type);
|
||||
}
|
||||
|
||||
if (!lexer->lookahead) {
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// handling nested delimiters qq { hello { from { the}}};
|
||||
if (lexer->lookahead == start_delimiter_char) {
|
||||
lexer->result_symbol = token_type;
|
||||
advance(lexer);
|
||||
return scan_nested_delimiters(lexer, token_type);
|
||||
}
|
||||
|
||||
lexer->result_symbol = token_type;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// shouldn't reach here
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scan_nested_delimiters(TSLexer *lexer, TokenType token_type) {
|
||||
while(lexer->lookahead) {
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
lexer->result_symbol = token_type;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
else if (lexer->lookahead == start_delimiter_char) {
|
||||
lexer->result_symbol = token_type;
|
||||
advance(lexer);
|
||||
scan_nested_delimiters(lexer, token_type);
|
||||
}
|
||||
else if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
advance(lexer);
|
||||
}
|
||||
else {
|
||||
advance(lexer);
|
||||
}
|
||||
}
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
|
||||
void advance(TSLexer *lexer) {
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
|
||||
void skip(TSLexer *lexer) {
|
||||
lexer->advance(lexer, true);
|
||||
}
|
||||
|
||||
void set_end_delimiter(int32_t start_delimiter) {
|
||||
// round, angle, square, curly
|
||||
is_delimiter_enclosing = true;
|
||||
if (start_delimiter == '(') {
|
||||
end_delimiter_char = ')';
|
||||
}
|
||||
else if (start_delimiter == '<') {
|
||||
end_delimiter_char = '>';
|
||||
}
|
||||
else if (start_delimiter == '[') {
|
||||
end_delimiter_char = ']';
|
||||
}
|
||||
else if (start_delimiter == '{') {
|
||||
end_delimiter_char = '}';
|
||||
}
|
||||
else {
|
||||
is_delimiter_enclosing = false;
|
||||
end_delimiter_char = start_delimiter;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_separator_delimiter(TSLexer *lexer, TokenType separator_token, TokenType end_token) {
|
||||
if (is_separator_delimiter_parsed) {
|
||||
lexer->result_symbol = end_token;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
lexer->result_symbol = separator_token;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
// if delimiter is {}, (), <>, []
|
||||
if (is_delimiter_enclosing) {
|
||||
run_over_spaces(lexer);
|
||||
|
||||
if (lexer->lookahead == start_delimiter_char) {
|
||||
lexer->result_symbol = separator_token;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
is_separator_delimiter_parsed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
is_separator_delimiter_parsed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t get_end_delimiter() {
|
||||
return end_delimiter_char;
|
||||
}
|
||||
|
||||
// Give a token type, parses the start delimiter,
|
||||
// and keeps track of it in memory.
|
||||
bool parse_start_delimiter(TSLexer *lexer, TokenType token_type) {
|
||||
run_over_spaces(lexer);
|
||||
|
||||
start_delimiter_char = lexer->lookahead;
|
||||
set_end_delimiter(start_delimiter_char);
|
||||
|
||||
// for substitute and tr/y usecase
|
||||
is_separator_delimiter_parsed = false;
|
||||
|
||||
lexer->result_symbol = token_type;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// runs over spaces like a champ
|
||||
void run_over_spaces(TSLexer *lexer) {
|
||||
while (lexer->lookahead == ' ' || lexer->lookahead == '\t' || lexer->lookahead == '\r' || lexer->lookahead == '\n') {
|
||||
skip(lexer);
|
||||
}
|
||||
}
|
||||
|
||||
// runs with the spaces using advance
|
||||
void run_with_spaces(TSLexer *lexer) {
|
||||
while(lexer->lookahead == ' ' || lexer->lookahead == '\t' || lexer->lookahead == '\r' || lexer->lookahead == '\n') {
|
||||
advance(lexer);
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_interpolation(TSLexer *lexer, TokenType surrounding_token) {
|
||||
if (lexer->lookahead == '$') {
|
||||
|
||||
// allow $ to be last character in a regex
|
||||
if (surrounding_token == SEARCH_REPLACE_CONTENT || surrounding_token == REGEX_PATTERN) {
|
||||
advance(lexer);
|
||||
run_with_spaces(lexer);
|
||||
if (lexer->lookahead == get_end_delimiter()) {
|
||||
lexer->result_symbol = surrounding_token;
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool handle_escape_sequence(TSLexer *lexer, TokenType surrounding_token) {
|
||||
// escape sequences, only basic support as of now
|
||||
if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
// also, self end delimiter will be treated as string
|
||||
if (
|
||||
lexer->lookahead == 't' || lexer->lookahead == 'n' || lexer->lookahead == 'r' || lexer->lookahead == 'f' || lexer->lookahead == 'b' || lexer->lookahead == 'a' || lexer->lookahead == 'e'
|
||||
) {
|
||||
// advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
lexer->result_symbol = surrounding_token;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_nested_delimiters() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t start_delimiter_char;
|
||||
int32_t end_delimiter_char;
|
||||
bool is_separator_delimiter_parsed;
|
||||
bool is_delimiter_enclosing; // is the delimiter {}, <> and same character not //, !!
|
||||
int delimiter_cout = 0;
|
||||
bool reached;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void * tree_sitter_perl_external_scanner_create() {
|
||||
return new Scanner();
|
||||
}
|
||||
|
||||
void tree_sitter_perl_external_scanner_destroy(void *payload) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
delete scanner;
|
||||
}
|
||||
|
||||
unsigned tree_sitter_perl_external_scanner_serialize(
|
||||
void *payload,
|
||||
char *buffer
|
||||
) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
return scanner->serialize(buffer);
|
||||
}
|
||||
|
||||
void tree_sitter_perl_external_scanner_deserialize(
|
||||
void *payload,
|
||||
const char *buffer,
|
||||
unsigned length
|
||||
) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
scanner->deserialize(buffer, length);
|
||||
}
|
||||
|
||||
bool tree_sitter_perl_external_scanner_scan(
|
||||
void *payload,
|
||||
TSLexer *lexer,
|
||||
const bool *valid_symbols
|
||||
) {
|
||||
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
return scanner->scan(lexer, valid_symbols);
|
||||
}
|
||||
}
|
||||
@ -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 **symbol_names;
|
||||
const char **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,23 @@
|
||||
=================================================
|
||||
single line comment
|
||||
=================================================
|
||||
|
||||
# I'm a comment and I can be anywhere
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(comments)
|
||||
)
|
||||
|
||||
=================================================
|
||||
a pound (#) inside a string is a string and not a comment
|
||||
=================================================
|
||||
|
||||
my $string = "This is a string with # in it";
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_double_quoted) (semi_colon))
|
||||
)
|
||||
@ -0,0 +1,149 @@
|
||||
=================================================
|
||||
if block with boolean
|
||||
=================================================
|
||||
|
||||
if (1) {
|
||||
print "hello";
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(if_statement (parenthesized_expression (integer))
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted))) (semi_colon)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
if else block with boolean
|
||||
=================================================
|
||||
|
||||
if (1) {
|
||||
print "hello";
|
||||
}
|
||||
else {
|
||||
print "else";
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(if_statement (parenthesized_expression (integer))
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted))) (semi_colon)
|
||||
)
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted))) (semi_colon)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
Simple while statement
|
||||
=================================================
|
||||
|
||||
my $i = 0;
|
||||
while ($i < 10) {
|
||||
print "hello $i";
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (integer) (semi_colon))
|
||||
(while_statement (empty_parenthesized_expression (binary_expression (scalar_variable) (integer)))
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted (interpolation (scalar_variable))))) (semi_colon)
|
||||
(unary_expression (scalar_variable)) (semi_colon)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
while statement with label
|
||||
=================================================
|
||||
|
||||
my $i = 0;
|
||||
MEOW: while ($i < 10) {
|
||||
print "hello $i";
|
||||
|
||||
next MEOW;
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (integer) (semi_colon))
|
||||
(while_statement (identifier) (empty_parenthesized_expression (binary_expression (scalar_variable) (integer)))
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted (interpolation (scalar_variable))))) (semi_colon) (loop_control_statement (loop_control_keyword) (identifier) (semi_colon)) (unary_expression (scalar_variable)) (semi_colon))
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
single line for loop
|
||||
=================================================
|
||||
|
||||
my @array = (1, 3, 4);
|
||||
print "in a loop" for @array;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (array_variable)) (array (integer) (integer) (integer)) (semi_colon))
|
||||
(single_line_statement (call_expression (identifier) (argument (string_double_quoted))) (for_simple_statement (array_variable) (semi_colon)))
|
||||
)
|
||||
|
||||
=================================================
|
||||
simple for loop TODO: this is failing
|
||||
=================================================
|
||||
|
||||
for (my $i=1; $i < 10; $i++) {
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(for_statement_1 (binary_expression (call_expression (identifier) (argument (scalar_variable))) (integer)) (semi_colon) (binary_expression (scalar_variable) (integer)) (semi_colon) (unary_expression (scalar_variable))
|
||||
(block)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
for ever loop
|
||||
=================================================
|
||||
|
||||
for (;;) {
|
||||
print "hello";
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(for_statement_1 (semi_colon) (semi_colon)
|
||||
(block
|
||||
(call_expression (identifier) (argument (string_double_quoted))) (semi_colon)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
foreach loop
|
||||
=================================================
|
||||
|
||||
foreach my $single (@array) {
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(foreach_statement (scope) (scalar_variable) (array_variable)
|
||||
(block)
|
||||
)
|
||||
)
|
||||
@ -0,0 +1,19 @@
|
||||
=================================================
|
||||
switch feature
|
||||
=================================================
|
||||
|
||||
use feature "switch";
|
||||
|
||||
---
|
||||
|
||||
(source_file (use_no_feature_statement (string_double_quoted) (semi_colon)))
|
||||
|
||||
=================================================
|
||||
multi features
|
||||
=================================================
|
||||
|
||||
use feature qw(switch say);
|
||||
|
||||
---
|
||||
|
||||
(source_file (use_no_feature_statement (word_list_qw (list_item) (list_item)) (semi_colon)))
|
||||
@ -0,0 +1,204 @@
|
||||
=================================================
|
||||
scalar declaration
|
||||
=================================================
|
||||
|
||||
my $a;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration
|
||||
(scalar_variable)
|
||||
) (semi_colon))
|
||||
)
|
||||
|
||||
|
||||
=================================================
|
||||
scalar declaration with initialization
|
||||
=================================================
|
||||
|
||||
my $a = 3;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration
|
||||
(scalar_variable)) (integer) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
multi declaration with initialization
|
||||
=================================================
|
||||
|
||||
my ($self, $args) = @_;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope)
|
||||
(multi_var_declaration
|
||||
(variable_declarator (scalar_variable)) (variable_declarator (scalar_variable))
|
||||
) (special_array_variable) (semi_colon)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
array declaration
|
||||
=================================================
|
||||
|
||||
my @array;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration
|
||||
(array_variable)
|
||||
) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
array declaration with initialization
|
||||
=================================================
|
||||
|
||||
my @array = ('meow', 'woof', 'burp');
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration
|
||||
(array_variable)) (array (string_single_quoted) (string_single_quoted) (string_single_quoted)) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
hash ref with initialization
|
||||
=================================================
|
||||
|
||||
my $hash = {
|
||||
'cat' => 'meow',
|
||||
"cow" => 'moo',
|
||||
dog => 'woof',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable))
|
||||
(hash_ref
|
||||
(string_single_quoted) (hash_arrow_operator) (string_single_quoted)
|
||||
(string_double_quoted) (hash_arrow_operator) (string_single_quoted)
|
||||
(bareword) (hash_arrow_operator) (string_single_quoted))
|
||||
(semi_colon)))
|
||||
|
||||
=================================================
|
||||
use statement
|
||||
=================================================
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(use_no_statement (package_name (identifier) (identifier)) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
no statement
|
||||
=================================================
|
||||
|
||||
no strict 'refs';
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(use_no_statement (package_name (identifier)) (string_single_quoted) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
require statement
|
||||
=================================================
|
||||
|
||||
require Data::Dumper;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(require_statement (package_name (identifier) (identifier)) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
single line comment
|
||||
=================================================
|
||||
|
||||
# this is a single line comment
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(comments)
|
||||
)
|
||||
|
||||
=================================================
|
||||
length of an array
|
||||
=================================================
|
||||
|
||||
$#array;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(scalar_variable) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
single quoted string with # in it
|
||||
=================================================
|
||||
|
||||
my $string = 'I have # in me';
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_single_quoted) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
single quoted string with the only one supported escaping
|
||||
=================================================
|
||||
|
||||
my $string = 'I have \' escaping in me';
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_single_quoted) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
Double quoted string with escape sequence
|
||||
=================================================
|
||||
|
||||
"this is a string \n in next line at the end";
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(string_double_quoted (escape_sequence)) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
<STDIN>
|
||||
=================================================
|
||||
|
||||
while (<>) {}
|
||||
my $fh = \*STDIN;
|
||||
my $line = <$fh>;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(while_statement (empty_parenthesized_expression (standard_input))
|
||||
(block)
|
||||
)
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (standard_input) (semi_colon))
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (standard_input_to_variable (scalar_variable)) (semi_colon))
|
||||
)
|
||||
@ -0,0 +1,29 @@
|
||||
=================================================
|
||||
method invocation 1
|
||||
=================================================
|
||||
|
||||
my $output = BaseModule::YeaThis->hello('first', {
|
||||
hello => 'beautiful'
|
||||
});
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable))
|
||||
(method_invocation (package_name (identifier) (identifier)) (arrow_operator) (identifier)
|
||||
(parenthesized_argument (argument (string_single_quoted) (hash_ref (bareword) (hash_arrow_operator) (string_single_quoted)))))
|
||||
(semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
method invocation 2
|
||||
=================================================
|
||||
|
||||
my $output = BaseModule->new();
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable))
|
||||
(method_invocation (identifier) (arrow_operator) (identifier) (empty_parenthesized_argument)) (semi_colon))
|
||||
)
|
||||
@ -0,0 +1,170 @@
|
||||
=================================================
|
||||
Interpolate only $ and @ variable and not %hash or object reference TODO: fix this
|
||||
=================================================
|
||||
|
||||
qq {hello $meow print("dsfsdf) %hash};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(string_qq_quoted
|
||||
(start_delimiter)
|
||||
(interpolation (scalar_variable))
|
||||
(end_delimiter))
|
||||
(semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
qq //
|
||||
=================================================
|
||||
|
||||
qq /im inside another delimiter/;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(string_qq_quoted (start_delimiter) (end_delimiter)) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
qq '' interpolate
|
||||
=================================================
|
||||
|
||||
qq 'this should $interpolate, yes';
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(string_qq_quoted (start_delimiter) (interpolation (scalar_variable)) (end_delimiter)) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
q{} string
|
||||
=================================================
|
||||
|
||||
my $string = q{im a non interpolated string};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_q_quoted) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
qx command
|
||||
=================================================
|
||||
|
||||
my $string = q{im a non interpolated string};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_q_quoted) (semi_colon))
|
||||
)
|
||||
|
||||
=================================================
|
||||
qw command
|
||||
=================================================
|
||||
|
||||
my @array = qw /
|
||||
PUBG
|
||||
EVENING
|
||||
BIO_SHOCK_INFINITY
|
||||
/;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration
|
||||
(scope) (single_var_declaration (array_variable)) (word_list_qw (list_item) (list_item) (list_item)) (semi_colon)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
m matcher operator
|
||||
=================================================
|
||||
|
||||
$string =~ m/Simple/is;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(binary_expression
|
||||
(scalar_variable) (patter_matcher_m (start_delimiter) (end_delimiter) (regex_option))
|
||||
) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
m matcher operator - $ at the end shouldn't interpolate
|
||||
=================================================
|
||||
|
||||
my $x = 'shru';
|
||||
if ($x =~ m/u$/) {
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable)) (string_single_quoted) (semi_colon))
|
||||
(if_statement
|
||||
(parenthesized_expression (binary_expression (scalar_variable) (patter_matcher_m (start_delimiter) (end_delimiter))))
|
||||
(block)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
qr regex operator
|
||||
=================================================
|
||||
|
||||
my $rex = qr/my.STRING/is;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration
|
||||
(scope) (single_var_declaration (scalar_variable)) (regex_pattern_qr (start_delimiter) (end_delimiter) (regex_option)) (semi_colon)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
s regex substitution
|
||||
=================================================
|
||||
|
||||
$subs =~ s/my.STRING/foo/is;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(binary_expression
|
||||
(scalar_variable)
|
||||
(substitution_pattern_s (start_delimiter) (separator_delimiter) (end_delimiter) (regex_option_for_substitution))) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
s regex substitution - no replace content
|
||||
=================================================
|
||||
|
||||
$subs =~ s/search//is;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(binary_expression
|
||||
(scalar_variable)
|
||||
(substitution_pattern_s (start_delimiter) (separator_delimiter) (end_delimiter) (regex_option_for_substitution))) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
tr// or y// transliteration
|
||||
=================================================
|
||||
|
||||
my $subs =~ tr{bar}{foo}cs;
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration
|
||||
(scope) (single_var_declaration (scalar_variable))
|
||||
(unary_expression (transliteration_tr_or_y (start_delimiter) (separator_delimiter) (end_delimiter) (regex_option_for_transliteration))) (semi_colon)
|
||||
)
|
||||
)
|
||||
@ -0,0 +1,27 @@
|
||||
=================================================
|
||||
ellipsis statement
|
||||
=================================================
|
||||
|
||||
sub foo { ... }
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(function_definition (identifier)
|
||||
(block
|
||||
(ellipsis_statement)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
constant
|
||||
=================================================
|
||||
|
||||
use constant SOUL_MATE => 'SCORPIO';
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(use_constant_statement (identifier) (string_single_quoted) (semi_colon))
|
||||
)
|
||||
@ -0,0 +1,70 @@
|
||||
=================================================
|
||||
Subroutine with empty block
|
||||
=================================================
|
||||
|
||||
sub hello {
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(function_definition (identifier)
|
||||
(block)
|
||||
)
|
||||
)
|
||||
|
||||
=================================================
|
||||
Subroutine call / function call
|
||||
=================================================
|
||||
|
||||
hello();
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(call_expression
|
||||
function_name: (identifier) args: (empty_parenthesized_argument)) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
Subroutine with arrow notation
|
||||
=================================================
|
||||
|
||||
my $result = GetSalesforceTemplateInfo($dbh)->{$args->{ALOHA}}->{'NAMASTE'};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(variable_declaration (scope) (single_var_declaration (scalar_variable))
|
||||
(hash_access_variable
|
||||
(hash_access_variable (call_expression (identifier) (argument (scalar_variable)))
|
||||
(hash_access_variable (scalar_variable) (bareword))) (string_single_quoted)) (semi_colon)))
|
||||
|
||||
=================================================
|
||||
Subroutine calling another subroutine without params
|
||||
=================================================
|
||||
|
||||
print Dumper %{$args};
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(call_expression (identifier) (argument
|
||||
(call_expression (identifier) (argument (hash_dereference (scalar_variable)))))) (semi_colon)
|
||||
)
|
||||
|
||||
=================================================
|
||||
Subroutine with CODE signature
|
||||
=================================================
|
||||
|
||||
sub Run (&) {
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(function_definition (identifier) (function_prototype (prototype))
|
||||
(block)
|
||||
)
|
||||
)
|
||||
Loading…
Reference in New Issue