Skip to content

Commit 1a1ced6

Browse files
philipc-mwPrabhakar Kumar
authored andcommitted
Fixes multiple issues with the Jupyter LabExtension for MATLAB.
* Fixing bug where chained transposes would be highlighted incorrectly, by swapping ? (zero or one) with * (any number). Also adding test for same bug. * Fixing bug with building on some Windows systems. In the Lezer build, we need to copy some files, but only on Windows - we attempt to copy, but fall back to || true on Linux, which does nothing but does not fail the build. * In comment parsing, using a regex to match whitespace, instead of just matching tabs and spaces. * Adding highlighting for system commands, choosing meta as the most appropriate tag: "Metadata or meta-instruction." * Adding tests for parsing system commands.
1 parent d6be9b6 commit 1a1ced6

File tree

10 files changed

+53
-29
lines changed

10 files changed

+53
-29
lines changed

.github/workflows/run-unit-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
# Reusable workflow
77
# Trigger on workflow call
88
workflow_call:
9+
workflow_dispatch:
910

1011
jobs:
1112
matlab_unit_tests:

src/jupyter_matlab_labextension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"build:labextension": "jupyter labextension build .",
3030
"build:labextension:dev": "jupyter labextension build --development True .",
3131
"build:lib": "jlpm build:lezer && tsc",
32-
"build:lezer": "cd src/lezer-matlab && npm run build",
32+
"build:lezer": "cd src/lezer-matlab && npm install",
3333
"clean": "jlpm clean:lib",
3434
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
3535
"clean:lintcache": "rimraf .eslintcache .stylelintcache",

src/jupyter_matlab_labextension/src/lezer-matlab/package.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
{
32
"name": "@lezer/matlab",
43
"version": "1.0.0",
@@ -18,19 +17,19 @@
1817
"license": "SEE LICENSE IN LICENSE.md",
1918
"devDependencies": {
2019
"@lezer/generator": "^1.0.0",
20+
"@rollup/plugin-node-resolve": "^9.0.0",
2121
"mocha": "^10.2.0",
22-
"rollup": "^2.52.2",
23-
"@rollup/plugin-node-resolve": "^9.0.0"
22+
"rollup": "^2.52.2"
2423
},
2524
"dependencies": {
2625
"@lezer/common": "^1.2.0",
27-
"@lezer/lr": "^1.0.0",
28-
"@lezer/highlight": "^1.0.0"
26+
"@lezer/highlight": "^1.0.0",
27+
"@lezer/lr": "^1.0.0"
2928
},
3029
"scripts": {
3130
"build": "lezer-generator src/matlab.grammar -o src/parser && rollup -c && npm run copy-lezer-files-to-build-on-windows",
3231
"build-debug": "lezer-generator src/matlab.grammar --names -o src/parser && rollup -c && npm run copy-lezer-files-to-build-on-windows",
33-
"copy-lezer-files-to-build-on-windows": "cp src/*.js dist/",
32+
"copy-lezer-files-to-build-on-windows": "copy src\\*.js dist\\ || true",
3433
"prepare": "npm run build",
3534
"test": "mocha test/test-*.js"
3635
}

src/jupyter_matlab_labextension/src/lezer-matlab/src/highlight.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import { styleTags, tags as t } from '@lezer/highlight';
66
// https://lezer.codemirror.net/docs/ref/#highlight.styleTags
77
export const matlabHighlighting = styleTags({
88
Keyword: t.keyword,
9-
VariableName: t.variableName,
9+
Identifier: t.variableName,
1010
LineComment: t.comment,
1111
MultilineComment: t.comment,
12+
SystemCommand: t.meta,
1213
String: t.string,
1314
'( )': t.paren,
1415
'[ ]': t.squareBracket,

src/jupyter_matlab_labextension/src/lezer-matlab/src/matlab.grammar

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
@top Script { expression* }
44

55
expression {
6-
VariableName |
6+
Identifier |
77
String |
88
MultilineComment |
99
keyword |
@@ -14,26 +14,26 @@ expression {
1414
// See https://lezer.codemirror.net/docs/guide/ for documentation on syntax
1515
// specific to @tokens blocks, and how it differs from regular expression syntax.
1616
@tokens {
17-
VariableName { $[a-zA-Z0-9_]+ $[a-zA-Z0-9_']? }
17+
Identifier { $[a-zA-Z0-9_]+ $[a-zA-Z0-9_']* }
1818
charVector { '"' (!["\n])* '"' }
1919
stringArray { "'" (!['\n])* "'" }
2020
SystemCommand { "!" (![\n])* }
2121
Symbol { "+" | "-" | "*" | "=" | ";" | ":" | "(" | ")" | "{" | "}" | "[" | "]" }
2222
space { @whitespace+ }
23-
@precedence { SystemCommand, VariableName }
23+
@precedence { SystemCommand, Identifier }
2424
@precedence { SystemCommand, space }
25-
@precedence { VariableName, charVector }
26-
@precedence { VariableName, stringArray }
25+
@precedence { Identifier, charVector }
26+
@precedence { Identifier, stringArray }
2727
}
2828

2929
String { charVector | stringArray }
3030

31-
// Once a string has been parsed and found to be a VariableName, it will then
31+
// Once a string has been parsed and found to be a Identifier, it will then
3232
// be tested against its specialize table, to test if it is a keyword.
3333
// The keyword node name is "Keyword".
3434
// https://lezer.codemirror.net/docs/guide/#token-specialization
3535
keyword {
36-
@specialize[@name=Keyword]<VariableName, "break" | "case" | "classdef" | "continue" | "global" | "otherwise" | "persistent" | "return" | "spmd" | "arguments" | "enumeration" | "events" | "for" | "function" | "if" | "methods" | "parfor" | "properties" | "try" | "while" | "elseif" | "else" | "end" | "switch" | "catch">
36+
@specialize[@name=Keyword]<Identifier, "break" | "case" | "classdef" | "continue" | "global" | "otherwise" | "persistent" | "return" | "spmd" | "arguments" | "enumeration" | "events" | "for" | "function" | "if" | "methods" | "parfor" | "properties" | "try" | "while" | "elseif" | "else" | "end" | "switch" | "catch">
3737
}
3838

3939
@skip { space | LineComment }

src/jupyter_matlab_labextension/src/lezer-matlab/src/parse_comments.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,19 @@ const fileStart = -1;
1111
const fileEnd = -1;
1212
const newline = '\n'.charCodeAt(0);
1313
const carriageReturn = '\r'.charCodeAt(0);
14-
const space = ' '.charCodeAt(0);
15-
const tab = '\t'.charCodeAt(0);
1614

17-
const whitespaceArray = [tab, space];
1815
const lineEndArray = [newline, carriageReturn, fileEnd, fileStart];
1916

17+
const isWhitespace = (char) => /\s/.test(char);
18+
2019
const precededByWhitespaceOnly = (input) => {
2120
// Scan from current position to start of line.
2221
// Return False if non-whitespace found.
2322
// Always return input back to where it started.
2423
const startPos = input.pos;
2524
let onlyWhitespace = true;
2625
while (!lineEndArray.includes(input.peek(-1))) {
27-
if (whitespaceArray.includes(input.peek(-1))) {
26+
if (isWhitespace(input.peek(-1))) {
2827
input.advance(-1);
2928
} else {
3029
onlyWhitespace = false;
@@ -42,7 +41,7 @@ const followedByWhitespaceOnly = (input) => {
4241
const startPos = input.pos;
4342
let onlyWhitespace = true;
4443
while (!lineEndArray.includes(input.peek(0))) {
45-
if (whitespaceArray.includes(input.peek(0))) {
44+
if (isWhitespace(input.peek(0))) {
4645
input.advance(1);
4746
} else {
4847
onlyWhitespace = false;

src/jupyter_matlab_labextension/src/lezer-matlab/test/additional_cases.txt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,36 @@ ver %{ Invalid as preceded by non-whitespace.
2323

2424
==>
2525

26-
Script(LineComment,String,LineComment,String,VariableName,LineComment,String,MultilineComment)
26+
Script(LineComment,String,LineComment,String,Identifier,LineComment,String,MultilineComment)
2727

2828
# Transpose is not a string delimiter
2929

3030
A1' + A2' + B1
3131

3232
==>
3333

34-
Script(VariableName,Symbol,VariableName,Symbol,VariableName)
34+
Script(Identifier,Symbol,Identifier,Symbol,Identifier)
3535

3636
# Character vectors can be preceded by non whitespace
3737

3838
A1" + A2" + B1
3939

4040
==>
4141

42-
Script(VariableName,String,Symbol,VariableName)
42+
Script(Identifier,String,Symbol,Identifier)
43+
44+
# Transposed transpose
45+
46+
A'' + B'
47+
48+
==>
49+
50+
Script(Identifier,Symbol,Identifier)
51+
52+
# System command with no preceding whitespace
53+
54+
test!test
55+
56+
==>
57+
58+
Script(Identifier,SystemCommand)

src/jupyter_matlab_labextension/src/lezer-matlab/test/basic_terms.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,20 @@ A1'
5454

5555
==>
5656

57-
Script(VariableName)
57+
Script(Identifier)
5858

5959
# Symbol
6060

6161
A + B
6262

6363
==>
6464

65-
Script(VariableName,Symbol,VariableName)
65+
Script(Identifier,Symbol,Identifier)
66+
67+
# System command
68+
69+
test ! echo "Test system command"
70+
71+
==>
72+
73+
Script(Identifier,SystemCommand)

src/jupyter_matlab_labextension/src/lezer-matlab/test/nested_terms.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Keyword in VariableName
1+
# Keyword in Identifier
22

33
forest
44

55
==>
66

7-
Script(VariableName)
7+
Script(Identifier)
88

99
# String in comment
1010

src/jupyter_matlab_labextension/src/lezer-matlab/test/test-long-matlab-files.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import {fileTests} from "@lezer/generator/dist/test"
55

66
let N = 10000
77

8-
let long_file_spec = `Script(${"Keyword,VariableName,Symbol,VariableName,Symbol,VariableName,VariableName,Symbol,VariableName,Symbol,Symbol,Keyword,".repeat(N)}LineComment)`
8+
let long_file_spec = `Script(${"Keyword,Identifier,Symbol,Identifier,Symbol,Identifier,Identifier,Symbol,Identifier,Symbol,Symbol,Keyword,".repeat(N)}LineComment)`
99
let long_file_input = `
1010
${"for c = 1:100\n\tdisp(c);\nend\n".repeat(N)}
1111
% Long file
1212
`
1313

14-
let long_line_spec = `Script(${"Keyword,VariableName,Symbol,VariableName,Symbol,VariableName,Symbol,VariableName,Symbol,VariableName,Symbol,Symbol,Keyword,Symbol,".repeat(N)}LineComment)`
14+
let long_line_spec = `Script(${"Keyword,Identifier,Symbol,Identifier,Symbol,Identifier,Symbol,Identifier,Symbol,Identifier,Symbol,Symbol,Keyword,Symbol,".repeat(N)}LineComment)`
1515
let long_line_input = `
1616
${"for c = 1:100;\tdisp(c);end;".repeat(N)}
1717
% Long line

0 commit comments

Comments
 (0)