2 stable releases
new 4.0.1 | Nov 11, 2024 |
---|---|
4.0.0 | Nov 9, 2024 |
#73 in Text editors
134 downloads per month
3MB
116K
SLoC
tree-sitter-t32
Lauterbach TRACE32® script language grammar for tree-sitter. Support for HLL expressions was adapted from tree-sitter-c.
A demo is available here.
Features
- Full coverage of the PRACTICE script language including TRACE32® commands & functions
- Extended support for HLL expressions
Quick Start
Dependencies
- Tree-sitter CLI for generating the parser from the grammar.
- A C compiler
- Make [optional]
- Yarn [optional]
Commands
Generate parser
Create and build the tree-sitter parser for the TRACE32® grammar.
tree-sitter generate
Parse TRACE32® Script
Use tree-sitter to parse a TRACE32® script.
Example:
; --------------------------------------------------------------------------------
; @Title: Beautify an existing PRACTICE script
; @Description:
; Beautifies the script, fixing the CamelCasing and indentation.
; @Keywords: PRACTICE, EDIT.FORMAT, CamelCasing, indent, beautify
; @Author: MOB
; @Copyright: (C) 1989-2020 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Id: beautify.cmm 19661 2022-07-29 15:43:03Z rweiss $
PARAMETERS &script
IF "&script"==""
(
DIALOG.File.open *.cmm
ENTRY %LINE &script
)
IF FILE.EXIST("&script")
(
ECHO %COLOR.GRAY "beautifying: &script"
SETUP.EDITOR.TYPE PowerView ; required for EDIT.FORMAT
PEDIT "&script"
EDIT.FORMAT /Beautify
EDIT.SAVE "&script"
EDIT.CLOSE "&script"
ECHO %COLOR.GREEN "beautified: &script"
)
ELSE
(
ECHO %ERROR "Error: no such file: &script"
)
ENDDO
tree-sitter parse <path>
Prints the syntax tree
(script [0, 0] - [34, 0]
(comment [0, 0] - [1, 0])
(comment [1, 0] - [2, 0])
(comment [2, 0] - [3, 0])
(comment [3, 0] - [4, 0])
(comment [4, 0] - [5, 0])
(comment [5, 0] - [6, 0])
(comment [6, 0] - [7, 0])
(comment [7, 0] - [8, 0])
(comment [8, 0] - [9, 0])
(parameter_declaration [10, 0] - [11, 0]
command: (identifier [10, 0] - [10, 10])
macro: (macro [10, 11] - [10, 18]))
(if_block [12, 0] - [18, 0]
command: (identifier [12, 0] - [12, 2])
condition: (binary_expression [12, 3] - [12, 16]
left: (string [12, 3] - [12, 12]
(macro [12, 4] - [12, 11]))
right: (string [12, 14] - [12, 16]))
(block [13, 0] - [17, 0]
(command_expression [14, 2] - [15, 0]
command: (identifier [14, 2] - [14, 18])
arguments: (argument_list [14, 18] - [14, 24]
(path [14, 19] - [14, 24])))
(parameter_declaration [15, 2] - [16, 0]
command: (identifier [15, 2] - [15, 7])
(identifier [15, 8] - [15, 13])
macro: (macro [15, 14] - [15, 21]))))
(if_block [18, 0] - [32, 0]
command: (identifier [18, 0] - [18, 2])
condition: (call_expression [18, 3] - [18, 24]
function: (identifier [18, 3] - [18, 13])
arguments: (argument_list [18, 13] - [18, 24]
(string [18, 14] - [18, 23]
(macro [18, 15] - [18, 22]))))
(block [19, 0] - [28, 0]
(command_expression [20, 2] - [21, 0]
command: (identifier [20, 2] - [20, 6])
arguments: (argument_list [20, 6] - [20, 41]
(format_expression [20, 7] - [20, 18]
value: (identifier [20, 8] - [20, 13])
value: (identifier [20, 14] - [20, 18]))
(string [20, 19] - [20, 41]
(macro [20, 33] - [20, 40]))))
(command_expression [21, 2] - [22, 0]
command: (identifier [21, 2] - [21, 19])
arguments: (argument_list [21, 19] - [21, 29]
(identifier [21, 20] - [21, 29]))
(comment [21, 29] - [22, 0]))
(command_expression [22, 2] - [23, 0]
command: (identifier [22, 2] - [22, 7])
arguments: (argument_list [22, 7] - [22, 17]
(string [22, 8] - [22, 17]
(macro [22, 9] - [22, 16]))))
(command_expression [23, 2] - [24, 0]
command: (identifier [23, 2] - [23, 13])
arguments: (argument_list [23, 13] - [23, 23]
(option_expression [23, 14] - [23, 23]
option: (identifier [23, 15] - [23, 23]))))
(command_expression [24, 2] - [25, 0]
command: (identifier [24, 2] - [24, 11])
arguments: (argument_list [24, 11] - [24, 21]
(string [24, 12] - [24, 21]
(macro [24, 13] - [24, 20]))))
(command_expression [25, 2] - [26, 0]
command: (identifier [25, 2] - [25, 12])
arguments: (argument_list [25, 12] - [25, 22]
(string [25, 13] - [25, 22]
(macro [25, 14] - [25, 21]))))
(command_expression [26, 2] - [27, 0]
command: (identifier [26, 2] - [26, 6])
arguments: (argument_list [26, 6] - [26, 41]
(format_expression [26, 7] - [26, 19]
value: (identifier [26, 8] - [26, 13])
value: (identifier [26, 14] - [26, 19]))
(string [26, 20] - [26, 41]
(macro [26, 33] - [26, 40])))))
(else_block [28, 0] - [32, 0]
command: (identifier [28, 0] - [28, 4])
(block [29, 0] - [32, 0]
(command_expression [30, 2] - [31, 0]
command: (identifier [30, 2] - [30, 6])
arguments: (argument_list [30, 6] - [30, 44]
(format_expression [30, 7] - [30, 13]
value: (identifier [30, 8] - [30, 13]))
(string [30, 14] - [30, 44]
(macro [30, 36] - [30, 43])))))))
(command_expression [33, 0] - [34, 0]
command: (identifier [33, 0] - [33, 5])))
Highlight TRACE32® Script
Use tree-sitter to highlight a TRACE32® script.
tree-sitter highlight <path>
Create Code Navigation Tags
Use tree-sitter to create a tags file from a TRACE32® script.
; --------------------------------------------------------------------------------
; @Title: Example test case for Unittests
; @Description:
; This is an example for a test case which can be executed with lbunit.cmm.
; @Keywords: lbtest test case
; @Author: MOB
; @Copyright: (C) 1989-2015 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Id: test_example.cmm 8648 2015-09-03 17:04:05Z mobermeir $
; the following block must be present in the beginning of every test case
PRIVATE &func &args &result
ENTRY &func %LINE &args
GOSUB &func &args // call subroutine and return result
ENTRY %LINE &result
ENDDO &result
; end of mandatory block
; SetupTestCase will be called once at the beginning of the test case
; It can be removed if it is not needed.
SetupTestCase:
(
PRIVATE &date
&date=DATE.DATE()+" "+DATE.TIME()
PUTS "test case started at: &date"
RETURN
)
; SetupTest will be called just before every test
; It can be removed if it is not needed.
SetupTest:
(
; here can be some setup
Data.Set VM:0x0--0xFF 0xA
RETURN
)
; All tests must start with "Test_"
Test_MyFirstTest:
(
; Assertions can be used:
A_FALSE FALSE()
A_TRUE (1.+1.==2.)
RETURN
)
Test_MySecondTest:
(
A_NUM_EQ 0xA Data.Byte(VM:0x0)
A_X_PASS Data.Set VM:0x0 0xB
A_NUM_EQ 0xB Data.Byte(VM:0x0)
RETURN
)
Test_MyThirdTest:
(
; Tests can return "PASS", "FAIL" or "NOT_EXEC"
; (alternatively or in addition to assertions)
IF (0xA!=Data.Byte(VM:0x0))
(
RETURN "FAIL"
)
ELSE IF (0xB==Data.Byte(VM:0x0))
(
RETURN "NOT_EXEC"
)
ELSE
(
RETURN "PASS"
)
RETURN // same as "PASS"
)
MyHelper:
(
A_NUM_EQ 0xA Data.Byte(VM:0x10)
RETURN
)
Test_MyFourthTest:
(
; tests can call helper functions
RePeaT 2.
(
GOSUB MyHelper
)
RETURN
)
DisabledTest_MyFifthTest:
(
; this routine will not be executed since it doesn't start with "Test_"
RETURN
)
; TearDownTest will be called just after every test
; It can be removed if it is not needed.
TearDownTest:
(
; here could be some cleanup
Break.RESet
RETURN
)
; TearDownTestCase will be called once at the end of the test case
; It can be removed if it is not needed.
TearDownTestCase:
(
PRIVATE &date
&date=DATE.DATE()+" "+DATE.TIME()
PUTS "test case ended at: &date"
RETURN
)
tree-sitter tags <path>
Prints a list of tags
func | call ref (13, 7) - (13, 11) `GOSUB &func &args // call subroutine and return result`
SetupTestCase | function def (20, 0) - (20, 13) `SetupTestCase:`
SetupTest | function def (30, 0) - (30, 9) `SetupTest:`
Test_MyFirstTest | function def (38, 0) - (38, 16) `Test_MyFirstTest:`
Test_MySecondTest | function def (46, 0) - (46, 17) `Test_MySecondTest:`
Test_MyThirdTest | function def (54, 0) - (54, 16) `Test_MyThirdTest:`
MyHelper | function def (73, 0) - (73, 8) `MyHelper:`
Test_MyFourthTest | function def (79, 0) - (79, 17) `Test_MyFourthTest:`
MyHelper | call ref (84, 10) - (84, 18) `GOSUB MyHelper`
DisabledTest_MyFifthTest | function def (89, 0) - (89, 24) `DisabledTest_MyFifthTest:`
TearDownTest | function def (97, 0) - (97, 12) `TearDownTest:`
TearDownTestCase | function def (106, 0) - (106, 16) `TearDownTestCase:`
Development
There is a makefile to simplify the most common activities. The makefile expects you to have Yarn installed and set up.
To build the parser from the grammar:
make build
To run all tests:
make test-all
Editor Support
Editor | Plugin | Syntax Highlighting | Local Variables | Folds | Indents |
---|---|---|---|---|---|
Neovim | nvim-treesitter | ✓ | ✓ | ✓ | ✓ |
Helix | ✓ |
Limitations
(symbol)
nodes that represent an unquoted module, like\module
, cannot be differentiated from node type(trace32_hll_variable)
, e.g.\x
.- Commands from the
Var
command group that contain multiple chained(format_expression) (_hll_expression)
blocks - Unquoted
(path)
nodes are not clearly distinguishable from other literal types in command argument lists. - For HLL expressions used at the top level of commands, the use of spaces is more restricted than for nested expressions inside parentheses. The grammar only models the strict behavior.
- PRACTICE comments start with either
//
or;
. However, in HLL expressions;
can be used as separator for multiple statements. The grammar will always interpret;
as the start of(comment)
node.
Mirrors
This repository is mirrored to https://gitlab.com/xasc/tree-sitter-t32. The main repository is https://codeberg.org/xasc/tree-sitter-t32.