feat: improve tree-sitter syntax highlighting with named nodes
- Add aliases for keywords (VAR_INPUT, BEGIN, IF, etc.) as named nodes - Add aliases for built-in types (INT, BOOL, STRING, etc.) as type_builtin - Add aliases for constants (TRUE, FALSE) - Add aliases for operators (AND, OR, NOT, MOD) - Add prefix node for # variable prefix highlighting - Highlight FB instance names in calls - Highlight FB parameter names as properties - Update README with detailed syntax highlighting features - Update .gitignore for *.wasm files
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
*.wasm
|
||||||
*.log
|
*.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -33,11 +33,15 @@ A comprehensive Neovim/LazyVim plugin providing **Language Server Protocol (LSP)
|
|||||||
|
|
||||||
### Syntax Highlighting
|
### Syntax Highlighting
|
||||||
- Full SCL syntax support via tree-sitter
|
- Full SCL syntax support via tree-sitter
|
||||||
- ORGANIZATION_BLOCK, FUNCTION_BLOCK, FUNCTION definitions
|
- Block definitions: ORGANIZATION_BLOCK, FUNCTION_BLOCK, FUNCTION
|
||||||
- Variable declarations (VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_TEMP, etc.)
|
- Variable sections: VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_TEMP, VAR_CONSTANT
|
||||||
- Control structures (IF/THEN/ELSE, CASE, FOR, WHILE, REPEAT)
|
- Control structures: IF/THEN/ELSIF/ELSE/END_IF, CASE/OF/END_CASE, FOR/TO/BY/DO/END_FOR, WHILE/END_WHILE, REPEAT/UNTIL/END_REPEAT
|
||||||
- Code regions and comments
|
- Built-in data types: BOOL, INT, DINT, REAL, STRING, TIME, etc.
|
||||||
- All SCL data types and operators
|
- Function block instances highlighted in calls
|
||||||
|
- FB parameter names (IN, PT, CU, etc.) highlighted as properties
|
||||||
|
- `#` prefix for local variables highlighted
|
||||||
|
- Operators: AND, OR, NOT, XOR, MOD
|
||||||
|
- Comments: line (`//`), block (`(* *)`), C-style (`/* */`)
|
||||||
|
|
||||||
### Additional Features
|
### Additional Features
|
||||||
| Feature | Description |
|
| Feature | Description |
|
||||||
|
|||||||
+163
-86
@@ -13,6 +13,8 @@ module.exports = grammar({
|
|||||||
[$.region_statement],
|
[$.region_statement],
|
||||||
[$.region_name],
|
[$.region_name],
|
||||||
[$.case_statement],
|
[$.case_statement],
|
||||||
|
[$.fb_call, $.function_call],
|
||||||
|
[$.fb_parameter, $.parameter],
|
||||||
[$.var_declaration, $.var_temp_declaration],
|
[$.var_declaration, $.var_temp_declaration],
|
||||||
[$.var_declaration, $.var_constant_declaration],
|
[$.var_declaration, $.var_constant_declaration],
|
||||||
[$.var_declaration, $.var_retain_declaration],
|
[$.var_declaration, $.var_retain_declaration],
|
||||||
@@ -31,36 +33,36 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
organization_block: $ => seq(
|
organization_block: $ => seq(
|
||||||
'ORGANIZATION_BLOCK',
|
alias('ORGANIZATION_BLOCK', $.keyword),
|
||||||
field('name', $.string),
|
field('name', $.string),
|
||||||
optional(seq('TITLE', '=', choice($.string, $.identifier))),
|
optional(seq(alias('TITLE', $.keyword), '=', choice($.string, $.identifier))),
|
||||||
optional($.attribute_list),
|
optional($.attribute_list),
|
||||||
optional(seq('VERSION', ':', $.number)),
|
optional(seq(alias('VERSION', $.keyword), ':', $.number)),
|
||||||
repeat($.var_declaration),
|
repeat($.var_declaration),
|
||||||
'BEGIN',
|
alias('BEGIN', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_ORGANIZATION_BLOCK'
|
alias('END_ORGANIZATION_BLOCK', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
function_block: $ => seq(
|
function_block: $ => seq(
|
||||||
'FUNCTION_BLOCK',
|
alias('FUNCTION_BLOCK', $.keyword),
|
||||||
field('name', $.string),
|
field('name', $.string),
|
||||||
optional(seq('TITLE', '=', choice($.string, $.identifier))),
|
optional(seq(alias('TITLE', $.keyword), '=', choice($.string, $.identifier))),
|
||||||
optional($.attribute_list),
|
optional($.attribute_list),
|
||||||
optional(seq('VERSION', ':', $.number)),
|
optional(seq(alias('VERSION', $.keyword), ':', $.number)),
|
||||||
repeat($.var_declaration),
|
repeat($.var_declaration),
|
||||||
'BEGIN',
|
alias('BEGIN', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_FUNCTION_BLOCK'
|
alias('END_FUNCTION_BLOCK', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
function: $ => seq(
|
function: $ => seq(
|
||||||
'FUNCTION',
|
alias('FUNCTION', $.keyword),
|
||||||
field('name', $.string),
|
field('name', $.string),
|
||||||
optional(seq(':', $.type)),
|
optional(seq(':', $.type)),
|
||||||
optional(seq('TITLE', '=', choice($.string, $.identifier))),
|
optional(seq(alias('TITLE', $.keyword), '=', choice($.string, $.identifier))),
|
||||||
optional($.attribute_list),
|
optional($.attribute_list),
|
||||||
optional(seq('VERSION', ':', $.number)),
|
optional(seq(alias('VERSION', $.keyword), ':', $.number)),
|
||||||
repeat(choice(
|
repeat(choice(
|
||||||
$.var_declaration,
|
$.var_declaration,
|
||||||
$.var_temp_declaration,
|
$.var_temp_declaration,
|
||||||
@@ -69,9 +71,9 @@ module.exports = grammar({
|
|||||||
$.var_non_retain_declaration,
|
$.var_non_retain_declaration,
|
||||||
$.block_comment
|
$.block_comment
|
||||||
)),
|
)),
|
||||||
'BEGIN',
|
alias('BEGIN', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_FUNCTION'
|
alias('END_FUNCTION', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
attribute_list: $ => seq(
|
attribute_list: $ => seq(
|
||||||
@@ -90,59 +92,60 @@ module.exports = grammar({
|
|||||||
|
|
||||||
attribute_value: $ => choice(
|
attribute_value: $ => choice(
|
||||||
$.string,
|
$.string,
|
||||||
'TRUE', 'FALSE',
|
alias('TRUE', $.constant),
|
||||||
|
alias('FALSE', $.constant),
|
||||||
$.identifier
|
$.identifier
|
||||||
),
|
),
|
||||||
|
|
||||||
var_declaration: $ => seq(
|
var_declaration: $ => seq(
|
||||||
choice(
|
choice(
|
||||||
'VAR_INPUT',
|
alias('VAR_INPUT', $.keyword),
|
||||||
'VAR_OUTPUT',
|
alias('VAR_OUTPUT', $.keyword),
|
||||||
'VAR_IN_OUT',
|
alias('VAR_IN_OUT', $.keyword),
|
||||||
'VAR',
|
alias('VAR', $.keyword),
|
||||||
'VAR_TEMP',
|
alias('VAR_TEMP', $.keyword),
|
||||||
seq('VAR', 'CONSTANT'),
|
seq(alias('VAR', $.keyword), alias('CONSTANT', $.keyword)),
|
||||||
seq('VAR', 'RETAIN'),
|
seq(alias('VAR', $.keyword), alias('RETAIN', $.keyword)),
|
||||||
seq('VAR', 'NON_RETAIN'),
|
seq(alias('VAR', $.keyword), alias('NON_RETAIN', $.keyword)),
|
||||||
'VAR_CONSTANT',
|
alias('VAR_CONSTANT', $.keyword),
|
||||||
'VAR_RETAIN',
|
alias('VAR_RETAIN', $.keyword),
|
||||||
'VAR_NON_RETAIN'
|
alias('VAR_NON_RETAIN', $.keyword)
|
||||||
),
|
),
|
||||||
repeat(choice($.var_item, $.block_comment)),
|
repeat(choice($.var_item, $.block_comment)),
|
||||||
'END_VAR'
|
alias('END_VAR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
var_temp_declaration: $ => seq(
|
var_temp_declaration: $ => seq(
|
||||||
'VAR_TEMP',
|
alias('VAR_TEMP', $.keyword),
|
||||||
repeat(choice($.var_item, $.block_comment)),
|
repeat(choice($.var_item, $.block_comment)),
|
||||||
'END_VAR'
|
alias('END_VAR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
var_constant_declaration: $ => seq(
|
var_constant_declaration: $ => seq(
|
||||||
choice(
|
choice(
|
||||||
seq('VAR', 'CONSTANT'),
|
seq(alias('VAR', $.keyword), alias('CONSTANT', $.keyword)),
|
||||||
'VAR_CONSTANT'
|
alias('VAR_CONSTANT', $.keyword)
|
||||||
),
|
),
|
||||||
repeat(choice($.var_item, $.block_comment)),
|
repeat(choice($.var_item, $.block_comment)),
|
||||||
'END_VAR'
|
alias('END_VAR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
var_retain_declaration: $ => seq(
|
var_retain_declaration: $ => seq(
|
||||||
choice(
|
choice(
|
||||||
seq('VAR', 'RETAIN'),
|
seq(alias('VAR', $.keyword), alias('RETAIN', $.keyword)),
|
||||||
'VAR_RETAIN'
|
alias('VAR_RETAIN', $.keyword)
|
||||||
),
|
),
|
||||||
repeat(choice($.var_item, $.block_comment)),
|
repeat(choice($.var_item, $.block_comment)),
|
||||||
'END_VAR'
|
alias('END_VAR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
var_non_retain_declaration: $ => seq(
|
var_non_retain_declaration: $ => seq(
|
||||||
choice(
|
choice(
|
||||||
seq('VAR', 'NON_RETAIN'),
|
seq(alias('VAR', $.keyword), alias('NON_RETAIN', $.keyword)),
|
||||||
'VAR_NON_RETAIN'
|
alias('VAR_NON_RETAIN', $.keyword)
|
||||||
),
|
),
|
||||||
repeat(choice($.var_item, $.block_comment)),
|
repeat(choice($.var_item, $.block_comment)),
|
||||||
'END_VAR'
|
alias('END_VAR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
var_item: $ => seq(
|
var_item: $ => seq(
|
||||||
@@ -155,33 +158,69 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
type: $ => choice(
|
type: $ => choice(
|
||||||
'BOOL', 'Bool',
|
alias('BOOL', $.type_builtin),
|
||||||
'INT', 'Int', 'int',
|
alias('Bool', $.type_builtin),
|
||||||
'DINT', 'DInt', 'dint',
|
alias('INT', $.type_builtin),
|
||||||
'SINT', 'SInt', 'sint',
|
alias('Int', $.type_builtin),
|
||||||
'USINT', 'USInt', 'usint',
|
alias('int', $.type_builtin),
|
||||||
'UINT', 'UInt', 'uint',
|
alias('DINT', $.type_builtin),
|
||||||
'WORD', 'Word', 'word',
|
alias('DInt', $.type_builtin),
|
||||||
'DWORD', 'DWord', 'dword',
|
alias('dint', $.type_builtin),
|
||||||
'BYTE', 'Byte', 'byte',
|
alias('SINT', $.type_builtin),
|
||||||
'REAL', 'Real', 'real',
|
alias('SInt', $.type_builtin),
|
||||||
'LREAL', 'LReal', 'lreal',
|
alias('sint', $.type_builtin),
|
||||||
'TIME', 'Time', 'time',
|
alias('USINT', $.type_builtin),
|
||||||
'TOD', 'Tod', 'tod',
|
alias('USInt', $.type_builtin),
|
||||||
'DT', 'Dt', 'dt',
|
alias('usint', $.type_builtin),
|
||||||
'String', 'STRING', 'string',
|
alias('UINT', $.type_builtin),
|
||||||
seq(choice('String', 'STRING', 'string'), '[', $.number, ']'),
|
alias('UInt', $.type_builtin),
|
||||||
'WString', 'WSTRING', 'wstring',
|
alias('uint', $.type_builtin),
|
||||||
seq(choice('WString', 'WSTRING', 'wstring'), '[', $.number, ']'),
|
alias('WORD', $.type_builtin),
|
||||||
'Char', 'CHAR', 'char',
|
alias('Word', $.type_builtin),
|
||||||
'WChar', 'WCHAR', 'wchar',
|
alias('word', $.type_builtin),
|
||||||
seq('ARRAY', '[', $.number, '..', $.number, ']', 'OF', $.type),
|
alias('DWORD', $.type_builtin),
|
||||||
|
alias('DWord', $.type_builtin),
|
||||||
|
alias('dword', $.type_builtin),
|
||||||
|
alias('BYTE', $.type_builtin),
|
||||||
|
alias('Byte', $.type_builtin),
|
||||||
|
alias('byte', $.type_builtin),
|
||||||
|
alias('REAL', $.type_builtin),
|
||||||
|
alias('Real', $.type_builtin),
|
||||||
|
alias('real', $.type_builtin),
|
||||||
|
alias('LREAL', $.type_builtin),
|
||||||
|
alias('LReal', $.type_builtin),
|
||||||
|
alias('lreal', $.type_builtin),
|
||||||
|
alias('TIME', $.type_builtin),
|
||||||
|
alias('Time', $.type_builtin),
|
||||||
|
alias('time', $.type_builtin),
|
||||||
|
alias('TOD', $.type_builtin),
|
||||||
|
alias('Tod', $.type_builtin),
|
||||||
|
alias('tod', $.type_builtin),
|
||||||
|
alias('DT', $.type_builtin),
|
||||||
|
alias('Dt', $.type_builtin),
|
||||||
|
alias('dt', $.type_builtin),
|
||||||
|
alias('String', $.type_builtin),
|
||||||
|
alias('STRING', $.type_builtin),
|
||||||
|
alias('string', $.type_builtin),
|
||||||
|
seq(choice(alias('String', $.type_builtin), alias('STRING', $.type_builtin), alias('string', $.type_builtin)), '[', $.number, ']'),
|
||||||
|
alias('WString', $.type_builtin),
|
||||||
|
alias('WSTRING', $.type_builtin),
|
||||||
|
alias('wstring', $.type_builtin),
|
||||||
|
seq(choice(alias('WString', $.type_builtin), alias('WSTRING', $.type_builtin), alias('wstring', $.type_builtin)), '[', $.number, ']'),
|
||||||
|
alias('Char', $.type_builtin),
|
||||||
|
alias('CHAR', $.type_builtin),
|
||||||
|
alias('char', $.type_builtin),
|
||||||
|
alias('WChar', $.type_builtin),
|
||||||
|
alias('WCHAR', $.type_builtin),
|
||||||
|
alias('wchar', $.type_builtin),
|
||||||
|
seq(alias('ARRAY', $.keyword), '[', $.number, '..', $.number, ']', alias('OF', $.keyword), $.type),
|
||||||
$.identifier,
|
$.identifier,
|
||||||
$.string
|
$.string
|
||||||
),
|
),
|
||||||
|
|
||||||
statement: $ => choice(
|
statement: $ => choice(
|
||||||
$.assignment,
|
$.assignment,
|
||||||
|
$.fb_call,
|
||||||
$.if_statement,
|
$.if_statement,
|
||||||
$.case_statement,
|
$.case_statement,
|
||||||
$.for_statement,
|
$.for_statement,
|
||||||
@@ -200,6 +239,26 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
empty_statement: $ => ';',
|
empty_statement: $ => ';',
|
||||||
|
|
||||||
|
fb_call: $ => seq(
|
||||||
|
field('instance', choice($.prefixed_identifier, $.identifier)),
|
||||||
|
'(',
|
||||||
|
optional(seq(
|
||||||
|
$.fb_parameter_list
|
||||||
|
)),
|
||||||
|
')'
|
||||||
|
),
|
||||||
|
|
||||||
|
fb_parameter_list: $ => seq(
|
||||||
|
$.fb_parameter,
|
||||||
|
repeat(seq(',', $.fb_parameter))
|
||||||
|
),
|
||||||
|
|
||||||
|
fb_parameter: $ => seq(
|
||||||
|
field('name', $.identifier),
|
||||||
|
choice(':=', '=>'),
|
||||||
|
$.expression
|
||||||
|
),
|
||||||
|
|
||||||
assignment: $ => seq(
|
assignment: $ => seq(
|
||||||
field('target', $.lvalue),
|
field('target', $.lvalue),
|
||||||
@@ -218,63 +277,83 @@ module.exports = grammar({
|
|||||||
|
|
||||||
function_name: $ => $.string,
|
function_name: $ => $.string,
|
||||||
|
|
||||||
prefixed_identifier: $ => seq('#', $.identifier),
|
prefixed_identifier: $ => seq(alias('#', $.prefix), $.identifier),
|
||||||
|
|
||||||
field_access: $ => seq($.lvalue, '.', choice($.identifier, $.prefixed_identifier)),
|
field_access: $ => seq($.lvalue, '.', choice($.identifier, $.prefixed_identifier)),
|
||||||
|
|
||||||
array_access: $ => seq($.lvalue, '[', $.expression, ']'),
|
array_access: $ => seq($.lvalue, '[', $.expression, ']'),
|
||||||
|
|
||||||
if_statement: $ => seq(
|
if_statement: $ => seq(
|
||||||
'IF', $.expression, 'THEN',
|
alias('IF', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
alias('THEN', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
repeat($.elsif_clause),
|
repeat($.elsif_clause),
|
||||||
optional($.else_clause),
|
optional($.else_clause),
|
||||||
'END_IF'
|
alias('END_IF', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
elsif_clause: $ => seq(
|
elsif_clause: $ => seq(
|
||||||
'ELSIF', $.expression, 'THEN', repeat($.statement)
|
alias('ELSIF', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
alias('THEN', $.keyword),
|
||||||
|
repeat($.statement)
|
||||||
),
|
),
|
||||||
|
|
||||||
else_clause: $ => seq('ELSE', repeat($.statement)),
|
else_clause: $ => seq(alias('ELSE', $.keyword), repeat($.statement)),
|
||||||
|
|
||||||
case_statement: $ => seq(
|
case_statement: $ => seq(
|
||||||
'CASE', $.expression, 'OF',
|
alias('CASE', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
alias('OF', $.keyword),
|
||||||
repeat($.case_item),
|
repeat($.case_item),
|
||||||
optional($.else_clause),
|
optional($.else_clause),
|
||||||
'END_CASE',
|
alias('END_CASE', $.keyword),
|
||||||
optional(';')
|
optional(';')
|
||||||
),
|
),
|
||||||
|
|
||||||
case_item: $ => seq(
|
case_item: $ => seq(
|
||||||
choice($.number, $.identifier, $.prefixed_identifier, $.range),
|
choice($.number, $.identifier, $.prefixed_identifier, $.range),
|
||||||
':', repeat($.statement)
|
':',
|
||||||
|
repeat($.statement)
|
||||||
),
|
),
|
||||||
|
|
||||||
range: $ => seq($.number, '..', $.number),
|
range: $ => seq($.number, '..', $.number),
|
||||||
|
|
||||||
for_statement: $ => seq(
|
for_statement: $ => seq(
|
||||||
'FOR', $.identifier, ':=', $.expression, 'TO', $.expression, optional(seq('BY', $.expression)), 'DO',
|
alias('FOR', $.keyword),
|
||||||
|
$.identifier,
|
||||||
|
':=',
|
||||||
|
$.expression,
|
||||||
|
alias('TO', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
optional(seq(alias('BY', $.keyword), $.expression)),
|
||||||
|
alias('DO', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_FOR'
|
alias('END_FOR', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
while_statement: $ => seq(
|
while_statement: $ => seq(
|
||||||
'WHILE', $.expression, 'DO',
|
alias('WHILE', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
alias('DO', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_WHILE'
|
alias('END_WHILE', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
repeat_statement: $ => seq(
|
repeat_statement: $ => seq(
|
||||||
'REPEAT',
|
alias('REPEAT', $.keyword),
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'UNTIL', $.expression, 'END_REPEAT'
|
alias('UNTIL', $.keyword),
|
||||||
|
$.expression,
|
||||||
|
alias('END_REPEAT', $.keyword)
|
||||||
),
|
),
|
||||||
|
|
||||||
region_statement: $ => seq(
|
region_statement: $ => seq(
|
||||||
'REGION', $.region_name,
|
alias('REGION', $.keyword),
|
||||||
|
$.region_name,
|
||||||
repeat($.statement),
|
repeat($.statement),
|
||||||
'END_REGION',
|
alias('END_REGION', $.keyword),
|
||||||
optional($.region_name)
|
optional($.region_name)
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -320,19 +399,19 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
unary_expression: $ => prec.right(10, choice(
|
unary_expression: $ => prec.right(10, choice(
|
||||||
seq('NOT', $.expression),
|
seq(alias('NOT', $.operator), $.expression),
|
||||||
seq('+', $.expression),
|
seq('+', $.expression),
|
||||||
seq('-', $.expression)
|
seq('-', $.expression)
|
||||||
)),
|
)),
|
||||||
|
|
||||||
binary_expression: $ => choice(
|
binary_expression: $ => choice(
|
||||||
prec.left(2, seq($.expression, 'OR', $.expression)),
|
prec.left(2, seq($.expression, alias('OR', $.operator), $.expression)),
|
||||||
prec.left(3, seq($.expression, 'XOR', $.expression)),
|
prec.left(3, seq($.expression, alias('XOR', $.operator), $.expression)),
|
||||||
prec.left(4, seq($.expression, 'AND', $.expression)),
|
prec.left(4, seq($.expression, alias('AND', $.operator), $.expression)),
|
||||||
prec.left(5, seq($.expression, choice('=', '<>'), $.expression)),
|
prec.left(5, seq($.expression, choice('=', '<>'), $.expression)),
|
||||||
prec.left(6, seq($.expression, choice('<', '>', '<=', '>='), $.expression)),
|
prec.left(6, seq($.expression, choice('<', '>', '<=', '>='), $.expression)),
|
||||||
prec.left(7, seq($.expression, choice('+', '-'), $.expression)),
|
prec.left(7, seq($.expression, choice('+', '-'), $.expression)),
|
||||||
prec.left(8, seq($.expression, choice('*', '/', 'MOD'), $.expression))
|
prec.left(8, seq($.expression, choice('*', '/', alias('MOD', $.operator)), $.expression))
|
||||||
),
|
),
|
||||||
|
|
||||||
number: $ => token(/\d+(\.\d+)?/),
|
number: $ => token(/\d+(\.\d+)?/),
|
||||||
@@ -346,13 +425,11 @@ module.exports = grammar({
|
|||||||
seq('"', repeat(choice(/[^"\n]/, '""')), '"')
|
seq('"', repeat(choice(/[^"\n]/, '""')), '"')
|
||||||
),
|
),
|
||||||
|
|
||||||
// Support for STRING type with length: STRING[80]
|
|
||||||
string_type: $ => seq(
|
string_type: $ => seq(
|
||||||
choice('STRING', 'String', 'string', 'WSTRING', 'WString', 'wstring'),
|
choice(alias('STRING', $.type_builtin), alias('String', $.type_builtin), alias('string', $.type_builtin), alias('WSTRING', $.type_builtin), alias('WString', $.type_builtin), alias('wstring', $.type_builtin)),
|
||||||
optional(seq('[', $.number, ']'))
|
optional(seq('[', $.number, ']'))
|
||||||
),
|
),
|
||||||
|
|
||||||
// Support for SCL character literals: 'A', WCHAR#'B'
|
|
||||||
char_literal: $ => choice(
|
char_literal: $ => choice(
|
||||||
seq("'", /[^']/, "'"),
|
seq("'", /[^']/, "'"),
|
||||||
seq('WCHAR#', "'", /[^']/, "'")
|
seq('WCHAR#', "'", /[^']/, "'")
|
||||||
@@ -374,9 +451,9 @@ module.exports = grammar({
|
|||||||
'*/)'
|
'*/)'
|
||||||
)),
|
)),
|
||||||
|
|
||||||
exit_statement: $ => 'EXIT',
|
exit_statement: $ => alias('EXIT', $.keyword),
|
||||||
|
|
||||||
continue_statement: $ => 'CONTINUE'
|
continue_statement: $ => alias('CONTINUE', $.keyword)
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -226,6 +226,67 @@ M.DATA_TYPES = {
|
|||||||
DTL = true,
|
DTL = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M.PARAMETERS = {
|
||||||
|
TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TP = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TONR = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" }, { name = "R", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
CTU = { inputs = { { name = "CU", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
CTD = { inputs = { { name = "CD", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
CTUD = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
R_TRIG = { inputs = { { name = "CLK", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" } } },
|
||||||
|
F_TRIG = { inputs = { { name = "CLK", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" } } },
|
||||||
|
SR = { inputs = { { name = "S", type = "BOOL" }, { name = "R1", type = "BOOL" } }, outputs = { { name = "Q1", type = "BOOL" } } },
|
||||||
|
RS = { inputs = { { name = "S1", type = "BOOL" }, { name = "R", type = "BOOL" } }, outputs = { { name = "Q1", type = "BOOL" } } },
|
||||||
|
IEC_TIMER = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TP = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_COUNTER = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTU = { inputs = { { name = "CU", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTD = { inputs = { { name = "CD", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTUD = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
ADD = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SUB = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MUL = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
DIV = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MIN = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MAX = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LIMIT = { inputs = { { name = "MN" }, { name = "IN" }, { name = "MX" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MOVE = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CONVERT = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROUND = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
TRUNC = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CEIL = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
FLOOR = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SQR = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SQRT = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SIN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
COS = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
TAN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ASIN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ACOS = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ATAN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LEN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CONCAT = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LEFT = { inputs = { { name = "IN" }, { name = "L" } }, outputs = { { name = "OUT" } } },
|
||||||
|
RIGHT = { inputs = { { name = "IN" }, { name = "L" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MID = { inputs = { { name = "IN" }, { name = "L" }, { name = "P" } }, outputs = { { name = "OUT" } } },
|
||||||
|
AND = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
OR = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
XOR = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SHL = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SHR = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROL = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROR = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
BCD_I = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
I_BCD = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
}
|
||||||
|
|
||||||
|
function M.get_parameters(name)
|
||||||
|
return M.PARAMETERS[name:upper()]
|
||||||
|
end
|
||||||
|
|
||||||
function M.is_known_function(name)
|
function M.is_known_function(name)
|
||||||
return M.FUNCTIONS[name:upper()] or false
|
return M.FUNCTIONS[name:upper()] or false
|
||||||
end
|
end
|
||||||
|
|||||||
+1115
-286
File diff suppressed because it is too large
Load Diff
+175
-3
@@ -335,6 +335,30 @@ function handlers.textDocument_hover(params)
|
|||||||
var_info.data_type or "unknown",
|
var_info.data_type or "unknown",
|
||||||
var_info.line + 1
|
var_info.line + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if var_info.comment and var_info.comment ~= "" then
|
||||||
|
detail = detail .. "\n\n" .. var_info.comment
|
||||||
|
end
|
||||||
|
|
||||||
|
if var_info.data_type then
|
||||||
|
local builtin_params = builtin.get_parameters(var_info.data_type)
|
||||||
|
if builtin_params then
|
||||||
|
detail = detail .. "\n\n**Members:**\n"
|
||||||
|
if builtin_params.inputs and #builtin_params.inputs > 0 then
|
||||||
|
detail = detail .. "*Inputs:*\n"
|
||||||
|
for _, inp in ipairs(builtin_params.inputs) do
|
||||||
|
detail = detail .. string.format(" - `%s`: %s\n", inp.name, inp.type or "ANY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if builtin_params.outputs and #builtin_params.outputs > 0 then
|
||||||
|
detail = detail .. "*Outputs:*\n"
|
||||||
|
for _, out in ipairs(builtin_params.outputs) do
|
||||||
|
detail = detail .. string.format(" - `%s`: %s\n", out.name, out.type or "ANY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
contents = { kind = "markdown", value = detail },
|
contents = { kind = "markdown", value = detail },
|
||||||
range = {
|
range = {
|
||||||
@@ -348,10 +372,17 @@ function handlers.textDocument_hover(params)
|
|||||||
for type_name, type_info in pairs(doc.types) do
|
for type_name, type_info in pairs(doc.types) do
|
||||||
if type_name == word then
|
if type_name == word then
|
||||||
local detail = string.format("**Type**: `%s`\nKind: %s", type_name, type_info.kind)
|
local detail = string.format("**Type**: `%s`\nKind: %s", type_name, type_info.kind)
|
||||||
|
if type_info.comment and type_info.comment ~= "" then
|
||||||
|
detail = detail .. "\n\n" .. type_info.comment
|
||||||
|
end
|
||||||
if type_info.kind == "struct" and type_info.fields then
|
if type_info.kind == "struct" and type_info.fields then
|
||||||
detail = detail .. "\n\n**Fields:**\n"
|
detail = detail .. "\n\n**Fields:**\n"
|
||||||
for _, field in ipairs(type_info.fields) do
|
for _, field in ipairs(type_info.fields) do
|
||||||
detail = detail .. string.format("- `%s`: %s\n", field.name, field.type)
|
if field.comment and field.comment ~= "" then
|
||||||
|
detail = detail .. string.format("- `%s`: %s // %s\n", field.name, field.type, field.comment)
|
||||||
|
else
|
||||||
|
detail = detail .. string.format("- `%s`: %s\n", field.name, field.type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return {
|
return {
|
||||||
@@ -365,6 +396,124 @@ function handlers.textDocument_hover(params)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if builtin.is_known_function_block(word) or builtin.is_known_function(word) then
|
||||||
|
local params_info = builtin.get_parameters(word)
|
||||||
|
local kind = builtin.is_known_function_block(word) and "Function Block" or "Function"
|
||||||
|
local detail = string.format("**%s**: `%s`\n", kind, word)
|
||||||
|
if params_info then
|
||||||
|
detail = detail .. "\n**Parameters:**\n"
|
||||||
|
if params_info.inputs and #params_info.inputs > 0 then
|
||||||
|
detail = detail .. "*Inputs:*\n"
|
||||||
|
for _, inp in ipairs(params_info.inputs) do
|
||||||
|
detail = detail .. string.format(" - `%s`: %s\n", inp.name, inp.type or "ANY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if params_info.outputs and #params_info.outputs > 0 then
|
||||||
|
detail = detail .. "*Outputs:*\n"
|
||||||
|
for _, out in ipairs(params_info.outputs) do
|
||||||
|
detail = detail .. string.format(" - `%s`: %s\n", out.name, out.type or "ANY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
detail = detail .. "\n_(No parameter info available)_"
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
contents = { kind = "markdown", value = detail },
|
||||||
|
range = {
|
||||||
|
start = { line = params.position.line, character = word_start - 1 },
|
||||||
|
["end"] = { line = params.position.line, character = word_end - 1 },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local fb_param_info = nil
|
||||||
|
|
||||||
|
local function find_fb_call_start(lines, current_line_idx)
|
||||||
|
for i = current_line_idx, 1, -1 do
|
||||||
|
local l = lines[i]
|
||||||
|
local fb_name = l:match("#([%w_]+)%s*%(") or l:match("([%w_]+)%s*%(")
|
||||||
|
if fb_name and doc.variables and doc.variables[fb_name] then
|
||||||
|
return fb_name, i
|
||||||
|
end
|
||||||
|
if l:match("%)%s*;%s*$") then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local fb_name_on_line, _ = find_fb_call_start(lines, line_idx)
|
||||||
|
if fb_name_on_line then
|
||||||
|
local fb_var = doc.variables[fb_name_on_line]
|
||||||
|
if fb_var then
|
||||||
|
local fb_type = fb_var.data_type
|
||||||
|
if fb_type then
|
||||||
|
local clean_type = fb_type:gsub('"', ""):gsub("#", "")
|
||||||
|
local params_info = builtin.get_parameters(clean_type)
|
||||||
|
|
||||||
|
if not params_info then
|
||||||
|
local workspace_types = plc_json.get_types(doc.root_dir)
|
||||||
|
if workspace_types and workspace_types[clean_type] then
|
||||||
|
local ws_type = workspace_types[clean_type]
|
||||||
|
if ws_type.kind == "function_block" or ws_type.kind == "function" then
|
||||||
|
local fields = {}
|
||||||
|
for _, f in ipairs(ws_type.inputs or {}) do
|
||||||
|
table.insert(fields, { name = f.name, type = f.type, comment = f.comment })
|
||||||
|
end
|
||||||
|
params_info = { inputs = fields, outputs = ws_type.outputs or {} }
|
||||||
|
elseif ws_type.fields then
|
||||||
|
local fields = {}
|
||||||
|
for _, f in ipairs(ws_type.fields) do
|
||||||
|
table.insert(fields, { name = f.name, type = f.type, comment = f.comment })
|
||||||
|
end
|
||||||
|
params_info = { inputs = fields, outputs = {} }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not params_info and doc.types and doc.types[clean_type] and doc.types[clean_type].fields then
|
||||||
|
local fields = {}
|
||||||
|
for _, f in ipairs(doc.types[clean_type].fields) do
|
||||||
|
table.insert(fields, { name = f.name, type = f.type, comment = f.comment })
|
||||||
|
end
|
||||||
|
params_info = { inputs = fields, outputs = {} }
|
||||||
|
end
|
||||||
|
|
||||||
|
if params_info then
|
||||||
|
for _, inp in ipairs(params_info.inputs or {}) do
|
||||||
|
if inp.name:upper() == word:upper() then
|
||||||
|
fb_param_info = { name = inp.name, type = inp.type, direction = "input", comment = inp.comment }
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not fb_param_info then
|
||||||
|
for _, out in ipairs(params_info.outputs or {}) do
|
||||||
|
if out.name:upper() == word:upper() then
|
||||||
|
fb_param_info = { name = out.name, type = out.type, direction = "output", comment = out.comment }
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if fb_param_info then
|
||||||
|
local detail = string.format("**Parameter**: `%s`\nType: `%s`\nDirection: %s",
|
||||||
|
fb_param_info.name, fb_param_info.type or "ANY", fb_param_info.direction)
|
||||||
|
if fb_param_info.comment and fb_param_info.comment ~= "" then
|
||||||
|
detail = detail .. "\n\n" .. fb_param_info.comment
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
contents = { kind = "markdown", value = detail },
|
||||||
|
range = {
|
||||||
|
start = { line = params.position.line, character = word_start - 1 },
|
||||||
|
["end"] = { line = params.position.line, character = word_end - 1 },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -432,9 +581,10 @@ function handlers.textDocument_completion(params)
|
|||||||
local var_info = doc.variables and doc.variables[var_name]
|
local var_info = doc.variables and doc.variables[var_name]
|
||||||
local data_type = var_info and var_info.data_type
|
local data_type = var_info and var_info.data_type
|
||||||
|
|
||||||
if data_type and doc.types then
|
if data_type then
|
||||||
local struct_name = data_type
|
local struct_name = data_type
|
||||||
if doc.types[struct_name] and doc.types[struct_name].fields then
|
|
||||||
|
if doc.types and doc.types[struct_name] and doc.types[struct_name].fields then
|
||||||
for _, field in ipairs(doc.types[struct_name].fields) do
|
for _, field in ipairs(doc.types[struct_name].fields) do
|
||||||
table.insert(items, {
|
table.insert(items, {
|
||||||
label = field.name,
|
label = field.name,
|
||||||
@@ -444,6 +594,28 @@ function handlers.textDocument_completion(params)
|
|||||||
insertTextFormat = 1,
|
insertTextFormat = 1,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
local builtin_params = builtin.get_parameters(struct_name)
|
||||||
|
if builtin_params then
|
||||||
|
for _, inp in ipairs(builtin_params.inputs or {}) do
|
||||||
|
table.insert(items, {
|
||||||
|
label = inp.name,
|
||||||
|
kind = 13,
|
||||||
|
detail = struct_name .. "." .. inp.name .. ": " .. (inp.type or "ANY"),
|
||||||
|
insertText = inp.name,
|
||||||
|
insertTextFormat = 1,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
for _, out in ipairs(builtin_params.outputs or {}) do
|
||||||
|
table.insert(items, {
|
||||||
|
label = out.name,
|
||||||
|
kind = 13,
|
||||||
|
detail = struct_name .. "." .. out.name .. ": " .. (out.type or "ANY"),
|
||||||
|
insertText = out.name,
|
||||||
|
insertTextFormat = 1,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+216
-431
@@ -84,8 +84,12 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": false,
|
"multiple": false,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "constant",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -108,6 +112,10 @@
|
|||||||
{
|
{
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "operator",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -162,6 +170,25 @@
|
|||||||
{
|
{
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "continue_statement",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -172,8 +199,12 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -193,6 +224,10 @@
|
|||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -205,6 +240,21 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {}
|
"fields": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "exit_statement",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true,
|
"named": true,
|
||||||
@@ -264,6 +314,77 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "fb_call",
|
||||||
|
"named": true,
|
||||||
|
"fields": {
|
||||||
|
"instance": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "prefixed_identifier",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": false,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "fb_parameter_list",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fb_parameter",
|
||||||
|
"named": true,
|
||||||
|
"fields": {
|
||||||
|
"name": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "expression",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fb_parameter_list",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "fb_parameter",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "field_access",
|
"type": "field_access",
|
||||||
"named": true,
|
"named": true,
|
||||||
@@ -303,6 +424,10 @@
|
|||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -327,7 +452,7 @@
|
|||||||
},
|
},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "attribute_list",
|
"type": "attribute_list",
|
||||||
@@ -341,6 +466,10 @@
|
|||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -397,7 +526,7 @@
|
|||||||
},
|
},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "attribute_list",
|
"type": "attribute_list",
|
||||||
@@ -407,6 +536,10 @@
|
|||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -484,6 +617,10 @@
|
|||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -539,7 +676,7 @@
|
|||||||
},
|
},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "attribute_list",
|
"type": "attribute_list",
|
||||||
@@ -549,6 +686,10 @@
|
|||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -607,12 +748,16 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": false,
|
"multiple": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "prefix",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -659,6 +804,10 @@
|
|||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "region_name",
|
"type": "region_name",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -682,6 +831,10 @@
|
|||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -745,6 +898,10 @@
|
|||||||
"type": "exit_statement",
|
"type": "exit_statement",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "fb_call",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "for_statement",
|
"type": "for_statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -803,12 +960,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -820,6 +981,10 @@
|
|||||||
{
|
{
|
||||||
"type": "type",
|
"type": "type",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "type_builtin",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -829,12 +994,16 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": false,
|
"multiple": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "operator",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -845,12 +1014,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block_comment",
|
"type": "block_comment",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "var_item",
|
"type": "var_item",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -864,12 +1037,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block_comment",
|
"type": "block_comment",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "var_item",
|
"type": "var_item",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -923,12 +1100,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block_comment",
|
"type": "block_comment",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "var_item",
|
"type": "var_item",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -942,12 +1123,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block_comment",
|
"type": "block_comment",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "var_item",
|
"type": "var_item",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -961,12 +1146,16 @@
|
|||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block_comment",
|
"type": "block_comment",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "var_item",
|
"type": "var_item",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -986,6 +1175,10 @@
|
|||||||
"type": "expression",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "keyword",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -1001,10 +1194,6 @@
|
|||||||
"type": "\"\"",
|
"type": "\"\"",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "#",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "'",
|
"type": "'",
|
||||||
"named": false
|
"named": false
|
||||||
@@ -1089,346 +1278,6 @@
|
|||||||
"type": ">=",
|
"type": ">=",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "AND",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ARRAY",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BEGIN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BOOL",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BY",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BYTE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Bool",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Byte",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CASE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CHAR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CONSTANT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Char",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DINT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DInt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DO",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DWORD",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "DWord",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Dt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ELSE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ELSIF",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_CASE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_FOR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_FUNCTION",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_FUNCTION_BLOCK",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_IF",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_ORGANIZATION_BLOCK",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_REGION",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_REPEAT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_VAR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "END_WHILE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "FALSE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "FOR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "FUNCTION",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "FUNCTION_BLOCK",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "IF",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "INT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Int",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "LREAL",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "LReal",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MOD",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "NON_RETAIN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "NOT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "OF",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "OR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ORGANIZATION_BLOCK",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "REAL",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "REGION",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "REPEAT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "RETAIN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Real",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SINT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SInt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "String",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "THEN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TIME",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TITLE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TO",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TOD",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TRUE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Time",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Tod",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "UINT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "UInt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "UNTIL",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "USINT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "USInt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_CONSTANT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_INPUT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_IN_OUT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_NON_RETAIN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_OUTPUT",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_RETAIN",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VAR_TEMP",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "VERSION",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WCHAR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WChar",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WHILE",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WORD",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WSTRING",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "WString",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Word",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "XOR",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "[",
|
"type": "[",
|
||||||
"named": false
|
"named": false
|
||||||
@@ -1442,37 +1291,13 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"extra": true
|
"extra": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "byte",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "c_style_comment",
|
"type": "c_style_comment",
|
||||||
"named": true,
|
"named": true,
|
||||||
"extra": true
|
"extra": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "char",
|
"type": "constant",
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "continue_statement",
|
|
||||||
"named": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "dint",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "dt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "dword",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "exit_statement",
|
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1484,73 +1309,33 @@
|
|||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "int",
|
"type": "keyword",
|
||||||
"named": false
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "line_comment",
|
"type": "line_comment",
|
||||||
"named": true,
|
"named": true,
|
||||||
"extra": true
|
"extra": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "lreal",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "real",
|
"type": "operator",
|
||||||
"named": false
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "sint",
|
"type": "prefix",
|
||||||
"named": false
|
"named": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "time",
|
|
||||||
"named": false
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "time_value",
|
"type": "time_value",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "tod",
|
"type": "type_builtin",
|
||||||
"named": false
|
"named": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "TOD",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "uint",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "UInt",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "usint",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "wchar",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "word",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "wstring",
|
|
||||||
"named": false
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "{",
|
"type": "{",
|
||||||
@@ -1560,4 +1345,4 @@
|
|||||||
"type": "}",
|
"type": "}",
|
||||||
"named": false
|
"named": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+58717
-54517
File diff suppressed because it is too large
Load Diff
@@ -129,6 +129,10 @@ function M.extract_variables(content)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local var_data_type = "unknown"
|
local var_data_type = "unknown"
|
||||||
|
local var_comment = line:match("//%s*(.+)$")
|
||||||
|
if not var_comment then
|
||||||
|
var_comment = line:match("%(%*(.-)%*%)")
|
||||||
|
end
|
||||||
if type_start then
|
if type_start then
|
||||||
local type_part = line:sub(type_start + 1)
|
local type_part = line:sub(type_start + 1)
|
||||||
type_part = type_part:gsub("%s*:=.*$", "")
|
type_part = type_part:gsub("%s*:=.*$", "")
|
||||||
@@ -143,6 +147,7 @@ function M.extract_variables(content)
|
|||||||
data_type = var_data_type,
|
data_type = var_data_type,
|
||||||
line = line_num,
|
line = line_num,
|
||||||
character = col - 1,
|
character = col - 1,
|
||||||
|
comment = var_comment,
|
||||||
}
|
}
|
||||||
variable_positions[var_name] = {
|
variable_positions[var_name] = {
|
||||||
line = line_num,
|
line = line_num,
|
||||||
@@ -172,6 +177,7 @@ function M.extract_types(content)
|
|||||||
local brace_depth = 0
|
local brace_depth = 0
|
||||||
local in_struct = false
|
local in_struct = false
|
||||||
local pending_type_name = nil
|
local pending_type_name = nil
|
||||||
|
local pending_comment = nil
|
||||||
|
|
||||||
local function extract_type_name(after_colon)
|
local function extract_type_name(after_colon)
|
||||||
if not after_colon then return nil end
|
if not after_colon then return nil end
|
||||||
@@ -183,6 +189,11 @@ function M.extract_types(content)
|
|||||||
for i, line in ipairs(lines) do
|
for i, line in ipairs(lines) do
|
||||||
local trimmed = line:gsub("^%s+", ""):gsub("%s+$", "")
|
local trimmed = line:gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
|
||||||
|
local is_comment_only = trimmed:match("^//")
|
||||||
|
if is_comment_only then
|
||||||
|
pending_comment = line:match("//%s*(.+)$")
|
||||||
|
end
|
||||||
|
|
||||||
local is_type_line = trimmed:match("^TYPE") and (trimmed:match("^TYPE%s") or trimmed:match('^TYPE"') or trimmed == "TYPE")
|
local is_type_line = trimmed:match("^TYPE") and (trimmed:match("^TYPE%s") or trimmed:match('^TYPE"') or trimmed == "TYPE")
|
||||||
|
|
||||||
if is_type_line then
|
if is_type_line then
|
||||||
@@ -190,6 +201,9 @@ function M.extract_types(content)
|
|||||||
in_struct = false
|
in_struct = false
|
||||||
brace_depth = 0
|
brace_depth = 0
|
||||||
pending_type_name = trimmed:match('^TYPE%s+"([^"]+)') or trimmed:match("^TYPE%s+(%w+)")
|
pending_type_name = trimmed:match('^TYPE%s+"([^"]+)') or trimmed:match("^TYPE%s+(%w+)")
|
||||||
|
if not pending_comment then
|
||||||
|
pending_comment = trimmed:match("//%s*(.+)$")
|
||||||
|
end
|
||||||
elseif in_type_section and trimmed:match("^END_TYPE") then
|
elseif in_type_section and trimmed:match("^END_TYPE") then
|
||||||
in_type_section = false
|
in_type_section = false
|
||||||
in_struct = false
|
in_struct = false
|
||||||
@@ -203,10 +217,12 @@ function M.extract_types(content)
|
|||||||
kind = "struct",
|
kind = "struct",
|
||||||
fields = {},
|
fields = {},
|
||||||
start_line = i - 1,
|
start_line = i - 1,
|
||||||
|
comment = pending_comment,
|
||||||
}
|
}
|
||||||
types[type_name_with_struct] = current_type
|
types[type_name_with_struct] = current_type
|
||||||
in_struct = true
|
in_struct = true
|
||||||
pending_type_name = nil
|
pending_type_name = nil
|
||||||
|
pending_comment = nil
|
||||||
elseif trimmed:match("^STRUCT%s*$") then
|
elseif trimmed:match("^STRUCT%s*$") then
|
||||||
if pending_type_name then
|
if pending_type_name then
|
||||||
current_type = {
|
current_type = {
|
||||||
@@ -214,9 +230,11 @@ function M.extract_types(content)
|
|||||||
kind = "struct",
|
kind = "struct",
|
||||||
fields = {},
|
fields = {},
|
||||||
start_line = i - 1,
|
start_line = i - 1,
|
||||||
|
comment = pending_comment,
|
||||||
}
|
}
|
||||||
types[pending_type_name] = current_type
|
types[pending_type_name] = current_type
|
||||||
pending_type_name = nil
|
pending_type_name = nil
|
||||||
|
pending_comment = nil
|
||||||
end
|
end
|
||||||
in_struct = true
|
in_struct = true
|
||||||
elseif trimmed:match("^END_STRUCT%s*$") then
|
elseif trimmed:match("^END_STRUCT%s*$") then
|
||||||
@@ -226,9 +244,14 @@ function M.extract_types(content)
|
|||||||
if field_name then
|
if field_name then
|
||||||
local after_colon = line:match(":%s*(.+)")
|
local after_colon = line:match(":%s*(.+)")
|
||||||
local field_type = after_colon and extract_type_name(after_colon)
|
local field_type = after_colon and extract_type_name(after_colon)
|
||||||
|
local field_comment = line:match("//%s*(.+)$")
|
||||||
|
if not field_comment then
|
||||||
|
field_comment = line:match("%(%*(.-)%*%)")
|
||||||
|
end
|
||||||
table.insert(current_type.fields, {
|
table.insert(current_type.fields, {
|
||||||
name = field_name,
|
name = field_name,
|
||||||
type = field_type or "unknown",
|
type = field_type or "unknown",
|
||||||
|
comment = field_comment,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
elseif not in_struct and not pending_type_name then
|
elseif not in_struct and not pending_type_name then
|
||||||
|
|||||||
+118
-46
@@ -85,6 +85,13 @@ local function parse_scl_type_file(content)
|
|||||||
local current_type_name = nil
|
local current_type_name = nil
|
||||||
local pending_type_name = nil
|
local pending_type_name = nil
|
||||||
|
|
||||||
|
local in_fb = false
|
||||||
|
local fb_name = nil
|
||||||
|
local fb_inputs = {}
|
||||||
|
local fb_outputs = {}
|
||||||
|
local fb_inouts = {}
|
||||||
|
local current_fb_section = nil
|
||||||
|
|
||||||
content = content:gsub("^([\239\187\191]+)", "")
|
content = content:gsub("^([\239\187\191]+)", "")
|
||||||
|
|
||||||
local lines = {}
|
local lines = {}
|
||||||
@@ -93,58 +100,123 @@ local function parse_scl_type_file(content)
|
|||||||
for i, line in ipairs(lines) do
|
for i, line in ipairs(lines) do
|
||||||
local trimmed = line:gsub("^%s+", ""):gsub("%s+$", "")
|
local trimmed = line:gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
|
||||||
if trimmed:match("^TYPE%s") or trimmed:match('^TYPE"') or trimmed == "TYPE" then
|
local fb_match = trimmed:match('^FUNCTION_BLOCK%s+"([^"]+)"') or trimmed:match("^FUNCTION_BLOCK%s+(%w+)")
|
||||||
in_type = true
|
if fb_match then
|
||||||
in_struct = false
|
in_fb = true
|
||||||
current_type_name = nil
|
fb_name = fb_match
|
||||||
pending_type_name = nil
|
fb_inputs = {}
|
||||||
local type_name = trimmed:match('TYPE%s+"([^"]+)"') or trimmed:match("^TYPE%s+(%w+)")
|
fb_outputs = {}
|
||||||
if type_name then
|
fb_inouts = {}
|
||||||
pending_type_name = type_name
|
current_fb_section = nil
|
||||||
|
elseif in_fb and trimmed:match("^END_FUNCTION_BLOCK") then
|
||||||
|
if fb_name and (#fb_inputs > 0 or #fb_outputs > 0 or #fb_inouts > 0) then
|
||||||
|
types[fb_name] = {
|
||||||
|
name = fb_name,
|
||||||
|
kind = "function_block",
|
||||||
|
inputs = fb_inputs,
|
||||||
|
outputs = fb_outputs,
|
||||||
|
inouts = fb_inouts,
|
||||||
|
source = "scl_file"
|
||||||
|
}
|
||||||
end
|
end
|
||||||
in_struct = false
|
in_fb = false
|
||||||
current_type_name = nil
|
fb_name = nil
|
||||||
pending_type_name = nil
|
fb_inputs = {}
|
||||||
elseif trimmed:match("^END_TYPE") then
|
fb_outputs = {}
|
||||||
in_type = false
|
fb_inouts = {}
|
||||||
in_struct = false
|
current_fb_section = nil
|
||||||
current_type_name = nil
|
elseif in_fb then
|
||||||
pending_type_name = nil
|
if trimmed:match("^VAR_INPUT") then
|
||||||
elseif in_type then
|
current_fb_section = "input"
|
||||||
if trimmed:match("^END_STRUCT") or trimmed:match("^END_STRUCT;") then
|
elseif trimmed:match("^VAR_OUTPUT") then
|
||||||
|
current_fb_section = "output"
|
||||||
|
elseif trimmed:match("^VAR_IN_OUT") then
|
||||||
|
current_fb_section = "inout"
|
||||||
|
elseif trimmed:match("^VAR%s") or trimmed:match("^VAR%s*$") then
|
||||||
|
current_fb_section = nil
|
||||||
|
elseif trimmed:match("^VAR_TEMP") then
|
||||||
|
current_fb_section = nil
|
||||||
|
elseif trimmed:match("^END_VAR") then
|
||||||
|
current_fb_section = nil
|
||||||
|
elseif current_fb_section then
|
||||||
|
local field_name = line:match("^%s*(%w+)")
|
||||||
|
if field_name and not trimmed:match("^%(%*") then
|
||||||
|
local field_type = line:match(":%s*([^;]+)")
|
||||||
|
if field_type then
|
||||||
|
local attr_match = field_type:match("%{%s*[^%}]+%%s*%}%s*:%s*(.+)$")
|
||||||
|
if attr_match then
|
||||||
|
field_type = attr_match
|
||||||
|
end
|
||||||
|
field_type = field_type:gsub("%s*;.*$", "")
|
||||||
|
field_type = field_type:gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
local field_comment = line:match("//%s*(.+)$") or line:match("%(%*(.-)%*%)")
|
||||||
|
local field = { name = field_name, type = field_type, comment = field_comment }
|
||||||
|
if current_fb_section == "input" then
|
||||||
|
table.insert(fb_inputs, field)
|
||||||
|
elseif current_fb_section == "output" then
|
||||||
|
table.insert(fb_outputs, field)
|
||||||
|
elseif current_fb_section == "inout" then
|
||||||
|
table.insert(fb_inouts, field)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not in_fb then
|
||||||
|
if trimmed:match("^TYPE%s") or trimmed:match('^TYPE"') or trimmed == "TYPE" then
|
||||||
|
in_type = true
|
||||||
in_struct = false
|
in_struct = false
|
||||||
current_type_name = nil
|
current_type_name = nil
|
||||||
pending_type_name = nil
|
pending_type_name = nil
|
||||||
elseif trimmed:match("^STRUCT") then
|
local type_name = trimmed:match('TYPE%s+"([^"]+)"') or trimmed:match("^TYPE%s+(%w+)")
|
||||||
if pending_type_name then
|
|
||||||
current_type_name = pending_type_name
|
|
||||||
in_struct = true
|
|
||||||
types[pending_type_name] = { name = pending_type_name, kind = "struct", fields = {}, source = "data_types_folder" }
|
|
||||||
pending_type_name = nil
|
|
||||||
end
|
|
||||||
elseif not in_struct and trimmed:match("^%w+%s*:") and not trimmed:match("^STRUCT") then
|
|
||||||
local type_name = trimmed:match("^(%w+)%s*:")
|
|
||||||
if type_name then
|
if type_name then
|
||||||
local next_line = lines[i + 1]
|
pending_type_name = type_name
|
||||||
local next_trimmed = next_line and next_line:gsub("^%s+", ""):gsub("%s+$", "")
|
|
||||||
if next_trimmed and next_trimmed:match("^STRUCT") then
|
|
||||||
pending_type_name = type_name
|
|
||||||
else
|
|
||||||
pending_type_name = nil
|
|
||||||
current_type_name = nil
|
|
||||||
in_struct = false
|
|
||||||
local base_type = trimmed:match(":%s*([%w_]+)")
|
|
||||||
types[type_name] = { name = type_name, kind = "alias", base_type = base_type or "UNKNOWN", source = "data_types_folder" }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
elseif in_struct and current_type_name and types[current_type_name] then
|
in_struct = false
|
||||||
local field_name = line:match("^%s*(%w+)%s*:")
|
current_type_name = nil
|
||||||
if field_name and field_name ~= "END_STRUCT" then
|
pending_type_name = nil
|
||||||
local field_type = line:match(":%s*([%w_]+)")
|
elseif trimmed:match("^END_TYPE") then
|
||||||
table.insert(types[current_type_name].fields, {
|
in_type = false
|
||||||
name = field_name,
|
in_struct = false
|
||||||
type = field_type or "unknown",
|
current_type_name = nil
|
||||||
})
|
pending_type_name = nil
|
||||||
|
elseif in_type then
|
||||||
|
if trimmed:match("^END_STRUCT") or trimmed:match("^END_STRUCT;") then
|
||||||
|
in_struct = false
|
||||||
|
current_type_name = nil
|
||||||
|
pending_type_name = nil
|
||||||
|
elseif trimmed:match("^STRUCT") then
|
||||||
|
if pending_type_name then
|
||||||
|
current_type_name = pending_type_name
|
||||||
|
in_struct = true
|
||||||
|
types[pending_type_name] = { name = pending_type_name, kind = "struct", fields = {}, source = "data_types_folder" }
|
||||||
|
pending_type_name = nil
|
||||||
|
end
|
||||||
|
elseif not in_struct and trimmed:match("^%w+%s*:") and not trimmed:match("^STRUCT") then
|
||||||
|
local type_name = trimmed:match("^(%w+)%s*:")
|
||||||
|
if type_name then
|
||||||
|
local next_line = lines[i + 1]
|
||||||
|
local next_trimmed = next_line and next_line:gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
if next_trimmed and next_trimmed:match("^STRUCT") then
|
||||||
|
pending_type_name = type_name
|
||||||
|
else
|
||||||
|
pending_type_name = nil
|
||||||
|
current_type_name = nil
|
||||||
|
in_struct = false
|
||||||
|
local base_type = trimmed:match(":%s*([%w_]+)")
|
||||||
|
types[type_name] = { name = type_name, kind = "alias", base_type = base_type or "UNKNOWN", source = "data_types_folder" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif in_struct and current_type_name and types[current_type_name] then
|
||||||
|
local field_name = line:match("^%s*(%w+)%s*:")
|
||||||
|
if field_name and field_name ~= "END_STRUCT" then
|
||||||
|
local field_type = line:match(":%s*([%w_]+)")
|
||||||
|
table.insert(types[current_type_name].fields, {
|
||||||
|
name = field_name,
|
||||||
|
type = field_type or "unknown",
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user