Skip to content

Commit

Permalink
chore: tidy up grammar and scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
amaanq committed Nov 18, 2023
1 parent f9bd96b commit 0c87399
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 94 deletions.
93 changes: 67 additions & 26 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,15 @@ module.exports = grammar({
)),
),

php_tag: $ => /<\?([pP][hH][pP]|=)?/,
php_tag: _ => /<\?([pP][hH][pP]|=)?/,

text_interpolation: $ => seq(
'?>',
optional($.text),
choice($.php_tag, $._eof),
),

text: $ => repeat1(choice(
text: _ => repeat1(choice(
token(prec(-1, /</)),
/[^\s<][^<]*/,
)),
Expand Down Expand Up @@ -160,9 +160,9 @@ module.exports = grammar({
$.function_static_declaration,
),

empty_statement: $ => prec(-1, ';'),
empty_statement: _ => prec(-1, ';'),

reference_modifier: $ => token('&'),
reference_modifier: _ => '&',

function_static_declaration: $ => seq(
keyword('static'),
Expand Down Expand Up @@ -315,9 +315,9 @@ module.exports = grammar({
'}',
),

final_modifier: $ => keyword('final'),
abstract_modifier: $ => keyword('abstract'),
readonly_modifier: $ => keyword('readonly'),
final_modifier: _ => keyword('final'),
abstract_modifier: _ => keyword('abstract'),
readonly_modifier: _ => keyword('readonly'),

class_interface_clause: $ => seq(
keyword('implements'),
Expand Down Expand Up @@ -381,8 +381,8 @@ module.exports = grammar({
),
),

var_modifier: $ => keyword('var', false),
static_modifier: $ => keyword('static'),
var_modifier: _ => keyword('var', false),
static_modifier: _ => keyword('static'),

use_declaration: $ => seq(
keyword('use'),
Expand Down Expand Up @@ -423,7 +423,7 @@ module.exports = grammar({
),
),

visibility_modifier: $ => choice(
visibility_modifier: _ => choice(
keyword('public'),
keyword('protected'),
keyword('private'),
Expand Down Expand Up @@ -514,13 +514,13 @@ module.exports = grammar({
),
),

bottom_type: $ => 'never',
bottom_type: _ => 'never',

union_type: $ => prec.right(pipeSep1($._types)),

intersection_type: $ => ampSep1($._types),

primitive_type: $ => choice(
primitive_type: _ => choice(
'array',
keyword('callable'), // not legal in property types
'iterable',
Expand All @@ -536,7 +536,7 @@ module.exports = grammar({
'true',
),

cast_type: $ => choice(
cast_type: _ => choice(
keyword('array', false),
keyword('binary', false),
keyword('bool', false),
Expand Down Expand Up @@ -587,7 +587,7 @@ module.exports = grammar({
$.null,
),

float: $ => /\d*(_\d+)*((\.\d*(_\d+)*)?([eE][\+-]?\d+(_\d+)*)|(\.\d*(_\d+)*)([eE][\+-]?\d+(_\d+)*)?)/,
float: _ => /\d*(_\d+)*((\.\d*(_\d+)*)?([eE][\+-]?\d+(_\d+)*)|(\.\d*(_\d+)*)([eE][\+-]?\d+(_\d+)*)?)/,

try_statement: $ => seq(
keyword('try'),
Expand Down Expand Up @@ -623,7 +623,7 @@ module.exports = grammar({
keyword('break'), optional($._expression), $._semicolon,
),

integer: $ => {
integer: _ => {
const decimal = /[1-9]\d*(_\d+)*/;
const octal = /0[oO]?[0-7]*(_[0-7]+)*/;
const hex = /0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*/;
Expand Down Expand Up @@ -1098,8 +1098,6 @@ module.exports = grammar({
$._string,
),

parenthesized_expression: $ => seq('(', $._expression, ')'),

scoped_call_expression: $ => prec(PREC.CALL, seq(
field('scope', $._scope_resolution_qualifier),
'::',
Expand All @@ -1115,13 +1113,13 @@ module.exports = grammar({
$._dereferencable_expression,
),

relative_scope: $ => prec(PREC.SCOPE, choice(
relative_scope: _ => prec(PREC.SCOPE, choice(
'self',
'parent',
keyword('static'),
)),

variadic_placeholder: $ => token('...'),
variadic_placeholder: _ => '...',

arguments: $ => seq(
'(',
Expand Down Expand Up @@ -1242,7 +1240,7 @@ module.exports = grammar({

// Note: remember to also update the is_escapable_sequence method in the
// external scanner whenever changing these rules
escape_sequence: $ => token.immediate(seq(
escape_sequence: _ => token.immediate(seq(
'\\',
choice(
'n',
Expand Down Expand Up @@ -1332,7 +1330,8 @@ module.exports = grammar({
),
),

_new_line: $ => choice(token(/\r?\n/), token(/\r/)),
// _new_line: _ => choice(token(/\r?\n/), token(/\r/)),
_new_line: _ => /\r?\n|\r/,

nowdoc_body: $ => seq($._new_line,
choice(
Expand Down Expand Up @@ -1378,9 +1377,9 @@ module.exports = grammar({
'`',
),

boolean: $ => /[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]/,
boolean: _ => /true|false/i,

null: $ => keyword('null', false),
null: _ => keyword('null', false),

_string: $ => choice($.encapsed_string, $.string, $.heredoc, $.nowdoc),

Expand Down Expand Up @@ -1455,8 +1454,10 @@ module.exports = grammar({
['*', PREC.TIMES],
['/', PREC.TIMES],
['%', PREC.TIMES],
// @ts-ignore
].map(([op, p]) => prec.left(p, seq(
field('left', $._expression),
// @ts-ignore
field('operator', op),
field('right', $._expression),
))),
Expand All @@ -1482,15 +1483,15 @@ module.exports = grammar({
$._expression,
),

name: $ => /[_a-zA-Z\u00A1-\u00ff][_a-zA-Z\u00A1-\u00ff\d]*/,
name: _ => /[_a-zA-Z\u00A1-\u00ff][_a-zA-Z\u00A1-\u00ff\d]*/,

_reserved_identifier: $ => choice(
_reserved_identifier: _ => choice(
'self',
'parent',
keyword('static'),
),

comment: $ => token(choice(
comment: _ => token(choice(
seq(
choice('//', /#[^?\[?\r?\n]/),
repeat(/[^?\r?\n]|\?[^>\r\n]/),
Expand All @@ -1508,24 +1509,64 @@ module.exports = grammar({
},
});

/**
* Creates a regex that matches the given word case-insensitively,
* and will alias the regex to the word if aliasAsWord is true
*
* @param {string} word
* @param {boolean} aliasAsWord?
*
* @return {RegExp|AliasRule}
*/
function keyword(word, aliasAsWord = true) {
/** @type {RegExp|AliasRule} */
let result = new RegExp(word, 'i');
if (aliasAsWord) result = alias(result, word);
return result;
}

/**
* Creates a rule to match one or more of the rules separated by a comma
*
* @param {Rule} rule
*
* @return {SeqRule}
*
*/
function commaSep1(rule) {
return seq(rule, repeat(seq(',', rule)));
}

/**
* Creates a rule to optionally match one or more of the rules separated by a comma
*
* @param {Rule} rule
*
* @return {ChoiceRule}
*
*/
function commaSep(rule) {
return optional(commaSep1(rule));
}

/**
* Creates a rule to match one or more of the rules separated by a pipe
*
* @param {Rule} rule
*
* @return {SeqRule}
*/
function pipeSep1(rule) {
return seq(rule, repeat(seq('|', rule)));
}

/**
* Creates a rule to match one or more of the rules separated by an ampersand
*
* @param {Rule} rule
*
* @return {SeqRule}
*/
function ampSep1(rule) {
return seq(rule, repeat(seq(token('&'), rule)));
}
60 changes: 34 additions & 26 deletions script/parse-examples
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
#!/bin/bash
#!/usr/bin/env bash

set -e
set -eu

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
function clone_repo {
owner=$1
name=$2
sha=$3

path=examples/$name
if [ ! -d "$path" ]; then
echo "Cloning $owner/$name"
git clone "https://github.com/$owner/$name" "$path"
fi

pushd "$path" >/dev/null
actual_sha=$(git rev-parse HEAD)
if [ "$actual_sha" != "$sha" ]; then
echo "Updating $owner/$name to $sha"
git fetch
git reset --hard "$sha"
fi
popd >/dev/null
}

checkout_at "laravel" "laravel/laravel" "9d0862b3340c8243ee072afc181e315ffa35e110"
checkout_at "phabricator" "phacility/phabricator" "d0b01a41f2498fb2a6487c2d6704dc7acfd4675f"
checkout_at "phpunit" "sebastianbergmann/phpunit" "5e523bdc7dd4d90fed9fb29d1df05347b3e7eaba"
checkout_at "WordPress" "WordPress/WordPress" "45286c5bb3f6fe5005567903ec858d87077eae2c"
clone_repo laravel laravel 9d0862b3340c8243ee072afc181e315ffa35e110
clone_repo phacility phabricator d0b01a41f2498fb2a6487c2d6704dc7acfd4675f
clone_repo sebastianbergmann phpunit 5e523bdc7dd4d90fed9fb29d1df05347b3e7eaba
clone_repo WordPress WordPress 45286c5bb3f6fe5005567903ec858d87077eae2c

known_failures="$(cat script/known-failures.txt)"
known_failures=$(cat script/known-failures.txt)

# shellcheck disable=2046
tree-sitter parse -q \
'examples/**/*.php' \
$(for file in $known_failures; do echo "!${file}"; done)
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}")
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
"Successfully parsed %d of %d example files (%.1f%%)\n" \
"$success_count" "$example_count" "$success_percent"
Loading

0 comments on commit 0c87399

Please sign in to comment.