mirror of https://github.com/Wilfred/difftastic/
Use tree-sitter-php from crates.io
parent
f9d663ea9f
commit
eb0b47d403
@ -1 +0,0 @@
|
||||
../tree-sitter-php/queries/highlights.scm
|
||||
@ -1 +0,0 @@
|
||||
tree-sitter-php/src
|
||||
@ -1,3 +0,0 @@
|
||||
/src/** linguist-vendored
|
||||
/examples/* linguist-vendored
|
||||
/corpus/* linguist-vendored
|
||||
@ -1,8 +0,0 @@
|
||||
|
||||
|
||||
Checklist:
|
||||
- [ ] All tests pass in CI
|
||||
- [ ] There are sufficient tests for the new fix/feature
|
||||
- [ ] Grammar rules have not been renamed unless absolutely necessary (x rules renamed)
|
||||
- [ ] The conflicts section hasn't grown too much (x new conflicts)
|
||||
- [ ] The parser size hasn't grown too much (master: STATE_COUNT, PR: STATE_COUNT) (check the value of STATE_COUNT in src/parser.c)
|
||||
@ -1,22 +0,0 @@
|
||||
name: Build/test
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
@ -1,14 +0,0 @@
|
||||
package-lock.json
|
||||
node_modules
|
||||
build
|
||||
*.log
|
||||
.DS_Store
|
||||
examples
|
||||
|
||||
*.a
|
||||
*.dylib
|
||||
*.so
|
||||
*.o
|
||||
bindings/c/*.h
|
||||
bindings/c/tree-sitter-*.pc
|
||||
.build/
|
||||
@ -1,5 +0,0 @@
|
||||
test
|
||||
build
|
||||
script
|
||||
examples
|
||||
target
|
||||
@ -1,59 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter"
|
||||
version = "0.20.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b3b781640108d29892e8b9684642d2cda5ea05951fd58f0fea1db9edeb9b71"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-php"
|
||||
version = "0.19.1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
]
|
||||
@ -1,25 +0,0 @@
|
||||
[package]
|
||||
name = "tree-sitter-php"
|
||||
description = "php grammar for the tree-sitter parsing library"
|
||||
version = "0.19.1"
|
||||
keywords = ["incremental", "parsing", "php"]
|
||||
categories = ["parsing", "text-editors"]
|
||||
repository = "https://github.com/tree-sitter/tree-sitter-php"
|
||||
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, < 0.21"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Josh Vera, GitHub
|
||||
|
||||
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.
|
||||
@ -1,114 +0,0 @@
|
||||
VERSION := 0.19.0
|
||||
|
||||
# Repository
|
||||
SRC_DIR := src
|
||||
|
||||
PARSER_REPO_URL := $(shell git -C $(SRC_DIR) remote get-url origin )
|
||||
|
||||
ifeq (, $(PARSER_NAME))
|
||||
PARSER_NAME := $(shell basename $(PARSER_REPO_URL))
|
||||
PARSER_NAME := $(subst tree-sitter-,,$(PARSER_NAME))
|
||||
PARSER_NAME := $(subst .git,,$(PARSER_NAME))
|
||||
endif
|
||||
|
||||
ifeq (, $(PARSER_URL))
|
||||
PARSER_URL := $(subst :,/,$(PARSER_REPO_URL))
|
||||
PARSER_URL := $(subst git@,https://,$(PARSER_URL))
|
||||
PARSER_URL := $(subst .git,,$(PARSER_URL))
|
||||
endif
|
||||
|
||||
UPPER_PARSER_NAME := $(shell echo $(PARSER_NAME) | tr a-z A-Z )
|
||||
|
||||
# install directory layout
|
||||
PREFIX ?= /usr/local
|
||||
INCLUDEDIR ?= $(PREFIX)/include
|
||||
LIBDIR ?= $(PREFIX)/lib
|
||||
PCLIBDIR ?= $(LIBDIR)/pkgconfig
|
||||
|
||||
# collect C++ sources, and link if necessary
|
||||
CPPSRC := $(wildcard $(SRC_DIR)/*.cc)
|
||||
|
||||
ifeq (, $(CPPSRC))
|
||||
ADDITIONALLIBS :=
|
||||
else
|
||||
ADDITIONALLIBS := -lc++
|
||||
endif
|
||||
|
||||
# collect sources
|
||||
SRC := $(wildcard $(SRC_DIR)/*.c)
|
||||
SRC += $(CPPSRC)
|
||||
OBJ := $(addsuffix .o,$(basename $(SRC)))
|
||||
|
||||
# ABI versioning
|
||||
SONAME_MAJOR := 0
|
||||
SONAME_MINOR := 0
|
||||
|
||||
CFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||
CXXFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||
override CFLAGS += -std=gnu99 -fPIC
|
||||
override CXXFLAGS += -fPIC
|
||||
|
||||
# OS-specific bits
|
||||
ifeq ($(shell uname),Darwin)
|
||||
SOEXT = dylib
|
||||
SOEXTVER_MAJOR = $(SONAME_MAJOR).dylib
|
||||
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).dylib
|
||||
LINKSHARED := $(LINKSHARED)-dynamiclib -Wl,
|
||||
ifneq ($(ADDITIONALLIBS),)
|
||||
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS),
|
||||
endif
|
||||
LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/libtree-sitter-$(PARSER_NAME).$(SONAME_MAJOR).dylib,-rpath,@executable_path/../Frameworks
|
||||
else
|
||||
SOEXT = so
|
||||
SOEXTVER_MAJOR = so.$(SONAME_MAJOR)
|
||||
SOEXTVER = so.$(SONAME_MAJOR).$(SONAME_MINOR)
|
||||
LINKSHARED := $(LINKSHARED)-shared -Wl,
|
||||
ifneq ($(ADDITIONALLIBS),)
|
||||
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS)
|
||||
endif
|
||||
LINKSHARED := $(LINKSHARED)-soname,libtree-sitter-$(PARSER_NAME).so.$(SONAME_MAJOR)
|
||||
endif
|
||||
ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly))
|
||||
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
|
||||
endif
|
||||
|
||||
all: libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXTVER) bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||
|
||||
libtree-sitter-$(PARSER_NAME).a: $(OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libtree-sitter-$(PARSER_NAME).$(SOEXTVER): $(OBJ)
|
||||
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
|
||||
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||
|
||||
bindings/c/$(PARSER_NAME).h:
|
||||
sed -e 's|@UPPER_PARSERNAME@|$(UPPER_PARSER_NAME)|' \
|
||||
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||
bindings/c/tree-sitter.h.in > $@
|
||||
|
||||
bindings/c/tree-sitter-$(PARSER_NAME).pc:
|
||||
sed -e 's|@LIBDIR@|$(LIBDIR)|;s|@INCLUDEDIR@|$(INCLUDEDIR)|;s|@VERSION@|$(VERSION)|' \
|
||||
-e 's|=$(PREFIX)|=$${prefix}|' \
|
||||
-e 's|@PREFIX@|$(PREFIX)|' \
|
||||
-e 's|@ADDITIONALLIBS@|$(ADDITIONALLIBS)|' \
|
||||
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||
-e 's|@PARSERURL@|$(PARSER_URL)|' \
|
||||
bindings/c/tree-sitter.pc.in > $@
|
||||
|
||||
install: all
|
||||
install -d '$(DESTDIR)$(LIBDIR)'
|
||||
install -m755 libtree-sitter-$(PARSER_NAME).a '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).a
|
||||
install -m755 libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter
|
||||
install -m644 bindings/c/$(PARSER_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/
|
||||
install -d '$(DESTDIR)$(PCLIBDIR)'
|
||||
install -m644 bindings/c/tree-sitter-$(PARSER_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXT) libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR) libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||
rm -f bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||
|
||||
.PHONY: all install clean
|
||||
@ -1,37 +0,0 @@
|
||||
// swift-tools-version:5.3
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "TreeSitterPHP",
|
||||
products: [
|
||||
.library(name: "TreeSitterPHP", targets: ["TreeSitterPHP"]),
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(name: "TreeSitterPHP",
|
||||
path: ".",
|
||||
exclude: [
|
||||
"binding.gyp",
|
||||
"bindings",
|
||||
"Cargo.toml",
|
||||
"corpus",
|
||||
"grammar.js",
|
||||
"LICENSE",
|
||||
"Makefile",
|
||||
"package.json",
|
||||
"README.md",
|
||||
"script",
|
||||
"src/grammar.json",
|
||||
"src/node-types.json",
|
||||
],
|
||||
sources: [
|
||||
"src/parser.c",
|
||||
"src/scanner.cc",
|
||||
],
|
||||
resources: [
|
||||
.copy("queries")
|
||||
],
|
||||
publicHeadersPath: "bindings/swift",
|
||||
cSettings: [.headerSearchPath("src")])
|
||||
]
|
||||
)
|
||||
@ -1,9 +0,0 @@
|
||||
tree-sitter-php
|
||||
==================
|
||||
|
||||
[](https://github.com/tree-sitter/tree-sitter-php/actions/workflows/ci.yml)
|
||||
|
||||
PHP grammar for [tree-sitter][].
|
||||
|
||||
[tree-sitter]: https://github.com/tree-sitter/tree-sitter
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_php_binding",
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"src/parser.c",
|
||||
"src/scanner.cc",
|
||||
"bindings/node/binding.cc"
|
||||
],
|
||||
"cflags_c": [
|
||||
"-std=c99"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#ifndef TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
#define TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
|
||||
#include <tree_sitter/parser.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern TSLanguage *tree_sitter_@PARSERNAME@();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
@ -1,11 +0,0 @@
|
||||
prefix=@PREFIX@
|
||||
libdir=@LIBDIR@
|
||||
includedir=@INCLUDEDIR@
|
||||
additionallibs=@ADDITIONALLIBS@
|
||||
|
||||
Name: tree-sitter-@PARSERNAME@
|
||||
Description: A tree-sitter grammar for the @PARSERNAME@ programming language.
|
||||
URL: @PARSERURL@
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} ${additionallibs} -ltree-sitter-@PARSERNAME@
|
||||
Cflags: -I${includedir}
|
||||
@ -1,28 +0,0 @@
|
||||
#include "tree_sitter/parser.h"
|
||||
#include <node.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
extern "C" TSLanguage * tree_sitter_php();
|
||||
|
||||
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_php());
|
||||
|
||||
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("php").ToLocalChecked());
|
||||
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||
}
|
||||
|
||||
NODE_MODULE(tree_sitter_php_binding, Init)
|
||||
|
||||
} // namespace
|
||||
@ -1,19 +0,0 @@
|
||||
try {
|
||||
module.exports = require("../../build/Release/tree_sitter_php_binding");
|
||||
} catch (error1) {
|
||||
if (error1.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error1;
|
||||
}
|
||||
try {
|
||||
module.exports = require("../../build/Debug/tree_sitter_php_binding");
|
||||
} catch (error2) {
|
||||
if (error2.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error2;
|
||||
}
|
||||
throw error1
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||
} catch (_) {}
|
||||
@ -1,48 +0,0 @@
|
||||
# tree-sitter-php
|
||||
|
||||
This crate provides support of the PHP language for the [tree-sitter][] parsing library. To use this crate, add it to
|
||||
the `[dependencies]` section of your
|
||||
`Cargo.toml` file. As this crate is not (yet) published to the central registry, you will have to specify it as a git
|
||||
dependency, currently we suggest using the `master` branch.
|
||||
|
||||
You will also need the [tree-sitter crate][] to do the actual parsing here.
|
||||
|
||||
``` toml
|
||||
[dependencies]
|
||||
tree-sitter = "0.19"
|
||||
tree-sitter-php = { git = "https://github.com/tree-sitter/tree-sitter-php.git", branch = "master" }
|
||||
```
|
||||
|
||||
To you the parser, you need to obtain an instance of a [`tree_sitter::Language`][Language] struct for php.
|
||||
The `language()` function provides this.
|
||||
Passing this struct to a [`tree_sitter::Parser`][Parser] will enable it to parse PHP.
|
||||
|
||||
``` rust
|
||||
use tree_sitter::Parser;
|
||||
|
||||
fn main() {
|
||||
let code = r#"
|
||||
function double(int $x) {
|
||||
return $x * 2;
|
||||
}
|
||||
"#;
|
||||
let mut parser = Parser::new();
|
||||
parser
|
||||
.set_language(tree_sitter_php::language())
|
||||
.expect("Error loading PHP parsing support");
|
||||
let parsed = parser.parse(code, None);
|
||||
println!("{:#?}", parsed);
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
[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
|
||||
@ -1,29 +0,0 @@
|
||||
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);
|
||||
|
||||
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||
c_config.compile("parser");
|
||||
|
||||
// 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);
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
cpp_config.compile("scanner");
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
//! This crate provides php 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_php::language()).expect("Error loading php 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_php() -> 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_php() }
|
||||
}
|
||||
|
||||
/// 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 HIGHLIGHT_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 php language");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#ifndef TREE_SITTER_PHP_H_
|
||||
#define TREE_SITTER_PHP_H_
|
||||
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern TSLanguage *tree_sitter_php();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_PHP_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "tree-sitter-php",
|
||||
"version": "0.19.0",
|
||||
"description": "PHP grammar for tree-sitter",
|
||||
"main": "bindings/node",
|
||||
"keywords": [
|
||||
"parser",
|
||||
"php"
|
||||
],
|
||||
"author": "Josh Vera",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tree-sitter/tree-sitter-php/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tree-sitter/tree-sitter-php#readme",
|
||||
"dependencies": {
|
||||
"nan": "^2.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tree-sitter-cli": "^0.19.1",
|
||||
"shelljs": "^0.8.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tree-sitter generate && node-gyp build",
|
||||
"test": "tree-sitter test && node script/parse-examples.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tree-sitter/tree-sitter-php.git"
|
||||
},
|
||||
"tree-sitter": [
|
||||
{
|
||||
"scope": "source.php",
|
||||
"file-types": [
|
||||
"php"
|
||||
],
|
||||
"highlights": "queries/highlights.scm"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
(php_tag) @tag
|
||||
"?>" @tag
|
||||
|
||||
; Types
|
||||
|
||||
(primitive_type) @type.builtin
|
||||
(cast_type) @type.builtin
|
||||
(named_type (name) @type) @type
|
||||
(named_type (qualified_name) @type) @type
|
||||
|
||||
; Functions
|
||||
|
||||
(array_creation_expression "array" @function.builtin)
|
||||
(list_literal "list" @function.builtin)
|
||||
|
||||
(method_declaration
|
||||
name: (name) @function.method)
|
||||
|
||||
(function_call_expression
|
||||
function: (qualified_name (name)) @function)
|
||||
|
||||
(scoped_call_expression
|
||||
name: (name) @function)
|
||||
|
||||
(member_call_expression
|
||||
name: (name) @function.method)
|
||||
|
||||
(function_definition
|
||||
name: (name) @function)
|
||||
|
||||
; Member
|
||||
|
||||
(property_element
|
||||
(variable_name) @property)
|
||||
|
||||
(member_access_expression
|
||||
name: (variable_name (name)) @property)
|
||||
(member_access_expression
|
||||
name: (name) @property)
|
||||
|
||||
; Variables
|
||||
|
||||
(relative_scope) @variable.builtin
|
||||
|
||||
((name) @constant
|
||||
(#match? @constant "^_?[A-Z][A-Z\\d_]+$"))
|
||||
|
||||
((name) @constructor
|
||||
(#match? @constructor "^[A-Z]"))
|
||||
|
||||
((name) @variable.builtin
|
||||
(#eq? @variable.builtin "this"))
|
||||
|
||||
(variable_name) @variable
|
||||
|
||||
; Basic tokens
|
||||
|
||||
(string) @string
|
||||
(heredoc) @string
|
||||
(boolean) @constant.builtin
|
||||
(null) @constant.builtin
|
||||
(integer) @number
|
||||
(float) @number
|
||||
(comment) @comment
|
||||
|
||||
"$" @operator
|
||||
|
||||
; Keywords
|
||||
|
||||
"abstract" @keyword
|
||||
"as" @keyword
|
||||
"break" @keyword
|
||||
"case" @keyword
|
||||
"catch" @keyword
|
||||
"class" @keyword
|
||||
"const" @keyword
|
||||
"continue" @keyword
|
||||
"declare" @keyword
|
||||
"default" @keyword
|
||||
"do" @keyword
|
||||
"echo" @keyword
|
||||
"else" @keyword
|
||||
"elseif" @keyword
|
||||
"enddeclare" @keyword
|
||||
"endforeach" @keyword
|
||||
"endif" @keyword
|
||||
"endswitch" @keyword
|
||||
"endwhile" @keyword
|
||||
"extends" @keyword
|
||||
"final" @keyword
|
||||
"finally" @keyword
|
||||
"foreach" @keyword
|
||||
"function" @keyword
|
||||
"global" @keyword
|
||||
"if" @keyword
|
||||
"implements" @keyword
|
||||
"include_once" @keyword
|
||||
"include" @keyword
|
||||
"insteadof" @keyword
|
||||
"interface" @keyword
|
||||
"namespace" @keyword
|
||||
"new" @keyword
|
||||
"private" @keyword
|
||||
"protected" @keyword
|
||||
"public" @keyword
|
||||
"require_once" @keyword
|
||||
"require" @keyword
|
||||
"return" @keyword
|
||||
"static" @keyword
|
||||
"switch" @keyword
|
||||
"throw" @keyword
|
||||
"trait" @keyword
|
||||
"try" @keyword
|
||||
"use" @keyword
|
||||
"while" @keyword
|
||||
@ -1,3 +0,0 @@
|
||||
((text) @injection.content
|
||||
(#set! injection.language "html")
|
||||
(#set! injection.combined))
|
||||
@ -1,26 +0,0 @@
|
||||
(class_declaration
|
||||
name: (name) @name) @definition.class
|
||||
|
||||
(function_definition
|
||||
name: (name) @name) @definition.function
|
||||
|
||||
(method_declaration
|
||||
name: (name) @name) @definition.function
|
||||
|
||||
(object_creation_expression
|
||||
[
|
||||
(qualified_name (name) @name)
|
||||
(variable_name (name) @name)
|
||||
]) @reference.class
|
||||
|
||||
(function_call_expression
|
||||
function: [
|
||||
(qualified_name (name) @name)
|
||||
(variable_name (name)) @name
|
||||
]) @reference.call
|
||||
|
||||
(scoped_call_expression
|
||||
name: (name) @name) @reference.call
|
||||
|
||||
(member_call_expression
|
||||
name: (name) @name) @reference.call
|
||||
@ -1 +0,0 @@
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
function checkout_at() {
|
||||
path="examples/$1"
|
||||
url=$2
|
||||
sha=$3
|
||||
|
||||
if [ ! -d "$path" ]; then
|
||||
git clone "https://github.com/$url" "$path"
|
||||
fi
|
||||
|
||||
pushd "$path"
|
||||
git fetch && git reset --hard "$sha"
|
||||
popd
|
||||
}
|
||||
|
||||
checkout_at "laravel" "laravel/laravel" "9d0862b3340c8243ee072afc181e315ffa35e110"
|
||||
checkout_at "phabricator" "phacility/phabricator" "d0b01a41f2498fb2a6487c2d6704dc7acfd4675f"
|
||||
checkout_at "phpunit" "sebastianbergmann/phpunit" "5e523bdc7dd4d90fed9fb29d1df05347b3e7eaba"
|
||||
checkout_at "WordPress" "WordPress/WordPress" "45286c5bb3f6fe5005567903ec858d87077eae2c"
|
||||
|
||||
known_failures="$(cat script/known-failures.txt)"
|
||||
|
||||
tree-sitter parse -q \
|
||||
'examples/**/*.php' \
|
||||
$(for file in $known_failures; do echo "!${file}"; done)
|
||||
|
||||
example_count=$(find examples -name '*.php' | 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
|
||||
@ -1,102 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const os = require('os')
|
||||
const util = require('util');
|
||||
const { exec, execSync } = require('child_process')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function main() {
|
||||
checkoutExampleProjects([
|
||||
{ dir: 'laravel', repository: 'https://github.com/laravel/laravel', sha: '9d0862b3340c8243ee072afc181e315ffa35e110' },
|
||||
{ dir: 'framework', repository: 'https://github.com/laravel/framework', sha: '45d439e98a6b14afde8911f7d22a265948adbf72' },
|
||||
{ dir: 'phabricator', repository: 'https://github.com/phacility/phabricator', sha: 'd0b01a41f2498fb2a6487c2d6704dc7acfd4675f' },
|
||||
{ dir: 'phpunit', repository: 'https://github.com/sebastianbergmann/phpunit', sha: '5e523bdc7dd4d90fed9fb29d1df05347b3e7eaba' },
|
||||
{ dir: 'WordPress', repository: 'https://github.com/WordPress/WordPress', sha: '45286c5bb3f6fe5005567903ec858d87077eae2c' },
|
||||
{ dir: 'mediawiki', repository: 'https://github.com/wikimedia/mediawiki', sha: 'b6b88cbf98fb0c7891324709a85eabc290ed28b4' },
|
||||
])
|
||||
|
||||
parseExamples()
|
||||
}
|
||||
|
||||
function parseExamples() {
|
||||
const knownFailures = loadKnownFailures().split(/\r\n|\n/).filter(line => line.length > 0)
|
||||
|
||||
let excludeString = knownFailures.join(" !")
|
||||
if (knownFailures.length > 0) {
|
||||
excludeString = "!" + excludeString
|
||||
}
|
||||
|
||||
if (os.platform == 'win32') {
|
||||
excludeString = convertToWindowsPath(excludeString)
|
||||
}
|
||||
|
||||
exec('"./node_modules/.bin/tree-sitter" parse -q examples/**/*.php ' + excludeString, (err, stdout) => {
|
||||
const failures = extractFailureFilePaths(stdout)
|
||||
failures.forEach(failure => {
|
||||
if (!knownFailures.includes(failure)) {
|
||||
console.error(`Unknown failure occurred: ${failure}`)
|
||||
}
|
||||
})
|
||||
|
||||
const failureCount = failures.length + knownFailures.length
|
||||
const exampleCount = countExampleFiles()
|
||||
const successCount = exampleCount - failureCount;
|
||||
const successPercent = 100 * successCount / exampleCount
|
||||
|
||||
console.log(`Successfully parsed ${successCount} of ${exampleCount} example files (${successPercent.toFixed(2)}%)`)
|
||||
})
|
||||
}
|
||||
|
||||
function extractFailureFilePaths(stdout) {
|
||||
return stdout.split(/\r\n|\n/).filter(line => line.length > 0).map(line => convertToUnixPath(line.substring(0, line.indexOf(" "))))
|
||||
}
|
||||
|
||||
function convertToUnixPath(filePathString) {
|
||||
return filePathString.split("\\").join("/")
|
||||
}
|
||||
|
||||
function convertToWindowsPath(filePathString) {
|
||||
return filePathString.split("/").join("\\")
|
||||
}
|
||||
|
||||
function countExampleFiles() {
|
||||
return shell.find('./examples').filter((file) => { return file.match(/\.php$/) }).length
|
||||
}
|
||||
|
||||
function createExamplesDirectoryIfNotExists() {
|
||||
const dir = './examples'
|
||||
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir)
|
||||
}
|
||||
}
|
||||
|
||||
function checkoutExampleProjects(projects) {
|
||||
createExamplesDirectoryIfNotExists()
|
||||
|
||||
checkoutPromise = util.promisify(checkoutExampleProject)
|
||||
|
||||
Promise.all(projects.map((project) => checkoutPromise(project)))
|
||||
}
|
||||
|
||||
function checkoutExampleProject(project) {
|
||||
const projectDir = './examples/' + project.dir
|
||||
if (!fs.existsSync(projectDir)) {
|
||||
cloneRepository(project)
|
||||
}
|
||||
|
||||
checkoutCommit(project)
|
||||
}
|
||||
|
||||
function cloneRepository(project) {
|
||||
execSync('cd examples && git clone --quiet ' + project.repository + ' ' + project.dir + ' && cd ..')
|
||||
}
|
||||
|
||||
function checkoutCommit(project) {
|
||||
execSync('cd examples/' + project.dir + ' && git fetch --quiet && git reset --quiet --hard "' + project.sha + '" && cd ../..')
|
||||
}
|
||||
|
||||
function loadKnownFailures() {
|
||||
return fs.readFileSync('./script/known-failures.txt').toString()
|
||||
}
|
||||
|
||||
main()
|
||||
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
@ -1,465 +0,0 @@
|
||||
#include <tree_sitter/parser.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cwctype>
|
||||
|
||||
namespace {
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
enum TokenType {
|
||||
AUTOMATIC_SEMICOLON,
|
||||
ENCAPSED_STRING_CHARS,
|
||||
ENCAPSED_STRING_CHARS_AFTER_VARIABLE,
|
||||
ENCAPSED_STRING_CHARS_HEREDOC,
|
||||
ENCAPSED_STRING_CHARS_AFTER_VARIABLE_HEREDOC,
|
||||
EOF_TOKEN,
|
||||
HEREDOC_START,
|
||||
HEREDOC_END,
|
||||
NOWDOC_STRING,
|
||||
SENTINEL_ERROR, // Unused token used to indicate error recovery mode
|
||||
};
|
||||
|
||||
struct Heredoc {
|
||||
Heredoc() : end_word_indentation_allowed(false) {}
|
||||
|
||||
string word;
|
||||
bool end_word_indentation_allowed;
|
||||
};
|
||||
|
||||
struct Scanner {
|
||||
bool has_leading_whitespace;
|
||||
vector<Heredoc> open_heredocs;
|
||||
|
||||
Scanner() : has_leading_whitespace(false) {}
|
||||
|
||||
void reset() {
|
||||
open_heredocs.clear();
|
||||
}
|
||||
|
||||
enum ScanContentResult {
|
||||
Error,
|
||||
End
|
||||
};
|
||||
|
||||
unsigned serialize(char *buffer) {
|
||||
unsigned i = 0;
|
||||
|
||||
buffer[i++] = open_heredocs.size();
|
||||
for (
|
||||
vector<Heredoc>::iterator iter = open_heredocs.begin(),
|
||||
end = open_heredocs.end();
|
||||
iter != end;
|
||||
++iter
|
||||
) {
|
||||
if (i + 2 + iter->word.size() >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) return 0;
|
||||
buffer[i++] = iter->end_word_indentation_allowed;
|
||||
buffer[i++] = iter->word.size();
|
||||
iter->word.copy(&buffer[i], iter->word.size());
|
||||
i += iter->word.size();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void deserialize(const char *buffer, unsigned length) {
|
||||
unsigned i = 0;
|
||||
has_leading_whitespace = false;
|
||||
open_heredocs.clear();
|
||||
|
||||
if (length == 0) return;
|
||||
|
||||
uint8_t open_heredoc_count = buffer[i++];
|
||||
for (unsigned j = 0; j < open_heredoc_count; j++) {
|
||||
Heredoc heredoc;
|
||||
heredoc.end_word_indentation_allowed = buffer[i++];
|
||||
uint8_t word_length = buffer[i++];
|
||||
heredoc.word.assign(buffer + i, buffer + i + word_length);
|
||||
i += word_length;
|
||||
open_heredocs.push_back(heredoc);
|
||||
}
|
||||
|
||||
// assert(i == length);
|
||||
}
|
||||
|
||||
void skip(TSLexer *lexer) {
|
||||
has_leading_whitespace = true;
|
||||
lexer->advance(lexer, true);
|
||||
}
|
||||
|
||||
static void advance(TSLexer *lexer) {
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
|
||||
bool scan_whitespace(TSLexer *lexer) {
|
||||
for (;;) {
|
||||
while (iswspace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
if (lexer->lookahead == '/') {
|
||||
advance(lexer);
|
||||
|
||||
if (lexer->lookahead == '/') {
|
||||
advance(lexer);
|
||||
while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
|
||||
advance(lexer);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_valid_name_char(TSLexer *lexer) {
|
||||
return iswalpha(lexer->lookahead) || lexer->lookahead == '_';
|
||||
}
|
||||
|
||||
static bool is_escapable_sequence(TSLexer *lexer) {
|
||||
// Note: remember to also update the escape_sequence rule in the
|
||||
// main grammar whenever changing this method
|
||||
int32_t letter = lexer->lookahead;
|
||||
|
||||
if (letter == 'n' ||
|
||||
letter == 'r' ||
|
||||
letter == 't' ||
|
||||
letter == 'v' ||
|
||||
letter == 'e' ||
|
||||
letter == 'f' ||
|
||||
letter == '\\' ||
|
||||
letter == '$' ||
|
||||
letter == '"') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Hex
|
||||
if (letter == 'x') {
|
||||
advance(lexer);
|
||||
return isxdigit(lexer->lookahead);
|
||||
}
|
||||
|
||||
// Unicode
|
||||
if (letter == 'u') {
|
||||
return true; // We handle the case where this is not really an escape sequence in grammar.js - this is needed to support the edge case "\u{$a}" in which case "\u" is to be interprented as characters and {$a} as a variable
|
||||
}
|
||||
|
||||
// Octal
|
||||
return iswdigit(lexer->lookahead) && lexer->lookahead >= '0' && lexer->lookahead <= '7';
|
||||
}
|
||||
|
||||
bool scan_nowdoc_string(TSLexer *lexer) {
|
||||
bool has_consumed_content = false;
|
||||
if (open_heredocs.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// While PHP requires the nowdoc end tag to be the very first on a new line, there may be an
|
||||
// arbitrary amount of whitespace before the closing token
|
||||
while (iswspace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
has_consumed_content = true;
|
||||
}
|
||||
|
||||
string heredoc_tag = open_heredocs.back().word;
|
||||
|
||||
bool end_tag_matched = false;
|
||||
|
||||
for (int i = 0; i < heredoc_tag.length(); i++) {
|
||||
if (lexer->lookahead != heredoc_tag[i]) break;
|
||||
advance(lexer);
|
||||
has_consumed_content = true;
|
||||
|
||||
end_tag_matched = (i == heredoc_tag.length() - 1 && (iswspace(lexer->lookahead) || lexer->lookahead == ';' || lexer->lookahead == ',' || lexer->lookahead == ')'));
|
||||
}
|
||||
|
||||
if (end_tag_matched) {
|
||||
// There may be an arbitrary amount of white space after the end tag
|
||||
while (iswspace(lexer->lookahead) && lexer->lookahead != '\r' && lexer->lookahead != '\n') {
|
||||
advance(lexer);
|
||||
has_consumed_content = true;
|
||||
}
|
||||
|
||||
// Return to allow the end tag parsing if we've encountered an end tag at a valid position
|
||||
if (lexer->lookahead == ';' || lexer->lookahead == ',' || lexer->lookahead == ')' || lexer->lookahead == '\n' || lexer->lookahead == '\r') {
|
||||
// , and ) is needed to support heredoc in function arguments
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (bool has_content = has_consumed_content;; has_content = true) {
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
switch (lexer->lookahead) {
|
||||
case '\n':
|
||||
case '\r':
|
||||
return has_content;
|
||||
default:
|
||||
if (lexer->eof(lexer)) return false;
|
||||
advance(lexer);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scan_encapsed_part_string(TSLexer *lexer, bool is_after_variable, bool is_heredoc) {
|
||||
bool has_consumed_content = false;
|
||||
|
||||
if (is_heredoc && !open_heredocs.empty()) {
|
||||
// While PHP requires the heredoc end tag to be the very first on a new line, there may be an
|
||||
// arbitrary amount of whitespace before the closing token
|
||||
// However, we should not consume \r or \n
|
||||
while (iswspace(lexer->lookahead) && lexer->lookahead != '\r' && lexer->lookahead != '\n') {
|
||||
advance(lexer);
|
||||
has_consumed_content = true;
|
||||
}
|
||||
|
||||
string heredoc_tag = open_heredocs.back().word;
|
||||
|
||||
bool end_tag_matched = false;
|
||||
|
||||
for (int i = 0; i < heredoc_tag.length(); i++) {
|
||||
if (lexer->lookahead != heredoc_tag[i]) break;
|
||||
has_consumed_content = true;
|
||||
advance(lexer);
|
||||
|
||||
end_tag_matched = (i == heredoc_tag.length() - 1 && (iswspace(lexer->lookahead) || lexer->lookahead == ';' || lexer->lookahead == ',' || lexer->lookahead == ')'));
|
||||
}
|
||||
|
||||
if (end_tag_matched) {
|
||||
// There may be an arbitrary amount of white space after the end tag
|
||||
// However, we should not consume \r or \n
|
||||
while (iswspace(lexer->lookahead) && lexer->lookahead != '\r' && lexer->lookahead != '\n') {
|
||||
advance(lexer);
|
||||
has_consumed_content = true;
|
||||
}
|
||||
|
||||
// Return to allow the end tag parsing if we've encountered an end tag at a valid position
|
||||
if (lexer->lookahead == ';' || lexer->lookahead == ',' || lexer->lookahead == ')' || lexer->lookahead == '\n' || lexer->lookahead == '\r') {
|
||||
// , and ) is needed to support heredoc in function arguments
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (bool has_content = has_consumed_content;; has_content = true) {
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
switch (lexer->lookahead) {
|
||||
case '"':
|
||||
if (!is_heredoc) {
|
||||
return has_content;
|
||||
}
|
||||
advance(lexer);
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
if (is_heredoc) {
|
||||
return has_content;
|
||||
}
|
||||
advance(lexer);
|
||||
break;
|
||||
case '\\':
|
||||
advance(lexer);
|
||||
|
||||
// \{ should not be interprented as an escape sequence, but both
|
||||
// should be consumed as normal characters
|
||||
if (lexer->lookahead == '{') {
|
||||
advance(lexer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_heredoc && lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_escapable_sequence(lexer)) {
|
||||
return has_content;
|
||||
}
|
||||
break;
|
||||
case '$':
|
||||
advance(lexer);
|
||||
|
||||
if (is_valid_name_char(lexer) || lexer->lookahead == '{') {
|
||||
return has_content;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if (is_after_variable) {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
if (is_valid_name_char(lexer)) {
|
||||
return has_content;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '[':
|
||||
if (is_after_variable) {
|
||||
return has_content;
|
||||
}
|
||||
advance(lexer);
|
||||
break;
|
||||
case '{':
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '$') {
|
||||
return has_content;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lexer->eof(lexer)) return false;
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
is_after_variable = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string scan_heredoc_word(TSLexer *lexer) {
|
||||
string result;
|
||||
|
||||
while (is_valid_name_char(lexer)) {
|
||||
result += lexer->lookahead;
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
||||
const bool is_error_recovery = valid_symbols[SENTINEL_ERROR];
|
||||
|
||||
if (is_error_recovery) {
|
||||
// Consider if we should clear the heredoc list on error
|
||||
return false;
|
||||
}
|
||||
|
||||
has_leading_whitespace = false;
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
if (valid_symbols[ENCAPSED_STRING_CHARS_AFTER_VARIABLE]) {
|
||||
lexer->result_symbol = ENCAPSED_STRING_CHARS_AFTER_VARIABLE;
|
||||
return scan_encapsed_part_string(lexer, /* is_after_variable */ true, /* is_heredoc */ false);
|
||||
}
|
||||
|
||||
if (valid_symbols[ENCAPSED_STRING_CHARS]) {
|
||||
lexer->result_symbol = ENCAPSED_STRING_CHARS;
|
||||
return scan_encapsed_part_string(lexer, /* is_after_variable */ false, /* is_heredoc */ false);
|
||||
}
|
||||
|
||||
if (valid_symbols[ENCAPSED_STRING_CHARS_AFTER_VARIABLE_HEREDOC]) {
|
||||
lexer->result_symbol = ENCAPSED_STRING_CHARS_AFTER_VARIABLE_HEREDOC;
|
||||
return scan_encapsed_part_string(lexer, /* is_after_variable */ true, /* is_heredoc */ true);
|
||||
}
|
||||
|
||||
if (valid_symbols[ENCAPSED_STRING_CHARS_HEREDOC]) {
|
||||
lexer->result_symbol = ENCAPSED_STRING_CHARS_HEREDOC;
|
||||
return scan_encapsed_part_string(lexer, /* is_after_variable */ false, /* is_heredoc */ true);
|
||||
}
|
||||
|
||||
if (valid_symbols[NOWDOC_STRING]) {
|
||||
lexer->result_symbol = NOWDOC_STRING;
|
||||
return scan_nowdoc_string(lexer);
|
||||
}
|
||||
|
||||
if (valid_symbols[HEREDOC_END]) {
|
||||
lexer->result_symbol = HEREDOC_END;
|
||||
if (open_heredocs.empty()) return false;
|
||||
|
||||
Heredoc heredoc = open_heredocs.back();
|
||||
|
||||
while (iswspace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
if (heredoc.word != scan_heredoc_word(lexer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
open_heredocs.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!scan_whitespace(lexer)) return false;
|
||||
|
||||
if (valid_symbols[EOF_TOKEN] && lexer->eof(lexer)) {
|
||||
lexer->result_symbol = EOF_TOKEN;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (valid_symbols[HEREDOC_START]) {
|
||||
lexer->result_symbol = HEREDOC_START;
|
||||
Heredoc heredoc;
|
||||
|
||||
while (iswspace(lexer->lookahead)) {
|
||||
skip(lexer);
|
||||
}
|
||||
|
||||
heredoc.word = scan_heredoc_word(lexer);
|
||||
if (heredoc.word.empty()) return false;
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
open_heredocs.push_back(heredoc);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid_symbols[AUTOMATIC_SEMICOLON]) {
|
||||
lexer->result_symbol = AUTOMATIC_SEMICOLON;
|
||||
|
||||
if (lexer->lookahead != '?') return false;
|
||||
|
||||
advance(lexer);
|
||||
|
||||
return lexer->lookahead == '>';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *tree_sitter_php_external_scanner_create() {
|
||||
return new Scanner();
|
||||
}
|
||||
|
||||
unsigned tree_sitter_php_external_scanner_serialize(void *payload, char *buffer) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
return scanner->serialize(buffer);
|
||||
}
|
||||
|
||||
void tree_sitter_php_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
scanner->deserialize(buffer, length);
|
||||
}
|
||||
|
||||
void tree_sitter_php_external_scanner_destroy(void *payload) {
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
delete scanner;
|
||||
}
|
||||
|
||||
bool tree_sitter_php_external_scanner_scan(void *payload, TSLexer *lexer,
|
||||
const bool *valid_symbols) {
|
||||
|
||||
Scanner *scanner = static_cast<Scanner *>(payload);
|
||||
return scanner->scan(lexer, valid_symbols);
|
||||
}
|
||||
|
||||
void tree_sitter_php_external_scanner_reset(void *p) {}
|
||||
|
||||
}
|
||||
@ -1,223 +0,0 @@
|
||||
#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_
|
||||
@ -1,67 +0,0 @@
|
||||
=========================================
|
||||
#131: Parse error when using self as constant
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
define('self', 'value');
|
||||
var_dump(self);
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement
|
||||
(function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments
|
||||
(argument (string (string_value)))
|
||||
(argument (string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments (argument (name)))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
#133: Incorrect precedence for error supression operator
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
@trigger_error("a") && trigger_error("b");
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement
|
||||
(binary_expression
|
||||
left: (unary_op_expression
|
||||
(function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
(encapsed_string
|
||||
(string_value)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
right: (function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
(encapsed_string
|
||||
(string_value)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1,770 +0,0 @@
|
||||
=========================================
|
||||
Abstract class
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
abstract class A {
|
||||
public function a() {}
|
||||
abstract public function b();
|
||||
}
|
||||
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
(abstract_modifier)
|
||||
(name)
|
||||
(declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
(method_declaration
|
||||
(abstract_modifier)
|
||||
(visibility_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
Anonymous classes
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
new class {
|
||||
public function test() {}
|
||||
};
|
||||
new class extends A implements B, C {};
|
||||
new class() {
|
||||
public $foo;
|
||||
};
|
||||
new class($a, $b) extends A {
|
||||
use T;
|
||||
};
|
||||
|
||||
class A {
|
||||
public function test() {
|
||||
return new class($this) extends A {
|
||||
const A = 'B';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement
|
||||
(object_creation_expression
|
||||
(declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(object_creation_expression
|
||||
(base_clause
|
||||
(name)
|
||||
)
|
||||
(class_interface_clause
|
||||
(name)
|
||||
(name)
|
||||
)
|
||||
(declaration_list)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(object_creation_expression
|
||||
(arguments)
|
||||
(declaration_list
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(property_element
|
||||
(variable_name (name))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(object_creation_expression
|
||||
(arguments
|
||||
(argument
|
||||
(variable_name (name))
|
||||
)
|
||||
(argument
|
||||
(variable_name (name))
|
||||
)
|
||||
)
|
||||
(base_clause
|
||||
(name)
|
||||
)
|
||||
(declaration_list
|
||||
(use_declaration
|
||||
(name)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(class_declaration
|
||||
(name)
|
||||
(declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement
|
||||
(return_statement
|
||||
(object_creation_expression
|
||||
(arguments (argument (variable_name (name))))
|
||||
(base_clause (name))
|
||||
(declaration_list
|
||||
(const_declaration
|
||||
(const_element (name) (string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
Conditional class definition
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
if (true) {
|
||||
class A {}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(if_statement
|
||||
(parenthesized_expression (boolean))
|
||||
(compound_statement
|
||||
(class_declaration
|
||||
(name)
|
||||
(declaration_list)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
Class constant modifiers
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
class Foo {
|
||||
const A = 1;
|
||||
public const B = 2;
|
||||
protected const C = 3;
|
||||
private const D = 4;
|
||||
final const E = 5;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
(name)
|
||||
(declaration_list
|
||||
(const_declaration
|
||||
(const_element (name) (integer))
|
||||
)
|
||||
(const_declaration
|
||||
(visibility_modifier)
|
||||
(const_element (name) (integer))
|
||||
)
|
||||
(const_declaration
|
||||
(visibility_modifier)
|
||||
(const_element (name) (integer))
|
||||
)
|
||||
(const_declaration
|
||||
(visibility_modifier)
|
||||
(const_element (name) (integer))
|
||||
)
|
||||
(const_declaration
|
||||
(final_modifier)
|
||||
(const_element (name) (integer))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
=========================================
|
||||
Final class
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
final class A {}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
(final_modifier)
|
||||
(name)
|
||||
(declaration_list)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
Implicitly public properties and methods
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
abstract class A {
|
||||
var $a;
|
||||
static $b;
|
||||
abstract function c();
|
||||
final function d() {}
|
||||
static function e() {}
|
||||
final static function f() {}
|
||||
function g() {}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
(abstract_modifier)
|
||||
(name)
|
||||
(declaration_list
|
||||
(property_declaration
|
||||
(var_modifier)
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
(property_declaration
|
||||
(static_modifier)
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
(method_declaration
|
||||
(abstract_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
)
|
||||
(method_declaration
|
||||
(final_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
(method_declaration
|
||||
(static_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
(method_declaration
|
||||
(final_modifier)
|
||||
(static_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
(method_declaration
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=========================================
|
||||
Property Types
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
class A {
|
||||
public string $a;
|
||||
protected static D $b;
|
||||
private ?float $c;
|
||||
private $d;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
type: (union_type (primitive_type))
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(static_modifier)
|
||||
type: (union_type (named_type (name)))
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
type: (union_type (optional_type (primitive_type)))
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(property_element (variable_name (name)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
=========================================
|
||||
Constructor Property Promotion
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
class Point {
|
||||
public function __construct(
|
||||
public float $x = 0.0,
|
||||
float $y = 0.0,
|
||||
private float $z = 0.0
|
||||
) {}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(property_promotion_parameter
|
||||
visibility: (visibility_modifier)
|
||||
type: (union_type
|
||||
(primitive_type)
|
||||
)
|
||||
name: (variable_name (name))
|
||||
default_value: (float)
|
||||
)
|
||||
(simple_parameter
|
||||
type: (union_type (primitive_type))
|
||||
name: (variable_name (name))
|
||||
default_value: (float)
|
||||
)
|
||||
(property_promotion_parameter
|
||||
visibility: (visibility_modifier)
|
||||
type: (union_type (primitive_type))
|
||||
name: (variable_name (name))
|
||||
default_value: (float)
|
||||
)
|
||||
)
|
||||
body: (compound_statement)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
================================================================================
|
||||
Readonly properties
|
||||
================================================================================
|
||||
|
||||
<?php
|
||||
class A {
|
||||
private readonly int $pria;
|
||||
private readonly float $prfa;
|
||||
private readonly mixed $prma;
|
||||
private readonly string $prsa;
|
||||
private readonly object $proa;
|
||||
readonly private int $rpia;
|
||||
readonly private float $rpfa;
|
||||
readonly private mixed $rpma;
|
||||
readonly private string $rpsa;
|
||||
readonly private object $rpoa;
|
||||
|
||||
protected readonly int $oria;
|
||||
protected readonly float $orfa;
|
||||
protected readonly mixed $orma;
|
||||
protected readonly string $orsa;
|
||||
protected readonly object $oroa;
|
||||
readonly protected int $roia;
|
||||
readonly protected float $rofa;
|
||||
readonly protected mixed $roma;
|
||||
readonly protected string $rosa;
|
||||
readonly protected object $rooa;
|
||||
|
||||
public readonly int $uria;
|
||||
public readonly float $urfa;
|
||||
public readonly mixed $urma;
|
||||
public readonly string $ursa;
|
||||
public readonly object $uroa;
|
||||
readonly public int $ruia;
|
||||
readonly public float $rufa;
|
||||
readonly public mixed $ruma;
|
||||
readonly public string $rusa;
|
||||
readonly public object $ruoa;
|
||||
|
||||
readonly int $ria;
|
||||
readonly float $rfa;
|
||||
readonly mixed $rma;
|
||||
ReAdOnLy string $rsa;
|
||||
READONLY object $roa;
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
(name)
|
||||
(declaration_list
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(visibility_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(primitive_type))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name))))
|
||||
(property_declaration
|
||||
(readonly_modifier)
|
||||
(union_type
|
||||
(named_type
|
||||
(name)))
|
||||
(property_element
|
||||
(variable_name
|
||||
(name)))))))
|
||||
|
||||
================================================================================
|
||||
Constructor property promotion with readonly modifier
|
||||
================================================================================
|
||||
|
||||
<?php
|
||||
class Point {
|
||||
public function __construct(
|
||||
public $x,
|
||||
protected readonly $y,
|
||||
private readonly int $z,
|
||||
) {}
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(property_promotion_parameter
|
||||
visibility: (visibility_modifier)
|
||||
name: (variable_name (name)))
|
||||
(property_promotion_parameter
|
||||
visibility: (visibility_modifier)
|
||||
readonly: (readonly_modifier)
|
||||
name: (variable_name (name)))
|
||||
(property_promotion_parameter
|
||||
visibility: (visibility_modifier)
|
||||
readonly: (readonly_modifier)
|
||||
type: (union_type (primitive_type))
|
||||
name: (variable_name (name))))
|
||||
body: (compound_statement)))))
|
||||
@ -1,706 +0,0 @@
|
||||
=========================================
|
||||
Interface declarations
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
interface ThrowableInterface {
|
||||
public function getMessage();
|
||||
}
|
||||
|
||||
class Exception_foo implements ThrowableInterface {
|
||||
public $foo = "foo";
|
||||
|
||||
public function getMessage() {
|
||||
return $this->foo;
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(interface_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
name: (name)
|
||||
parameters: (formal_parameters))))
|
||||
(class_declaration
|
||||
name: (name)
|
||||
(class_interface_clause (name))
|
||||
body: (declaration_list
|
||||
(property_declaration
|
||||
(visibility_modifier)
|
||||
(property_element (variable_name (name)) (property_initializer (encapsed_string (string_value)))))
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
name: (name)
|
||||
parameters: (formal_parameters)
|
||||
body: (compound_statement
|
||||
(return_statement (member_access_expression
|
||||
object: (variable_name (name))
|
||||
name: (name))))))))
|
||||
|
||||
==========================
|
||||
Use declarations
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
trait AbstractTrait
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
use LoggerAwareTrait, OtherTrait {}
|
||||
use LoggerAwareTrait, OtherTrait;
|
||||
}
|
||||
|
||||
class AbstractCache
|
||||
{
|
||||
use AbstractTrait {
|
||||
deleteItems as private;
|
||||
AbstractTrait::deleteItem as delete;
|
||||
AbstractTrait::hasItem as has;
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(trait_declaration
|
||||
(name)
|
||||
(declaration_list
|
||||
(use_declaration (name))
|
||||
(use_declaration (name) (name) (use_list))
|
||||
(use_declaration (name) (name))))
|
||||
(class_declaration
|
||||
(name)
|
||||
(declaration_list
|
||||
(use_declaration
|
||||
(name)
|
||||
(use_list
|
||||
(use_as_clause (name) (visibility_modifier))
|
||||
(use_as_clause (class_constant_access_expression (name) (name)) (name))
|
||||
(use_as_clause (class_constant_access_expression (name) (name)) (name)))))))
|
||||
|
||||
==========================
|
||||
Namespace names in namespaces
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
namespace Be \ ta {
|
||||
class A {}
|
||||
class B {}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(namespace_definition
|
||||
name: (namespace_name (name) (name))
|
||||
body: (compound_statement
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list))
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list)))))
|
||||
|
||||
==============================
|
||||
Class declarations
|
||||
==============================
|
||||
|
||||
<?php
|
||||
class foo {
|
||||
function __construct($name) {
|
||||
$GLOBALS['List']= &$this;
|
||||
$this->Name = $name;
|
||||
$GLOBALS['List']->echoName();
|
||||
}
|
||||
|
||||
function echoName() {
|
||||
$GLOBALS['names'][]=$this->Name;
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(method_declaration
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
name: (variable_name (name))))
|
||||
body: (compound_statement
|
||||
(expression_statement (reference_assignment_expression
|
||||
left: (subscript_expression (variable_name (name)) (string (string_value)))
|
||||
right: (variable_name (name))))
|
||||
(expression_statement (assignment_expression
|
||||
left: (member_access_expression
|
||||
object: (variable_name (name))
|
||||
name: (name))
|
||||
right: (variable_name (name))))
|
||||
(expression_statement (member_call_expression
|
||||
object: (subscript_expression (variable_name (name)) (string (string_value)))
|
||||
name: (name)
|
||||
arguments: (arguments)))))
|
||||
(method_declaration
|
||||
name: (name)
|
||||
parameters: (formal_parameters)
|
||||
body: (compound_statement
|
||||
(expression_statement (assignment_expression
|
||||
left: (subscript_expression (subscript_expression (variable_name (name)) (string (string_value))))
|
||||
right: (member_access_expression
|
||||
object: (variable_name (name))
|
||||
name: (name)))))))))
|
||||
|
||||
========================================
|
||||
Class declarations with base classes
|
||||
========================================
|
||||
|
||||
<?php
|
||||
class A extends B {
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
(base_clause (name))
|
||||
body: (declaration_list)))
|
||||
|
||||
==========================
|
||||
Function parameters
|
||||
==========================
|
||||
|
||||
<?php
|
||||
function test(int $a, string ...$b)
|
||||
{
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
type: (union_type (primitive_type))
|
||||
name: (variable_name (name)))
|
||||
(variadic_parameter
|
||||
type: (union_type (primitive_type))
|
||||
name: (variable_name (name))))
|
||||
body: (compound_statement)))
|
||||
|
||||
====================================
|
||||
Functions with default parameters
|
||||
====================================
|
||||
|
||||
<?php
|
||||
function a($arg = self::bar) {
|
||||
echo $arg;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name)
|
||||
(formal_parameters
|
||||
(simple_parameter
|
||||
(variable_name (name))
|
||||
(class_constant_access_expression (relative_scope) (name))))
|
||||
(compound_statement (echo_statement (variable_name (name))))))
|
||||
|
||||
========================================================================
|
||||
Static variables in functions
|
||||
========================================================================
|
||||
|
||||
<?php
|
||||
function blah()
|
||||
{
|
||||
static $hey=0, $yo=0;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(compound_statement
|
||||
(function_static_declaration
|
||||
(static_variable_declaration (variable_name (name)) (integer))
|
||||
(static_variable_declaration (variable_name (name)) (integer))))))
|
||||
|
||||
=========================================
|
||||
Defining Constants
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
define("CONSTANT", "Hello world.");
|
||||
const CONSTANT = 'Hello World';
|
||||
const ANOTHER_CONST = CONSTANT.'; Goodbye World';
|
||||
const ANIMALS = array('dog', 'cat', 'bird');
|
||||
define('ANIMALS', array(
|
||||
'dog',
|
||||
'cat',
|
||||
'bird'
|
||||
));
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement
|
||||
(function_call_expression
|
||||
(name)
|
||||
(arguments
|
||||
(argument (encapsed_string (string_value)))
|
||||
(argument (encapsed_string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(const_declaration
|
||||
(const_element
|
||||
(name)
|
||||
(string (string_value))
|
||||
)
|
||||
)
|
||||
(const_declaration
|
||||
(const_element
|
||||
(name)
|
||||
(binary_expression
|
||||
(name)
|
||||
(string (string_value))
|
||||
)
|
||||
)
|
||||
)
|
||||
(const_declaration
|
||||
(const_element
|
||||
(name)
|
||||
(array_creation_expression
|
||||
(array_element_initializer (string (string_value)))
|
||||
(array_element_initializer (string (string_value)))
|
||||
(array_element_initializer (string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(function_call_expression
|
||||
(name)
|
||||
(arguments
|
||||
(argument (string (string_value)))
|
||||
(argument
|
||||
(array_creation_expression
|
||||
(array_element_initializer (string (string_value)))
|
||||
(array_element_initializer (string (string_value)))
|
||||
(array_element_initializer (string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
=======================================
|
||||
Attributes
|
||||
=======================================
|
||||
|
||||
<?php
|
||||
|
||||
#[Test]
|
||||
function a(#[Test] $a) {
|
||||
$c;
|
||||
}
|
||||
|
||||
class PostsController
|
||||
{
|
||||
#[Test]
|
||||
const CONSTANT = 'constant value';
|
||||
|
||||
#[Test]
|
||||
private string $a = '';
|
||||
|
||||
#[Route("/api/posts/{id}", ["GET"])]
|
||||
public function get(#[Test] $id) { /* ... */ }
|
||||
}
|
||||
|
||||
#[MyAttribute]
|
||||
#[\MyExample\MyAttribute]
|
||||
#[MyAttribute(1234)]
|
||||
#[MyAttribute(MyAttribute::VALUE)]
|
||||
#[MyAttribute(array("key" => "value"))]
|
||||
#[MyAttribute(100 + 200)]
|
||||
class Thing
|
||||
{
|
||||
}
|
||||
|
||||
new #[ExampleAttribute] class() {};
|
||||
#[ExampleAttribute] fn($x) => $x;
|
||||
$baz = #[ExampleAttribute] function($x) {return $x;};
|
||||
|
||||
class A {
|
||||
#[\Assert\All(
|
||||
new \Assert\NotNull,
|
||||
new \Assert\Length(min: 5))
|
||||
]
|
||||
public string $name = '';
|
||||
|
||||
}
|
||||
|
||||
#[
|
||||
A1,
|
||||
A2(),
|
||||
A3(0),
|
||||
A4(x: 1),
|
||||
]
|
||||
function a() {
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
|
||||
(function_definition
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
attributes: (attribute_list
|
||||
(attribute_group (attribute (name)))
|
||||
)
|
||||
name: (variable_name (name))
|
||||
)
|
||||
)
|
||||
body: (compound_statement (expression_statement (variable_name (name))))
|
||||
)
|
||||
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(const_declaration
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
(const_element (name) (string (string_value)))
|
||||
)
|
||||
|
||||
(property_declaration
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
(visibility_modifier)
|
||||
type: (union_type (primitive_type))
|
||||
(property_element (variable_name (name))
|
||||
(property_initializer (string (string_value)))
|
||||
)
|
||||
)
|
||||
(method_declaration
|
||||
attributes: (attribute_list
|
||||
(attribute_group
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments
|
||||
(argument (encapsed_string (string_value)))
|
||||
(argument
|
||||
(array_creation_expression
|
||||
(array_element_initializer (encapsed_string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(visibility_modifier)
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
name: (variable_name (name))
|
||||
)
|
||||
)
|
||||
body: (compound_statement (comment))
|
||||
)
|
||||
)
|
||||
)
|
||||
(class_declaration
|
||||
attributes: (attribute_list
|
||||
(attribute_group
|
||||
(attribute (name))
|
||||
)
|
||||
(attribute_group
|
||||
(attribute
|
||||
(qualified_name
|
||||
(namespace_name_as_prefix
|
||||
(namespace_name (name))
|
||||
)
|
||||
(name)
|
||||
)
|
||||
)
|
||||
)
|
||||
(attribute_group
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments (argument (integer)))
|
||||
)
|
||||
)
|
||||
(attribute_group
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments
|
||||
(argument
|
||||
(class_constant_access_expression
|
||||
(name)
|
||||
(name)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(attribute_group
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments
|
||||
(argument
|
||||
(array_creation_expression
|
||||
(array_element_initializer
|
||||
(encapsed_string (string_value))
|
||||
(encapsed_string (string_value))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(attribute_group
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments
|
||||
(argument
|
||||
(binary_expression
|
||||
left: (integer)
|
||||
right: (integer)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
name: (name)
|
||||
body: (declaration_list)
|
||||
)
|
||||
(expression_statement
|
||||
(object_creation_expression
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
(arguments)
|
||||
(declaration_list)
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(arrow_function
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
name: (variable_name (name))
|
||||
)
|
||||
)
|
||||
body: (variable_name (name))
|
||||
)
|
||||
)
|
||||
(expression_statement
|
||||
(assignment_expression
|
||||
left: (variable_name (name))
|
||||
right: (anonymous_function_creation_expression
|
||||
attributes: (attribute_list (attribute_group (attribute (name))))
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
name: (variable_name (name))
|
||||
)
|
||||
)
|
||||
body: (compound_statement
|
||||
(return_statement
|
||||
(variable_name (name))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(class_declaration
|
||||
name: (name)
|
||||
body: (declaration_list
|
||||
(property_declaration
|
||||
attributes: (attribute_list
|
||||
(attribute_group
|
||||
(attribute
|
||||
(qualified_name
|
||||
(namespace_name_as_prefix (namespace_name (name)))
|
||||
(name)
|
||||
)
|
||||
parameters: (arguments
|
||||
(argument
|
||||
(object_creation_expression
|
||||
(qualified_name
|
||||
(namespace_name_as_prefix (namespace_name (name)))
|
||||
(name)
|
||||
)
|
||||
)
|
||||
)
|
||||
(argument
|
||||
(object_creation_expression
|
||||
(qualified_name
|
||||
(namespace_name_as_prefix (namespace_name (name)))
|
||||
(name)
|
||||
)
|
||||
(arguments
|
||||
(argument
|
||||
name: (name)
|
||||
(integer)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(visibility_modifier)
|
||||
type: (union_type (primitive_type))
|
||||
(property_element
|
||||
(variable_name (name))
|
||||
(property_initializer (string (string_value)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(function_definition
|
||||
attributes: (attribute_list
|
||||
(attribute_group
|
||||
(attribute (name))
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments)
|
||||
)
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments (argument (integer)))
|
||||
)
|
||||
(attribute
|
||||
(name)
|
||||
parameters: (arguments (argument name: (name) (integer)))
|
||||
)
|
||||
)
|
||||
)
|
||||
name: (name)
|
||||
parameters: (formal_parameters)
|
||||
body: (compound_statement)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
=======================================
|
||||
Enums
|
||||
=======================================
|
||||
|
||||
<?php
|
||||
|
||||
enum A {}
|
||||
enum B implements Bar, Baz {
|
||||
}
|
||||
enum C: int implements Bar {}
|
||||
|
||||
enum Suit: string
|
||||
{
|
||||
case Hearts = 'H';
|
||||
case Diamonds;
|
||||
case Clubs = 'C';
|
||||
case Spades = 'S';
|
||||
|
||||
// Fulfills the interface contract.
|
||||
public function color(): string {
|
||||
return match($this) {
|
||||
Suit::Hearts, Suit::Diamonds => 'Red',
|
||||
Suit::Clubs, Suit::Spades => 'Black',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(enum_declaration
|
||||
(name)
|
||||
(enum_declaration_list)
|
||||
)
|
||||
(enum_declaration
|
||||
(name)
|
||||
(class_interface_clause
|
||||
(name)
|
||||
(name)
|
||||
)
|
||||
(enum_declaration_list)
|
||||
)
|
||||
(enum_declaration
|
||||
(name)
|
||||
(union_type (primitive_type))
|
||||
(class_interface_clause (name))
|
||||
(enum_declaration_list)
|
||||
)
|
||||
(enum_declaration
|
||||
(name)
|
||||
(union_type (primitive_type))
|
||||
(enum_declaration_list
|
||||
(enum_case (name) (string (string_value)))
|
||||
(enum_case (name))
|
||||
(enum_case (name) (string (string_value)))
|
||||
(enum_case (name) (string (string_value)))
|
||||
|
||||
(comment)
|
||||
|
||||
(method_declaration
|
||||
(visibility_modifier)
|
||||
(name)
|
||||
(formal_parameters)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement
|
||||
(return_statement
|
||||
(match_expression
|
||||
(parenthesized_expression
|
||||
(variable_name (name))
|
||||
)
|
||||
(match_block
|
||||
(match_conditional_expression
|
||||
(match_condition_list
|
||||
(class_constant_access_expression (name) (name))
|
||||
(class_constant_access_expression (name) (name))
|
||||
)
|
||||
(string (string_value))
|
||||
)
|
||||
(match_conditional_expression
|
||||
(match_condition_list
|
||||
(class_constant_access_expression (name) (name))
|
||||
(class_constant_access_expression (name) (name))
|
||||
)
|
||||
(string (string_value))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,188 +0,0 @@
|
||||
====================
|
||||
no interpolated text
|
||||
====================
|
||||
|
||||
<?php
|
||||
echo "hi";
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement (encapsed_string (string_value))))
|
||||
|
||||
===============================
|
||||
interpolated text at beginning
|
||||
===============================
|
||||
|
||||
<div>
|
||||
<?php
|
||||
echo "hi";
|
||||
---
|
||||
|
||||
(program
|
||||
(text)
|
||||
(php_tag)
|
||||
(echo_statement (encapsed_string (string_value))))
|
||||
|
||||
===============================
|
||||
interpolated text at end
|
||||
===============================
|
||||
|
||||
<?php
|
||||
echo "hi";
|
||||
?>
|
||||
|
||||
<div>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement (encapsed_string (string_value)))
|
||||
(text_interpolation (text)))
|
||||
|
||||
===============================
|
||||
interpolated text in middle
|
||||
===============================
|
||||
|
||||
<?php
|
||||
echo "hi";
|
||||
?>
|
||||
|
||||
<div>
|
||||
|
||||
<?php
|
||||
echo "bye";
|
||||
?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement (encapsed_string (string_value)))
|
||||
(text_interpolation
|
||||
(text)
|
||||
(php_tag))
|
||||
(echo_statement (encapsed_string (string_value)))
|
||||
(text_interpolation))
|
||||
|
||||
==============================
|
||||
short open tag: On
|
||||
==============================
|
||||
|
||||
<?
|
||||
echo "Used a short tag\n";
|
||||
?>
|
||||
Finished
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement (encapsed_string (string_value) (escape_sequence)))
|
||||
(text_interpolation (text)))
|
||||
|
||||
==============================
|
||||
short open tag: Off
|
||||
==============================
|
||||
|
||||
<div>one</div>
|
||||
|
||||
<?php
|
||||
$a = 'This gets echoed twice';
|
||||
?>
|
||||
|
||||
<?= $a ?>
|
||||
|
||||
<div>two</div>
|
||||
|
||||
<? $b=3; ?>
|
||||
|
||||
<?php
|
||||
echo "{$b}";
|
||||
?>
|
||||
|
||||
<?= "{$b}" ?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(text)
|
||||
(php_tag)
|
||||
(expression_statement (assignment_expression (variable_name (name)) (string (string_value))))
|
||||
(text_interpolation (php_tag))
|
||||
(expression_statement (variable_name (name)))
|
||||
(text_interpolation (text) (php_tag))
|
||||
(expression_statement (assignment_expression (variable_name (name)) (integer)))
|
||||
(text_interpolation (php_tag))
|
||||
(echo_statement (encapsed_string (variable_name (name))))
|
||||
(text_interpolation (php_tag))
|
||||
(expression_statement (encapsed_string (variable_name (name))))
|
||||
(text_interpolation))
|
||||
|
||||
======================
|
||||
Single line php comment
|
||||
======================
|
||||
|
||||
<ul class="foo"><?php // this is a comment ?></ul>
|
||||
|
||||
<?php
|
||||
// foo?
|
||||
// foo? bar?
|
||||
echo "hi";
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(text)
|
||||
(php_tag)
|
||||
(comment)
|
||||
(text_interpolation (text) (php_tag))
|
||||
(comment)
|
||||
(comment)
|
||||
(echo_statement (encapsed_string (string_value))))
|
||||
|
||||
|
||||
=======================================
|
||||
Singel line comment without any content
|
||||
=======================================
|
||||
|
||||
<?php
|
||||
# Check if PHP xml isn't compiled
|
||||
#
|
||||
if ( ! function_exists('xml_parser_create') ) {
|
||||
echo $test;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(comment)
|
||||
(comment)
|
||||
(if_statement
|
||||
condition: (parenthesized_expression
|
||||
(unary_op_expression
|
||||
(function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments (argument (string (string_value))))
|
||||
)
|
||||
)
|
||||
)
|
||||
body: (compound_statement (echo_statement (variable_name (name))))
|
||||
)
|
||||
)
|
||||
|
||||
=====================================
|
||||
Closing tags before the first PHP tag
|
||||
=====================================
|
||||
|
||||
a ?> b <?php c;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(text)
|
||||
(php_tag)
|
||||
(expression_statement
|
||||
(name)))
|
||||
@ -1,109 +0,0 @@
|
||||
========================
|
||||
Booleans
|
||||
========================
|
||||
|
||||
<?php
|
||||
True;
|
||||
true;
|
||||
TRUE;
|
||||
false;
|
||||
False;
|
||||
FALSE;
|
||||
?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement (boolean))
|
||||
(expression_statement (boolean))
|
||||
(expression_statement (boolean))
|
||||
(expression_statement (boolean))
|
||||
(expression_statement (boolean))
|
||||
(expression_statement (boolean))
|
||||
(text_interpolation))
|
||||
|
||||
==========================
|
||||
Floats
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
1.0;
|
||||
1E432;
|
||||
1.0E-3432;
|
||||
1423.0E3432;
|
||||
.5;
|
||||
6.674_083e11;
|
||||
107_925_284.88;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
(expression_statement (float))
|
||||
)
|
||||
|
||||
==========================
|
||||
Integers
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
1234;
|
||||
1_234_456;
|
||||
0123;
|
||||
0123_456;
|
||||
0x1A;
|
||||
0x1A_2B_3C;
|
||||
0b111111111;
|
||||
0b1111_1111_1111;
|
||||
0o123;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
(expression_statement (integer))
|
||||
)
|
||||
|
||||
============================
|
||||
Testing string scanner confirmance
|
||||
==============================
|
||||
|
||||
<?php echo "\"\t\\'" . '\n\\\'a\\\b\\' ?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement (binary_expression (encapsed_string (escape_sequence) (escape_sequence) (escape_sequence) (string_value)) (string (string_value))))
|
||||
(text_interpolation))
|
||||
|
||||
==========================
|
||||
Shell command
|
||||
==========================
|
||||
<?php
|
||||
`ls -la`;
|
||||
`ls`;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement (shell_command_expression))
|
||||
(expression_statement (shell_command_expression)))
|
||||
@ -1,469 +0,0 @@
|
||||
==============================
|
||||
If statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
if ($a > 0) {
|
||||
echo "Yes";
|
||||
}
|
||||
|
||||
if ($a==0) {
|
||||
echo "bad";
|
||||
} else {
|
||||
echo "good";
|
||||
}
|
||||
|
||||
if ($a==0) {
|
||||
echo "bad";
|
||||
} elseif ($a==3) {
|
||||
echo "bad";
|
||||
} else {
|
||||
echo "good";
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value)))))
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value))))
|
||||
alternative: (else_clause
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value))))))
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value))))
|
||||
alternative: (else_if_clause
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value)))))
|
||||
alternative: (else_clause
|
||||
body: (compound_statement (echo_statement (encapsed_string (string_value)))))))
|
||||
|
||||
==============================
|
||||
Alternative if statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
if ($a) echo 1; else echo 0;
|
||||
if ($a):
|
||||
echo 1;
|
||||
echo 2;
|
||||
else:
|
||||
echo 0;
|
||||
endif;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (echo_statement (integer))
|
||||
alternative: (else_clause
|
||||
body: (echo_statement (integer))))
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (colon_block
|
||||
(echo_statement (integer))
|
||||
(echo_statement (integer)))
|
||||
alternative: (else_clause
|
||||
body: (colon_block
|
||||
(echo_statement (integer))))))
|
||||
|
||||
====================================
|
||||
Wordpress colon blocks
|
||||
====================================
|
||||
|
||||
<?php
|
||||
|
||||
if ($post) :
|
||||
?>
|
||||
<?php
|
||||
|
||||
if ( $open ) {
|
||||
$attachment_id;
|
||||
}
|
||||
|
||||
?>
|
||||
<?php
|
||||
else :
|
||||
$post;
|
||||
|
||||
endif;
|
||||
|
||||
?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (colon_block
|
||||
(text_interpolation (php_tag))
|
||||
(if_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (compound_statement (expression_statement (variable_name (name))))
|
||||
)
|
||||
)
|
||||
(text_interpolation (php_tag))
|
||||
alternative: (else_clause
|
||||
body: (colon_block
|
||||
(expression_statement (variable_name (name)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(text_interpolation)
|
||||
)
|
||||
|
||||
==============================
|
||||
While statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
while ($a < 10) {
|
||||
echo $a;
|
||||
$a++;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(while_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (compound_statement
|
||||
(echo_statement (variable_name (name)))
|
||||
(expression_statement (update_expression (variable_name (name)))))))
|
||||
|
||||
==============================
|
||||
Alternative while statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
while ($a<5) echo $a++;
|
||||
while ($a<9):
|
||||
echo ++$a;
|
||||
echo $b;
|
||||
endwhile;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(while_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (echo_statement (update_expression (variable_name (name)))))
|
||||
(while_statement
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))
|
||||
body: (colon_block
|
||||
(echo_statement (update_expression (variable_name (name))))
|
||||
(echo_statement (variable_name (name))))))
|
||||
|
||||
==============================
|
||||
For statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
for($a=0;$a<5;$a++) echo $a;
|
||||
for($a=0;$a<5;$a++):
|
||||
echo $a;
|
||||
endfor;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(for_statement
|
||||
(assignment_expression (variable_name (name)) (integer))
|
||||
(binary_expression (variable_name (name)) (integer))
|
||||
(update_expression (variable_name (name)))
|
||||
(echo_statement (variable_name (name))))
|
||||
(for_statement
|
||||
(assignment_expression (variable_name (name)) (integer))
|
||||
(binary_expression (variable_name (name)) (integer))
|
||||
(update_expression (variable_name (name)))
|
||||
(echo_statement (variable_name (name)))))
|
||||
|
||||
==============================
|
||||
Switch statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
switch ($a) {
|
||||
case 0:
|
||||
echo "bad";
|
||||
break;
|
||||
case 1:
|
||||
echo "good";
|
||||
break;
|
||||
default:
|
||||
echo "bad";
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(switch_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (switch_block
|
||||
(case_statement
|
||||
value: (integer)
|
||||
(echo_statement (encapsed_string (string_value))) (break_statement))
|
||||
(case_statement
|
||||
value: (integer)
|
||||
(echo_statement (encapsed_string (string_value))) (break_statement))
|
||||
(default_statement
|
||||
(echo_statement (encapsed_string (string_value))) (break_statement))))
|
||||
(text_interpolation))
|
||||
|
||||
==============================
|
||||
Alternative switch statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
switch ($a):
|
||||
case 0;
|
||||
echo 0;
|
||||
break;
|
||||
case 5:
|
||||
echo 1;
|
||||
break;
|
||||
default;
|
||||
echo 0;
|
||||
break;
|
||||
endswitch;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(switch_statement
|
||||
condition: (parenthesized_expression (variable_name (name)))
|
||||
body: (switch_block
|
||||
(case_statement
|
||||
value: (integer)
|
||||
(echo_statement (integer))
|
||||
(break_statement))
|
||||
(case_statement
|
||||
value: (integer)
|
||||
(echo_statement (integer))
|
||||
(break_statement))
|
||||
(default_statement
|
||||
(echo_statement (integer))
|
||||
(break_statement)))))
|
||||
|
||||
==============================
|
||||
Include statement
|
||||
==============================
|
||||
|
||||
<?php
|
||||
include "015.inc";
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(expression_statement (include_expression (encapsed_string (string_value)))))
|
||||
|
||||
==============================
|
||||
Do-while statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
do {
|
||||
echo $i;
|
||||
$i--;
|
||||
} while($i>0);
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(do_statement
|
||||
body: (compound_statement
|
||||
(echo_statement (variable_name (name)))
|
||||
(expression_statement (update_expression (variable_name (name)))))
|
||||
condition: (parenthesized_expression (binary_expression
|
||||
left: (variable_name (name))
|
||||
right: (integer)))))
|
||||
|
||||
==============================
|
||||
Try statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
|
||||
try {
|
||||
} catch (MyException) {
|
||||
} catch (OtherException|YetAnotherException $e) {
|
||||
} finally {
|
||||
}
|
||||
|
||||
try {
|
||||
ThrowException();
|
||||
} catch (MyException $exception) {
|
||||
print "There was an exception: " . $exception->getException();
|
||||
print "\n";
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(try_statement
|
||||
body: (compound_statement)
|
||||
(catch_clause
|
||||
type: (type_list
|
||||
(named_type (name))
|
||||
)
|
||||
body: (compound_statement))
|
||||
(catch_clause
|
||||
type: (type_list
|
||||
(named_type (name))
|
||||
(named_type (name))
|
||||
)
|
||||
name: (variable_name (name))
|
||||
body: (compound_statement))
|
||||
(finally_clause
|
||||
body: (compound_statement)))
|
||||
(try_statement
|
||||
body: (compound_statement
|
||||
(expression_statement (function_call_expression
|
||||
function: (name)
|
||||
arguments: (arguments))))
|
||||
(catch_clause
|
||||
type: (type_list
|
||||
(named_type (name))
|
||||
)
|
||||
name: (variable_name (name))
|
||||
body: (compound_statement
|
||||
(expression_statement (print_intrinsic (binary_expression
|
||||
left: (encapsed_string (string_value))
|
||||
right: (member_call_expression
|
||||
object: (variable_name (name))
|
||||
name: (name)
|
||||
arguments: (arguments)))))
|
||||
(expression_statement (print_intrinsic (encapsed_string (escape_sequence))))))))
|
||||
|
||||
==============================
|
||||
Foreach statements
|
||||
==============================
|
||||
|
||||
<?php
|
||||
foreach ($a as $b[0]) {
|
||||
echo $b[0]."\n";
|
||||
}
|
||||
|
||||
foreach($arr as $key => $value);
|
||||
|
||||
foreach($a as $b):
|
||||
echo $a;
|
||||
echo $b;
|
||||
endforeach;
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(foreach_statement
|
||||
(variable_name (name))
|
||||
(subscript_expression (variable_name (name)) (integer))
|
||||
body: (compound_statement
|
||||
(echo_statement (binary_expression
|
||||
left: (subscript_expression (variable_name (name)) (integer))
|
||||
right: (encapsed_string (escape_sequence))))))
|
||||
(foreach_statement
|
||||
(variable_name (name))
|
||||
(pair (variable_name (name)) (variable_name (name))))
|
||||
(foreach_statement
|
||||
(variable_name (name))
|
||||
(variable_name (name))
|
||||
body: (colon_block
|
||||
(echo_statement (variable_name (name)))
|
||||
(echo_statement (variable_name (name))))))
|
||||
|
||||
=================================
|
||||
Case insensitive keywords
|
||||
=================================
|
||||
|
||||
<?php
|
||||
|
||||
FOREACH ($a AS $b) {
|
||||
DO {
|
||||
if ($c) {
|
||||
d();
|
||||
} else {
|
||||
e();
|
||||
}
|
||||
} while ($f);
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(foreach_statement
|
||||
(variable_name (name))
|
||||
(variable_name (name))
|
||||
(compound_statement
|
||||
(do_statement
|
||||
(compound_statement
|
||||
(if_statement
|
||||
(parenthesized_expression (variable_name (name)))
|
||||
(compound_statement
|
||||
(expression_statement (function_call_expression (name) (arguments))))
|
||||
(else_clause
|
||||
(compound_statement
|
||||
(expression_statement (function_call_expression (name) (arguments)))))))
|
||||
(parenthesized_expression (variable_name (name)))))))
|
||||
|
||||
|
||||
=========================================
|
||||
Accessing Constants
|
||||
=========================================
|
||||
|
||||
<?php
|
||||
|
||||
echo ANOTHER_CONST;
|
||||
echo ANIMALS[1];
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(echo_statement
|
||||
(name)
|
||||
)
|
||||
(echo_statement
|
||||
(subscript_expression
|
||||
(name)
|
||||
(integer)
|
||||
)
|
||||
)
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,171 +0,0 @@
|
||||
=========================
|
||||
Type names
|
||||
=========================
|
||||
|
||||
<?php
|
||||
function a(): A {}
|
||||
function b(): A\B {}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type (named_type (name)))
|
||||
(compound_statement))
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type
|
||||
(named_type (qualified_name (namespace_name_as_prefix (namespace_name (name))) (name)))
|
||||
)
|
||||
(compound_statement)))
|
||||
|
||||
=========================
|
||||
Primitive types
|
||||
=========================
|
||||
|
||||
<?php
|
||||
function a(): int {}
|
||||
function b(): callable {}
|
||||
function c(): iterable {}
|
||||
function d(): never {}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement))
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement))
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement))
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(bottom_type)
|
||||
(compound_statement)))
|
||||
|
||||
=======================
|
||||
Optional types
|
||||
=======================
|
||||
|
||||
<?php
|
||||
|
||||
function a(): ?array {}
|
||||
function b(): ?Something {}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type
|
||||
(optional_type (primitive_type))
|
||||
)
|
||||
(compound_statement))
|
||||
(function_definition
|
||||
(name) (formal_parameters)
|
||||
(union_type
|
||||
(optional_type (named_type (name)))
|
||||
)
|
||||
(compound_statement)))
|
||||
|
||||
|
||||
==========================
|
||||
Union types
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
function a(int|string|null $var) : ?int|MyClass {}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
name: (name)
|
||||
parameters: (formal_parameters
|
||||
(simple_parameter
|
||||
type: (union_type
|
||||
(primitive_type)
|
||||
(primitive_type)
|
||||
(primitive_type)
|
||||
)
|
||||
name: (variable_name (name))
|
||||
)
|
||||
)
|
||||
return_type: (union_type
|
||||
(optional_type
|
||||
(primitive_type)
|
||||
)
|
||||
(named_type (name))
|
||||
)
|
||||
body: (compound_statement)
|
||||
)
|
||||
)
|
||||
|
||||
==========================
|
||||
Mixed type
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
function a(mixed|string $var) : mixed {
|
||||
|
||||
}
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name)
|
||||
(formal_parameters
|
||||
(simple_parameter
|
||||
(union_type
|
||||
(primitive_type)
|
||||
(primitive_type)
|
||||
)
|
||||
(variable_name (name))
|
||||
)
|
||||
)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement)
|
||||
)
|
||||
)
|
||||
|
||||
==========================
|
||||
Static type
|
||||
==========================
|
||||
|
||||
<?php
|
||||
|
||||
function a(string $var) : static {
|
||||
|
||||
}
|
||||
---
|
||||
|
||||
(program
|
||||
(php_tag)
|
||||
(function_definition
|
||||
(name)
|
||||
(formal_parameters
|
||||
(simple_parameter
|
||||
(union_type
|
||||
(primitive_type)
|
||||
)
|
||||
(variable_name (name))
|
||||
)
|
||||
)
|
||||
(union_type (primitive_type))
|
||||
(compound_statement)
|
||||
)
|
||||
)
|
||||
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
// <- tag
|
||||
|
||||
if ($a) {}
|
||||
// <- keyword
|
||||
|
||||
while ($b) {}
|
||||
// <- keyword
|
||||
|
||||
WHILE ($b) {}
|
||||
// <- keyword
|
||||
|
||||
do { } while ($c);
|
||||
// <- keyword
|
||||
// ^ keyword
|
||||
|
||||
try {} catch (Exception $e) {}
|
||||
// <- keyword
|
||||
// ^ keyword
|
||||
|
||||
function a() {}
|
||||
// <- keyword
|
||||
|
||||
class A {}
|
||||
// <- keyword
|
||||
|
||||
throw new Exception("oh");
|
||||
// <- keyword
|
||||
// ^ keyword
|
||||
|
||||
function b(
|
||||
int $a,
|
||||
// <- type.builtin
|
||||
|
||||
string $b,
|
||||
// <- type.builtin
|
||||
|
||||
Person $e
|
||||
// ^ type
|
||||
): Dog {}
|
||||
// ^ type
|
||||
|
||||
interface T {}
|
||||
// ^ keyword
|
||||
|
||||
trait T {}
|
||||
// ^ keyword
|
||||
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
echo <<<OMG
|
||||
something
|
||||
OMG
|
||||
// <- string
|
||||
|
||||
echo true, TRUE, false, FALSE
|
||||
// ^ constant.builtin
|
||||
// ^ constant.builtin
|
||||
// ^ constant.builtin
|
||||
// ^ constant.builtin
|
||||
|
||||
echo PI_314
|
||||
// ^ constant
|
||||
@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
function a(array $b, Something $c) {
|
||||
// ^ type.builtin
|
||||
// ^ type
|
||||
echo (int) $foo;
|
||||
// ^ type.builtin
|
||||
}
|
||||
Loading…
Reference in New Issue