diff --git a/.gitignore b/.gitignore index 146f185..0fa83a5 100644 --- a/.gitignore +++ b/.gitignore @@ -24,8 +24,6 @@ target/ # VisualStudio Code .vscode/* -!.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json -*.code-workspace diff --git a/README.md b/README.md index 22d872d..f7d77f6 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ # tree-sitter-metamodelica -An [open-source](OSMC-License.txt) MetaModelica ([Meta-Programming and Language -Modeling with MetaModelica -1.0 Appendix A](https://www.researchgate.net/publication/272070589_Meta-Programming_and_Language_Modeling_with_MetaModelica_10)) +An [open-source](OSMC-License.txt) MetaModelica ([MetaModelica 2.0](https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758)) grammar and highlighting-query for [tree-sitter](https://github.com/tree-sitter/tree-sitter). @@ -39,9 +37,8 @@ npx tree-sitter parse examples/Main.mo ## Highlighting -There is also a highlighting query included. Make sure that the [tree-sitter -per-user -configuration](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#per-user-configuration) +There is also a highlighting query included. Make sure that the +[tree-sitter per-user configuration](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#per-user-configuration) are pointing to the parent directory of `tree-sitter-metamodelica`. So if this directory is in `/home/USER/workspace/tree-sitter-metamodelica` add `/home/USER/workspace` to the parser directories: @@ -63,8 +60,7 @@ npx tree-sitter highlight examples/Main.mo ## Usage -Use [Web -Tree-sitter](https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/README.md) +Use [Web Tree-sitter](https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/README.md) `tree-sitter-metamodelica.wasm` in your application: ```typescript @@ -73,8 +69,8 @@ import * as Parser from 'web-tree-sitter' await Parser.init() const parser = new Parser -const Modelica = await Parser.Language.load(`tree-sitter-metamodelica.wasm`) -parser.setLanguage(Modelica) +const MetaModelica = await Parser.Language.load(`tree-sitter-metamodelica.wasm`) +parser.setLanguage(MetaModelica) ``` ## Current Status diff --git a/grammar.js b/grammar.js index aaa5425..263ef77 100644 --- a/grammar.js +++ b/grammar.js @@ -40,8 +40,23 @@ module.exports = grammar({ name: "metamodelica", + extras: $ => [ + $.COMMENT, + $.BLOCK_COMMENT, + $._SPACE + ], + + word: $ => $.IDENT, + rules: { - // TODO: add the actual grammar rules - source_file: $ => 'hello' + ...require("./rules/a1-classAndMainGrammar"), + ...require("./rules/a2-extends"), + ...require("./rules/a3-modification"), + ...require("./rules/a4-equations"), + ...require("./rules/a5-expressions"), + ...require("./rules/a6-metamodelicaExtensions"), + ...require("./rules/builtin"), + ...require("./rules/keywords"), + ...require("./rules/lexicalConventions"), } }); diff --git a/package.json b/package.json index c2907eb..1513e79 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,8 @@ "scope": "source.metamodelica", "file-types": [ "mo" - ] + ], + "highlights": "queries/highlights.scm" } ] } diff --git a/queries/highlights.scm b/queries/highlights.scm new file mode 100644 index 0000000..72f1470 --- /dev/null +++ b/queries/highlights.scm @@ -0,0 +1,177 @@ +;;;;; Highlights in the examples happen between these symbols: >...< +; List of available captures for tree-sitter highlights can be found in +; https://github.com/tree-sitter/tree-sitter/blob/dcb7acede4b31fedfc9d65b902fc95f6fe5ea099/cli/src/highlight.rs#L143-L171 + + +;;; Errors +(ERROR) @error ;; when something is placed wrong +; error has to be added to the config.json file to be shown correctly ;;"error": {"color": "red", "bold": true, "underline": true} + +;;; Strings +(STRING) @string ;; R(unit=>"Ohm"<) + +;;; Comments +[ + (BLOCK_COMMENT) ;; >/* comment */< + (COMMENT) ;; >// comment< +] +(string_comment (STRING) @comment) ;; model foo >"description"< + +;;; Numbers +[ + (UNSIGNED_INTEGER) ;; >220< + (UNSIGNED_REAL) ;; >3.14159< +] @number + +;;; Types +(type_specifier (name_path (IDENT) @type )) ;; >A<.>MyType< x +(T_REAL) @type.builtin ;; >Real< x +(T_INTEGER) @type.builtin ;; >Integer< x +(T_BOOLEAN) @type.builtin ;; >Boolean< x +(T_STRING) @type.builtin ;; >String< x +(T_LIST) @type.builtin ;; >List< x +(T_OPTION) @type.builtin ;; >Option< x +(T_TUPLE) @type.builtin ;; >Tuple< x + +;;; Variables +(declaration (IDENT) @variable.parameter) ;; Real >x< +(component_reference_function_call componentReference: (component_reference) @variable.parameter) ;; >x< + +;;; Function calls +(component_reference_function_call functionName: (component_reference) @function) + +;;; Classes +(class_definition (class_type class: (CLASS))(class_specifier (identifier) @module)) ;; class >A< end >A<; +(class_definition (class_type optimization: (OPTIMIZATION))(class_specifier (identifier) @module)) ;; optimization >A< end >A<; +(class_definition (class_type model: (MODEL))(class_specifier (identifier) @module)) ;; model >A< end >A<; +(class_definition (class_type record: (RECORD))(class_specifier (identifier) @type)) ;; record >R< end >R<; +(class_definition (class_type connector: (CONNECTOR))(class_specifier (identifier) @module)) ;; connector >C< end >C<; +(class_definition (class_type type: (TYPE))(class_specifier (identifier) @type)) ;; type >T< end >T<; +(class_definition (class_type package: (PACKAGE))(class_specifier (identifier) @module)) ;; package >A< end >A<; +(class_definition (class_type function: (FUNCTION))(class_specifier (identifier) @function)) ;; function >foo< end >foo<; +(class_definition (class_type uniontype: (UNIONTYPE))(class_specifier (identifier) @type)) ;; uniontype >T< end >T<; + +;;; Within +(within_clause namePath: (name_path (IDENT) @module)) ;; withing >PackageA<.>PackageB<; + +;;; Import +(explicit_import_name (IDENT) @module) ;; import >A< = PackageA; +(explicit_import_name namePath: (name_path (IDENT) @module)) ;; import B = >PackageA<.>PackageB<; +(implicit_import_name namePathStar: (name_path_star identifier: (IDENT) @module)) ;; import >PackageA<.>PackageB<.*; + +;;; Function Builtins +(EQUALITY) @function.builtin ;; >equality<(id = id2); +(FAILURE) @function.builtin ;; >failure<(equality(id = id2)); + +;; KEYWORDS +[ + (AS) + (BLOCK) + (BREAK) + (CASE) + (CLASS) + (CONNECT) + (CONNECTOR) + (CONSTANT) + (CONSTRAINEDBY) + (CONSTRAINT) + (DER) + (DISCRETE) + (EACH) + (ELSE) + (ELSEIF) + (ELSEWHEN) + (ENCAPSULATED) + (ENUMERATION) + (EQUALITY) + (EQUATION) + (EXPANDABLE) + (EXTENDS) + (EXTERNAL) + (FAILURE) + (FINAL) + (FINAL) + (FLOW) + (FOR) + (FUNCTION) + (GUARD) + (IF) + (IMPORT) + (INITIAL) + (INNER) + (LOCAL) + (LOOP) + (MATCH) + (MATCHCONTINUE) + (MODEL) + (OPERATOR) + (OPTIMIZATION) + (OVERLOAD) + (PACKAGE) + (PARAMETER) + (PARTIAL) + (PROTECTED) + (PUBLIC) + (RECORD) + (REDECLARE) + (REPLACEABLE) + (RETURN) + (STREAM) + (T_ALGORITHM) + (T_AND) + (T_ANNOTATION) + (T_END) + (T_FALSE) + (T_IN) + (T_INPUT) + (T_NOT) + (T_OR) + (T_OUTER) + (T_OUTPUT) + (T_TRUE) + (THEN) + (TRY) + (TYPE) + (UNIONTYPE) + (WHEN) + (WHILE) + (WITHIN) +] @keyword + +;; PUNCTUATION BRACKET +[ + (LBRACE) + (LBRACK) + (LPAR) + (RBRACE) + (RBRACK) + (RPAR) +] @punctuation.bracket + +;; OPERATOR +[ + (ALLWILD) + (ASSIGN) + (COLON) + (COLONCOLON) + (COMMA) + (DOT) + (EQEQ) + (EQUALS) + (GREATER) + (GREATEREQ) + (LESS) + (LESSEQ) + (LESSGT) + (MINUS_EW) + (MINUS) + (PLUS_EW) + (PLUS) + (POWER_EW) + (POWER) + (SLASH_EW) + (SLASH) + (STAR_EW) + (STAR) + (WILD) +] @operator diff --git a/rules/a1-classAndMainGrammar.js b/rules/a1-classAndMainGrammar.js new file mode 100644 index 0000000..e4d1f48 --- /dev/null +++ b/rules/a1-classAndMainGrammar.js @@ -0,0 +1,348 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.1 Class and Main Grammar Elements +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.1 Class and Main Grammar Elements +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + stored_definition: $ => seq( + optional( + field("withinClause", + seq( + $.within_clause, + $._SEMICOLON + ) + ) + ), + field("classDefinitionList", repeat($._class_definition_list)) + ), + + within_clause: $ => seq( + field("within", $.WITHIN), + optional(field("namePath", $.name_path)) + ), + + // TODO: Or use left? + _class_definition_list: $ => seq( + optional(field("final", $.FINAL)), + field("classDefinition", $.class_definition), + $._SEMICOLON, + ), + + class_definition: $ => seq( + optional(field("encapsulated", $.ENCAPSULATED)), + optional(field("partial", $.PARTIAL)), + field("classType", $.class_type), + field("classSpecifier", $.class_specifier) + ), + + class_type: $ => choice( + field("class", $.CLASS), + field("optimization", $.OPTIMIZATION), + field("model", $.MODEL), + field("record", $.RECORD), + field("block", $.BLOCK), + seq( + optional($.EXPANDABLE), + field("connector", $.CONNECTOR) + ), + field("type", $.TYPE), + field("package", $.PACKAGE), + field("function", $.FUNCTION), + field("uniontype", $.UNIONTYPE), + seq( + field("operator", $.OPERATOR), + optional(choice($.FUNCTION, $.RECORD)) + ) + ), + + // TODO: What is DER, CODE, EQUALITY, INITIAL? + identifier: $ => choice( + $.IDENT, + $.DER, + $.EQUALITY, + $.INITIAL + ), + + class_specifier: $ => choice( + seq( + field("identifier", $.identifier), + $._class_specifier2 + ), + seq( + $.EXTENDS, + field("identifier", $.identifier), + optional(field("classModification", $.class_modification)), + field("comment", optional($.string_comment)), + field("composition", optional($.composition)), + $.T_END, + field("endIdentifier", $.identifier) + ) + ), + + _class_specifier2: $ => choice( + seq( + optional( + field("identList", + seq( + $.LESS, + $._ident_list, + $.GREATER, + ) + ) + ), + field("comment", optional($.string_comment)), + field("composition", optional($.composition)), + $.T_END, + field("endIdentifier", $.identifier) + ), + seq( + $.EQUALS, + field("basePrefix", optional(alias($.type_prefix, $.base_prefix))), + field("typeSpecifier", $.type_specifier), + optional( + field("classModifier", $.class_modification) + ), + field("comment", optional($.comment)) + ), + seq( + $.EQUALS, + field("enumeration", $.enumeration) + ), + seq( + $.EQUALS, + field("pder", $.pder) + ), + seq( + $.EQUALS, + field("overloading", $.overloading) + ) + ), + + pder: $ => seq( + $.DER, + $.LPAR, + field("namePath", $.name_path), + $.COMMA, + $._ident_list, + $.RPAR, + field("comment", optional($.comment)) + ), + + _ident_list: $ => seq( + field("ident", $.IDENT), + repeat(seq( + $.COMMA, + field("ident", $.IDENT) + )) + ), + + overloading: $ => seq( + $.OVERLOAD, + $.LPAR, + $._name_list, + $.RPAR, + field("comment", optional($.comment)) + ), + + //base_prefix: $ => $.type_prefix, + + _name_list: $ => seq( + field("namePath", $.name_path), + repeat(seq( + $.COMMA, + field("namePath", $.name_path), + )) + ), + + enumeration: $ => seq( + $.ENUMERATION, + $.LPAR, + choice( + $._enum_list, + $.COLON + ), + $.RPAR, + field("comment", optional($.comment)) + ), + + _enum_list: $ => seq( + field("enumerationLiteral", $.enumeration_literal), + repeat(seq( + $.COMMA, + field("enumerationLiteral", $.enumeration_literal), + )) + ), + + enumeration_literal: $ => seq( + $.IDENT, + field("comment", optional($.comment)) + ), + + composition: $ => choice( + seq( + repeat1($._element_list), + optional($._composition2) + ), + seq( + repeat($._element_list), + $._composition2 + ) + ), + + _composition2: $ => choice( + choice( + repeat1( + choice( + $._public__element_list, + $._protected__element_list, + $.initial_equation_clause, + $.initial_algorithm_clause, + $.equation_clause, + $.constraint_clause, + $.algorithm_clause, + ) + ), + $.external_clause + ), + repeat1( + choice( + $._public__element_list, + $._protected__element_list, + $.initial_equation_clause, + $.initial_algorithm_clause, + $.equation_clause, + $.constraint_clause, + $.algorithm_clause + ) + ), + $.external_clause + ), + + external_clause: $ => seq( + $.EXTERNAL, + optional(field("languageSpecification", $.language_specification)), + optional( + seq( + optional(seq( + field("componentReference", $.component_reference), + $.EQUALS + )), + $.IDENT, + $.LPAR, + optional($._expression_list), + $.RPAR + ) + ), + optional($.annotation), + $._SEMICOLON, + optional(field("externalAnnotation", $.external_annotation)) + ), + + external_annotation: $ => seq( + field("externalAnnotation", $.annotation), + $._SEMICOLON + ), + + _public__element_list: $ => seq( + $.PUBLIC, + repeat($._element_list) + ), + + _protected__element_list: $ => seq( + $.PROTECTED, + repeat($._element_list) + ), + + language_specification: $ => seq( + $.STRING, + $._SEMICOLON + ), + + // _element_list could be empty list, use repeat(_element_list) everywhere + _element_list: $ => seq( + choice( + field("element", $.element), + field("annotation", $.annotation) + ), + $._SEMICOLON + ), + + element: $ => choice( + field("importClause", $.import_clause), + field("extendsClause", $.extends_clause), + seq( + optional($.REDECLARE), + optional($.FINAL), + optional($.INNER), + optional($.T_OUTER), + choice( + choice( + field("classDefinition", $.class_definition), + field("componentClause", $.component_clause) + ), + seq( + $.REPLACEABLE, + choice( + field("classDefinition", $.class_definition), + field("componentClause", $.component_clause) + ), + optional(field("constrainingClauseComment", $.constraining_clause_comment)) + ) + ) + ) + ), + + import_clause: $ => seq( + $.IMPORT, + choice( + field("explicitImportName", $.explicit_import_name), + field("implicitImportName", $.implicit_import_name) + ), + field("comment", optional($.comment)) + ), + + // TODO: What is CODE? + explicit_import_name: $ => seq( + $.IDENT, + $.EQUALS, + field("namePath", $.name_path) + ), + + implicit_import_name: $ => field("namePathStar", $.name_path_star) +}; diff --git a/rules/a2-extends.js b/rules/a2-extends.js new file mode 100644 index 0000000..34f97e6 --- /dev/null +++ b/rules/a2-extends.js @@ -0,0 +1,158 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.2 Extends +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.2 Extends +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + // Extends + extends_clause: $ => seq( + $.EXTENDS, + field("namePath", $.name_path), + optional(field("classModification", $.class_modification)), + optional(field("annotation", $.annotation)) + ), + + constraining_clause_comment: $ => seq( + field("constrainingClause", $.constraining_clause), + field("comment", optional($.comment)) + ), + + constraining_clause: $ => choice( + seq( + $.EXTENDS, + field("namePath", $.name_path), + optional(field("classModification", $.class_modification)) + ), + seq( + $.CONSTRAINEDBY, + field("namePath", $.name_path), + optional(field("classModification", $.class_modification)) + ) + ), + + // Component clause + component_clause: $ => seq( + field("typePrefix", optional($.type_prefix)), + field("typeSpecifier", $.type_specifier), + $._component_list, + ), + + // Can be empty, so it's this mess + type_prefix: $ => choice( + seq( + choice( + $.FLOW, + $.STREAM + ), + optional(choice( + $.DISCRETE, + $.PARAMETER, + $.CONSTANT + )), + optional(choice( + $.T_INPUT, + $.T_OUTPUT + )) + ), + seq( + choice( + $.DISCRETE, + $.PARAMETER, + $.CONSTANT + ), + optional(choice( + $.T_INPUT, + $.T_OUTPUT + )) + ), + choice( + $.T_INPUT, + $.T_OUTPUT + ) + ), + + type_specifier: $ => seq( + choice( + $._builtin_types, + field("namePath", $.name_path), + ), + optional(seq( + $.LESS, + $._type_specifier_list, + $.GREATER + )), + optional($.array_subscripts) + ), + + _type_specifier_list: $ => seq( + field("typeSpecifier", $.type_specifier), + optional(seq( + $.COMMA, + $._type_specifier_list + )) + ), + + _component_list: $ => seq( + field("componentDeclaration", $.component_declaration), + optional(seq( + $.COMMA, + $._component_list + )) + ), + + component_declaration: $ => seq( + field("declaration", $.declaration), + optional(field("conditionalAttribute", $.conditional_attribute)), + field("comment", optional($.comment)) + ), + + conditional_attribute: $ => seq( + $.IF, + field("expression", $.expression) + ), + + declaration: $ => seq( + choice( + field("identifier", $.IDENT), + $.OPERATOR + ), + optional($.array_subscripts), + optional(field("modification", $.modification)) + ) +}; diff --git a/rules/a3-modification.js b/rules/a3-modification.js new file mode 100644 index 0000000..beda633 --- /dev/null +++ b/rules/a3-modification.js @@ -0,0 +1,130 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY), + without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.3 Modification +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.3 Modification +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + modification: $ => choice( + seq( + field("classModification", $.class_modification), + optional(seq( + $.EQUALS, + field("expression", $.expression) + )) + ), + seq( + $.EQUALS, + field("expression", $.expression) + ), + seq( + $.ASSIGN, + field("expression", $.expression) + ) + ), + + class_modification: $ => seq( + $.LPAR, + optional($._argument_list), + $.RPAR + ), + + _argument_list: $ => seq( + field("argument", $.argument), + optional(seq( + $.COMMA, + $._argument_list + )) + ), + + argument: $ => choice( + $.element_modification_or_replaceable, + $.element_redeclaration + ), + + element_modification_or_replaceable: $ => seq( + optional($.EACH), + optional($.FINAL), + choice( + $.element_modification, + $.element_replaceable + ) + ), + + element_modification: $ => seq( + field("componentReference", $.component_reference), + optional(field("modification", $.modification)), + field("stringComment", optional($.string_comment)) + ), + + element_redeclaration: $ => seq( + $.REDECLARE, + optional($.EACH), + optional($.FINAL), + choice( + choice( + field("classDefinition", $.class_definition), + $.component_clause1 + ), + $.element_replaceable + ) + ), + + // TODO: What the heck is class_definition[final]? + // I just used class_definition + element_replaceable: $ => seq( + $.REPLACEABLE, + choice( + field("classDefinition", $.class_definition), + $.component_clause1 + ), + optional($.constraining_clause_comment) + ), + + component_clause1: $ => seq( + field("basePrefix", optional(alias($.type_prefix, $.base_prefix))), + field("typeSpecifier", $.type_specifier), + $.component_declaration1 + ), + + component_declaration1: $ => seq( + field("declaration", $.declaration), + field("comment", optional($.comment)) + ) +}; diff --git a/rules/a4-equations.js b/rules/a4-equations.js new file mode 100644 index 0000000..558a794 --- /dev/null +++ b/rules/a4-equations.js @@ -0,0 +1,368 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY), + without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.4 Equations +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.4 Equations +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + // TODO: Do look ahead + initial_equation_clause: $ => prec.left(seq( + $.INITIAL, + $.EQUATION, + repeat($._equation_annotation_list) + )), + + // TODO: Do look ahead + equation_clause: $ => prec.left(seq( + $.EQUATION, + repeat($._equation_annotation_list) + )), + + // TODO: Ask Adrian if this is correct with LA of _constraint_annotation_list + // TODO: Do look ahead + constraint_clause: $ => prec.left(seq( + $.CONSTRAINT, + repeat($._constraint_annotation_list) + )), + + // TODO: Do look ahead + _equation_annotation_list: $ => choice( + seq( + $.equation, + $._SEMICOLON + ), + seq( + $.annotation, + $._SEMICOLON + ) + ), + + // TODO: What the heck is `{ ... }?` ? + // TODO: Do look ahead + _constraint_annotation_list: $ => choice( + seq( + $.equation, + $._SEMICOLON + ), + seq( + $.annotation, + $._SEMICOLON + ) + ), + + algorithm_clause: $ => prec.left(seq( + $.T_ALGORITHM, + repeat($._algorithm_annotation_list) + )), + + // TODO: Do look ahead + initial_algorithm_clause: $ => prec.left(seq( + $.INITIAL, + $.T_ALGORITHM, + repeat($._algorithm_annotation_list) + )), + + // TODO: Do look ahead + _algorithm_annotation_list: $ => choice( + seq( + $.algorithm, + $._SEMICOLON + ), + seq( + $.annotation, + $._SEMICOLON + ) + ), + + // TODO: Recursive equation + equation: $ => seq( + choice( + $._equality_or_noretcall_equation, + $.conditional_equation_e, + $.for_clause_e, + $.connect_clause, + $.when_clause_e, + seq( + $.FAILURE, + $.LPAR, + field("equation", $.equation), + $.RPAR + ), + seq( + $.EQUALITY, + $.LPAR, + field("leftExpression", $.expression), + $.EQUALS, + field("rightExpression", $.expression), + $.RPAR + ) + ), + optional($.comment) + ), + + constraint: $ => seq( + choice( + $._equality_or_noretcall_equation, + $.conditional_equation_e, + $.for_clause_e, + $.connect_clause, + $.when_clause_e, + seq( + $.FAILURE, + $.LPAR, + $.equation, + $.RPAR + ), + seq( + $.EQUALITY, + $.LPAR, + $.expression, + $.EQUALS, + $.expression, + $.RPAR + ) + ), + optional($.comment) + ), + + // TODO: recursion + algorithm: $ => seq( + choice( + $.assign_clause_a, + $.conditional_equation_a, + $.for_clause_a, + // TODO: add parfor_clause_a + //$.parfor_clause_a, + $.while_clause, + $.try_clause, + $.when_clause_a, + $.BREAK, + $.RETURN, + // TODO: add CONTINUE + // $.CONTINUE, + seq( + $.FAILURE, + $.LPAR, + $.algorithm, + $.RPAR + ), + seq( + $.EQUALITY, + $.LPAR, + $.expression, + $.ASSIGN, + $.expression, + $.RPAR + ) + ), + optional($.comment) + ), + + // TODO: What should `( ASSIGN | eq = EQUALS )` mean? + assign_clause_a: $ => seq( + $.simple_expression, + optional( + seq( + choice( + $.ASSIGN, + $.EQUALS + ), + $.expression + )) + ), + + // TODO: Do look ahead + _equality_or_noretcall_equation: $ => choice( + field("equalityEquation", seq( + $.simple_expression, + choice( + $.EQUALS, + $.ASSIGN + ), + $.expression + )), + field("noReturnCallEquation", seq( + $.component_reference, + $.function_call + )) + ), + + conditional_equation_e: $ => seq( + $.IF, + $.expression, + $.THEN, + repeat($._equation_list), + repeat($.equation_elseif), + optional(seq( + $.ELSE, + repeat($._equation_list) + )), + $.T_END, + $.IF + ), + + conditional_equation_a: $ => seq( + $.IF, + $.expression, + $.THEN, + repeat($._algorithm_list), + repeat($.algorithm_elseif), + optional(seq( + $.ELSE, + repeat($._algorithm_list) + )), + $.T_END, + $.IF + ), + + for_clause_e: $ => seq( + $.FOR, + $.for_indices, + $.LOOP, + repeat($._equation_list), + $.T_END, + $.FOR + ), + + for_clause_a: $ => seq( + $.FOR, + $.for_indices, + $.LOOP, + repeat($._algorithm_list), + $.T_END, + $.FOR + ), + + while_clause: $ => seq( + $.WHILE, + $.expression, + $.LOOP, + repeat($._algorithm_list), + $.T_END, + $.WHILE + ), + + when_clause_e: $ => seq( + $.WHEN, + $.expression, + $.THEN, + repeat($._equation_list), + repeat($.else_when_e), + $.T_END, + $.WHEN + ), + + //_else_when_e_list: $ => $.else_when_e, + + // TODO: left or right? + else_when_e: $ => prec.left(seq( + $.ELSEWHEN, + $.expression, + $.THEN, + repeat($._equation_list) + )), + + when_clause_a: $ => seq( + $.WHEN, + $.expression, + $.THEN, + repeat($._algorithm_list), + repeat($.else_when_a), + $.T_END, + $.WHEN + ), + + //_else_when_a_list: $ => $.else_when_a, + + // TODO: left or right? + else_when_a: $ => prec.left(seq( + $.ELSEWHEN, + $.expression, + $.THEN, + repeat($._algorithm_list) + )), + + //_equation_elseif_list: $ => $.equation_elseif, + + // TODO: left or right? + equation_elseif: $ => prec.left(seq( + $.ELSEIF, + $.expression, + $.THEN, + repeat($._equation_list) + )), + + //_algorithm_elseif_list: $ => $.algorithm_elseif, + + // TODO: left or right? + algorithm_elseif: $ => prec.left(seq( + $.ELSEIF, + $.expression, + $.THEN, + repeat($._algorithm_list) + )), + + // TODO: Do look ahead + _equation_list_then: $ => seq( + $.equation, + $._SEMICOLON + ), + + // TODO: Do look ahead + // TODO: How to distinguish from _equation_list_then? Use alias and remove + _equation_list: $ => seq( + $.equation, + $._SEMICOLON + ), + + // TODO: Do look ahead + _algorithm_list: $ => seq( + $.algorithm, + $._SEMICOLON, + ), + + connect_clause: $ => seq( + $.CONNECT, + $.LPAR, + $.component_reference, + $.COMMA, + $.component_reference, + $.RPAR + ) +}; diff --git a/rules/a5-expressions.js b/rules/a5-expressions.js new file mode 100644 index 0000000..da69e4a --- /dev/null +++ b/rules/a5-expressions.js @@ -0,0 +1,449 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY), + without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.5 Expressions +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.5 Expressions +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + expression: $ => choice( + $.if_expression, + $.simple_expression, + $.part_eval_function_expression, + $.match_expression + ), + + part_eval_function_expression: $ => seq( + $.FUNCTION, + $.component_reference, + $.function_call + ), + + if_expression: $ => seq( + $.IF, + $.expression, + $.THEN, + $.expression, + repeat($.elseif_expression), + $.ELSE, + $.expression + ), + + //elseif__expression_list + + elseif_expression: $ => seq( + $.ELSEIF, + $.expression, + $.THEN, + $.expression + ), + + for_indices: $ => seq( + $.for_index, + optional(seq( + $.COMMA, + $.for_indices + )) + ), + + for_index: $ => seq( + $.IDENT, + optional(seq( + optional(seq( + $.GUARD, + $.expression + )), + $.T_IN, + $.expression + )) + ), + + // TODO: recursion? + simple_expression: $ => choice( + seq( + $._simple_expr, + optional(seq( + $.COLONCOLON, + $.simple_expression + )) + ), + seq( + $.IDENT, + $.AS, + $.simple_expression + ) + ), + + _simple_expr: $ => seq( + $._logical_expression, + optional(seq( + $.COLON, + $._logical_expression + )), + optional(seq( + $.COLON, + $._logical_expression + )) + ), + + // TODO: What is `( )*` ? + _logical_expression: $ => seq( + $._logical_term, + repeat(seq( + $.T_OR, + $._logical_term + )) + ), + + _logical_term: $ => seq( + $._logical_factor, + repeat(seq( + $.T_AND, + $._logical_factor + )) + ), + + _logical_factor: $ => seq( + optional($.T_NOT), + $._relation + ), + + _relation: $ => seq( + $._arithmetic_expression, + optional(seq( + choice( + $.LESS, + $.LESSEQ, + $.GREATER, + $.GREATEREQ, + $.EQEQ, + $.LESSGT + ), + $._arithmetic_expression + )) + ), + + _arithmetic_expression: $ => seq( + $._unary_arithmetic_expression, + repeat(seq( + choice( + $.PLUS, + $.MINUS, + $.PLUS_EW, + $.MINUS_EW + ), + $._term + )) + ), + + _unary_arithmetic_expression: $ => choice( + seq( + $.PLUS, + $._term + ), + seq( + $.MINUS, + $._term + ), + seq( + $.PLUS_EW, + $._term + ), + seq( + $.MINUS_EW, + $._term + ), + $._term + ), + + _term: $ => seq( + $._factor, + repeat(seq( + choice( + $.STAR, + $.SLASH, + $.STAR_EW, + $.SLASH_EW + ), + $._factor + )) + ), + + _factor: $ => seq( + $._primary, + optional(seq( + choice( + $.POWER, + $.POWER_EW + ), + $._primary + )) + ), + + _primary: $ => prec.left(choice( + $.UNSIGNED_INTEGER, + $.UNSIGNED_REAL, + $.STRING, + $.T_FALSE, + $.T_TRUE, + $.component_reference_function_call, + seq( + $.DER, + $.function_call + ), + seq( + $.LPAR, + $._output_expression_list + ), + seq( + $.LBRACK, + $._matrix_expression_list, + $.RBRACK + ), + seq( + $.LBRACE, + $._for_or_expression_list, + $.RBRACE + ), + $.T_END + )), + + // TODO: recursive + _matrix_expression_list: $ => seq( + $._expression_list, + optional(seq( + $._SEMICOLON, + $._matrix_expression_list + )) + ), + + component_reference_function_call: $ => prec(2,choice( + seq( + field("functionName", $.component_reference), + $.function_call + ), + field("componentReference", $.component_reference), + seq( + $.INITIAL, + $.LPAR, + $.RPAR + ) + )), + + name_path: $ => seq( + optional($.DOT), + $.IDENT, + repeat(seq( + $.DOT, + $.IDENT + )) + ), + + name_path_star: $ => seq( + optional($.DOT), + $._name_path_star2 + ), + + // TODO: Fix look ahead + + _name_path_star2: $ => choice( + seq( + field("identifier", $.IDENT), + optional($.STAR_EW) + ), + seq( + field("identifier", $.IDENT), + $.DOT, + $._name_path_star2 + ), + // Modification for import like `import A.{foo,bar}` + seq( + $.LBRACE, + optional($.IDENT), + repeat(seq( + $.COMMA, + $.IDENT + )), + $.RBRACE + ) + ), + + component_reference: $ => choice( + seq( + optional($.DOT), + $._component_reference2 + ), + $.ALLWILD, + $.WILD + ), + + // TODO: recursion + _component_reference2: $ => seq( + choice( + $.IDENT, + $.OPERATOR + ), + optional($.array_subscripts), + optional(seq( + $.DOT, + $._component_reference2 + )) + ), + + //TODO: Can function_arguments be optional? + function_call: $ => seq( + $.LPAR, + optional($.function_arguments), + $.RPAR + ), + + // Not sure, but _for_or_expression_list should be optional + function_arguments: $ => choice( + seq( + $._for_or_expression_list, + optional($._named_arguments) + ), + $._named_arguments + ), + + // TODO: Do look ahead + _for_or_expression_list: $ => seq( + $.expression, + optional(choice( + repeat1(seq( + $.COMMA, + $.expression + )), + seq( + $.FOR, + $.for_indices + ) + )), + ), + + //_for_or_expression_list2 + + _named_arguments: $ => seq( + $.named_argument, + repeat(seq( + $.COMMA, + $.named_argument + )) + ), + + named_argument: $ => seq( + choice( + $.IDENT, + $.OPERATOR + ), + $.EQUALS, + $.expression + ), + + // TODO: recursion + _output_expression_list: $ => choice( + $.RPAR, + seq( + $.COMMA, + $._output_expression_list + ), + seq( + $.expression, + choice( + seq( + $.COMMA, + $._output_expression_list + ), + $.RPAR + ) + ) + ), + + _expression_list: $ => seq( + $.expression, + optional(seq( + $.COMMA, + $._expression_list + )) + ), + + array_subscripts: $ => seq( + $.LBRACK, + $._subscript_list, + $.RBRACK + ), + + // TODO: Recursion + _subscript_list: $ => seq( + $.subscript, + optional(seq( + $.COMMA, + $._subscript_list + )) + ), + + subscript: $ => choice( + $.expression, + $.COLON + ), + + comment: $ => choice( + seq( + $.string_comment, + optional($.annotation) + ), + seq( + optional($.string_comment), + $.annotation + ) + ), + + // TODO: What is `(PLUS s2 = STRING)*`? + string_comment: $ => seq( + $.STRING, + repeat(seq( + $.PLUS, + $.STRING + )) + ), + + annotation: $ => seq( + $.T_ANNOTATION, + $.class_modification + ) +}; diff --git a/rules/a6-metamodelicaExtensions.js b/rules/a6-metamodelicaExtensions.js new file mode 100644 index 0000000..5148bc5 --- /dev/null +++ b/rules/a6-metamodelicaExtensions.js @@ -0,0 +1,122 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY), + without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.6 MetaModelica Extensions +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Appendix A, section A.6 MetaModelica Extensions +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + match_expression: $ => choice( + seq( + $.MATCHCONTINUE, + $.expression, + optional($.string_comment), + optional($.local_clause), + $.cases, + $.T_END, + $.MATCHCONTINUE + ), + seq( + $.MATCH, + $.expression, + optional($.string_comment), + optional($.local_clause), + $.cases, + $.T_END, + $.MATCH + ) + ), + + // TODO: el=_element_list ?? + local_clause: $ => seq( + $.LOCAL, + repeat($._element_list) + ), + + cases: $ => seq( + field("case", repeat1($.onecase)), + field("elsecase", optional($.elsecase)) + ), + + elsecase: $ => seq( + $.ELSE, + optional(seq( + optional($.string_comment), + optional(seq( + $.EQUATION, + repeat($._equation_list_then) + )), + $.THEN + )), + $.expression, + $._SEMICOLON + ), + + onecase: $ => seq( + $.CASE, + $._pattern, + optional($.string_comment), + choice( + optional(seq( + $.EQUATION, + repeat($._equation_list_then) + )), + optional(seq( + $.ALGORITHM, + repeat($._algorithm_annotation_list) + )), + ), + $.THEN, + $.expression, + $._SEMICOLON + ), + + // TODO: e=expression ??? + _pattern: $ => seq( + $.expression + ), + + try_clause: $ => seq( + $.TRY, + repeat($._algorithm_list), + $.ELSE, + repeat($._algorithm_list), + $.T_END, + $.TRY + ), +}; diff --git a/rules/builtin.js b/rules/builtin.js new file mode 100644 index 0000000..dc471fb --- /dev/null +++ b/rules/builtin.js @@ -0,0 +1,67 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// Buildin types and functions +// +// From Towards Modelica 4 Meta-Programming and Language Modeling with MetaModelica 2.0 +// Section 5.1.2 Predefined Types and Type Constructors +// https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A418188&dswid=-9758 + +module.exports = { + + _builtin_types: $ => choice( + $.T_REAL, + $.T_INTEGER, + $.T_BOOLEAN, + $.T_STRING, + $.T_LIST, + $.T_OPTION, + $.T_TUPLE, + $.T_SEQUENCE, + $.T_ANY, + ), + + // Types + T_REAL: $ => "Real", + T_INTEGER: $ => "Integer", + T_BOOLEAN: $ => "Boolean", + T_STRING: $ => "String", + + T_LIST: $ => "List", + T_OPTION: $ => "Option", + T_TUPLE: $ => "Tuple", + T_SEQUENCE: $ => "Sequence", + T_ANY: $ => "Any", +}; diff --git a/rules/keywords.js b/rules/keywords.js new file mode 100644 index 0000000..9850f0e --- /dev/null +++ b/rules/keywords.js @@ -0,0 +1,145 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// Keywords and special characters + +module.exports = { + // Reserved characters + ALLWILD: $ => "__", + ASSIGN: $ => ":=", + COLON: $ => ":", + COLONCOLON: $ => "::", + COMMA: $ => ",", + DOT: $ => ".", + EQEQ: $ => "==", + EQUALS: $ => "=", + GREATER: $ => ">", + GREATEREQ: $ => ">=", + LBRACE: $ => "{", + LBRACK: $ => "[", + LESS: $ => "<", + LESSEQ: $ => "<=", + LESSGT: $ => "<>", + LPAR: $ => "(", + MINUS_EW: $ => ".-", + MINUS: $ => "-", + PLUS_EW: $ => ".+", + PLUS: $ => "+", + POWER_EW: $ => ".^", + POWER: $ => "^", + RBRACE: $ => "}", + RBRACK: $ => "]", + RPAR: $ => ")", + _SEMICOLON: $ => ";", + SLASH_EW: $ => "./", + SLASH: $ => "/", + STAR_EW: $ => ".*", + STAR: $ => "*", + WILD: $ => "_", + + // keywords + ALGORITHM: $ => "algorithm", + AS: $ => "as", + BLOCK: $ => "block", + BREAK: $ => "break", + CASE: $ => "case", + CLASS: $ => "class", + CONNECT: $ => "connect", + CONNECTOR: $ => "connector", + CONSTANT: $ => "constant", + CONSTRAINEDBY: $ => "constrainedby", + CONSTRAINT: $ => "constraint", + DER: $ => "der", + DISCRETE: $ => "discrete", + EACH: $ => "each", + ELSE: $ => "else", + ELSEIF: $ => "elseif", + ELSEWHEN: $ => "elsewhen", + ENCAPSULATED: $ => "encapsulated", + ENUMERATION: $ => "enumeration", + EQUALITY: $ => "equality", + EQUATION: $ => "equation", + EXPANDABLE: $ => "expandable", + EXTENDS: $ => "extends", + EXTERNAL: $ => "external", + FAILURE: $ => "failure", + FINAL: $ => "final", + FINAL: $ => "final", + FLOW: $ => "flow", + FOR: $ => "for", + FUNCTION: $ => "function", + GUARD: $ => "guard", + IF: $ => "if", + IMPORT: $ => "import", + INITIAL: $ => "initial", + INNER: $ => "inner", + LOCAL: $ => "local", + LOOP: $ => "loop", + MATCH: $ => "match", + MATCHCONTINUE: $ => "matchcontinue", + MODEL: $ => "model", + OPERATOR: $ => "operator", + OPTIMIZATION: $ => "optimization", + OVERLOAD: $ => "overload", + PACKAGE: $ => "package", + PARAMETER: $ => "parameter", + PARTIAL: $ => "partial", + PROTECTED: $ => "protected", + PUBLIC: $ => "public", + RECORD: $ => "record", + REDECLARE: $ => "redeclare", + REPLACEABLE: $ => "replaceable", + RETURN: $ => "return", + STREAM: $ => "stream", + T_ALGORITHM: $ => "algorithm", + T_AND: $ => "and", + T_ANNOTATION: $ => "annotation", + T_END: $ => "end", + T_FALSE: $ => "false", + T_IN: $ => "in", + T_INPUT: $ => "input", + T_NOT: $ => "not", + T_OR: $ => "or", + T_OUTER: $ => "outer", + T_OUTPUT: $ => "output", + T_TRUE: $ => "true", + THEN: $ => "then", + TRY: $ => "try", + TYPE: $ => "type", + UNIONTYPE: $ => "uniontype", + WHEN: $ => "when", + WHILE: $ => "while", + WITHIN: $ => "within", +} diff --git a/rules/lexicalConventions.js b/rules/lexicalConventions.js new file mode 100644 index 0000000..6e08065 --- /dev/null +++ b/rules/lexicalConventions.js @@ -0,0 +1,167 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2024, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the OSMC (Open Source Modelica Consortium) + * Public License (OSMC-PL) are obtained from OSMC, either from the above + * address, from the URLs: + * http://www.openmodelica.org or + * https://github.com/OpenModelica/ or + * http://www.ida.liu.se/projects/OpenModelica, + * and in the OpenModelica distribution. + * + * GNU AGPL version 3 is obtained from: + * https://www.gnu.org/licenses/licenses.html#GPL + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +// A.0 Lexical conventions +// +// From Modelica 3.7 Language Specification +// Appendix A, section A.1 Lexical conventions +// https://specification.modelica.org/master/modelica-concrete-syntax.html + +module.exports = { + // TODO: Remove or use this one + /* + IDENT: $ => token( + choice( + // NON-DIGIT { DIGIT | NON-DIGIT } + seq( + /[_a-zA-Z]/, + repeat( + /[_a-zA-Z0-9]/, + ) + ), + // Q_IDENT + seq( + "'", + repeat( + choice( + // Q_CHAR + /[_a-zA-Z]/, + /[0-9]/, + "!", "#", "$", "%", "&", "(", ")", "*", "+", ",", "-", ".", "/", + ":", ";", "<", ">", "=", "?", "@", "[", "]", "^", "{", "}", "|", + "~", " ", + "\"", + // S_ESCAPE + "\\'", "\\\"", "\\?", "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", + "\\t", "\\v", + ) + ), + "'" + ) + ) + ), + */ + + IDENT: $ => token(choice( + seq(/[_a-zA-Z]/, repeat(choice(/[0-9]/, /[_a-zA-Z]/))), + seq("’", repeat(choice( + /[_a-zA-Z]/, /[0-9]/, "!", "#", "$", "%", "&", "(", ")", + "*", "+", ",", "-", ".", "/", ":", ";", "<", ">", "=", + "?", "@", "[", "]", "^", "{", "}", "|", "~", " ", "\"", + seq("\\", choice("’", "'", "\"", "?", "\\", "a", "b", "f", "n", "r", "t", "v")))), "’"))), + + STRING: $ => token( + seq( + "\"", + repeat( + choice( + // S_CHAR + /[^"\\]/, + // S_ESCAPE + "\\'", "\\\"", "\\?", "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", + "\\t", "\\v", + ) + ), + "\"" + ) + ), + + UNSIGNED_INTEGER: $ => token( + repeat1( + /[0-9]/ + ) + ), + + UNSIGNED_REAL: $ => token( + choice( + seq( + // UNSIGNED_INTEGER, + /[0-9]+/, + ".", + optional( + // UNSIGNED_INTEGER + /[0-9]+/ + ) + ), + seq( + // UNSIGNED_INTEGER + /[0-9]+/, + optional( + seq( + ".", + optional( + // UNSIGNED_INTEGER + /[0-9]+/ + ) + ) + ), + choice("e", "E"), + optional(choice("+", "-")), + // UNSIGNED_INTEGER + /[0-9]+/ + ), + seq( + ".", + // UNSIGNED_INTEGER + /[0-9]+/, + optional( + seq( + choice("e", "E"), + optional(choice("+", "-")), + // UNSIGNED_INTEGER + /[0-9]+/ + ) + ) + ) + ) + ), + + BLOCK_COMMENT: $ => token( + seq( + "/*", + /[^*]*\*+([^/*][^*]*\*+)*/, + "/" + ) + ), + + COMMENT: $ => token( + seq( + "//", + /[^\r\n]*/ + ) + ), + + _SPACE: $ => /\s+/, +}; diff --git a/test/corpus/a1-1_stored_definition_within.txt b/test/corpus/a1-1_stored_definition_within.txt new file mode 100644 index 0000000..63b7452 --- /dev/null +++ b/test/corpus/a1-1_stored_definition_within.txt @@ -0,0 +1,11 @@ +============================== +A.2 Stored Definition – Within +============================== + +within; + +--- + +(stored_definition + (within_clause + (WITHIN))) diff --git a/test/corpus/a1-2_stored_definition_within2.txt b/test/corpus/a1-2_stored_definition_within2.txt new file mode 100644 index 0000000..c04aa1f --- /dev/null +++ b/test/corpus/a1-2_stored_definition_within2.txt @@ -0,0 +1,13 @@ +=============================== +A.1 Stored Definition – Within2 +=============================== + +within a091234; + +--- + +(stored_definition + (within_clause + (WITHIN) + (name_path + (IDENT)))) diff --git a/test/corpus/a1-3_stored_definition_within3.txt b/test/corpus/a1-3_stored_definition_within3.txt new file mode 100644 index 0000000..9c9a2f0 --- /dev/null +++ b/test/corpus/a1-3_stored_definition_within3.txt @@ -0,0 +1,19 @@ +=============================== +A.1 Stored Definition – Within3 +=============================== + +within PackageA.PackageB.PackageC.PackageD; + +--- + +(stored_definition + (within_clause + (WITHIN) + (name_path + (IDENT) + (DOT) + (IDENT) + (DOT) + (IDENT) + (DOT) + (IDENT)))) diff --git a/test/corpus/a1-4_class_definition_list.txt b/test/corpus/a1-4_class_definition_list.txt new file mode 100644 index 0000000..2211bef --- /dev/null +++ b/test/corpus/a1-4_class_definition_list.txt @@ -0,0 +1,55 @@ +========================= +A.1 class_definition_list +========================= + +package PackageA +end PackageA; + +function foo +end foo; + +model MyModel +end MyModel; + +class C +end C; + +--- + +(stored_definition + (class_definition + (class_type + (PACKAGE)) + (class_specifier + (identifier + (IDENT)) + (T_END) + (identifier + (IDENT)))) + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (T_END) + (identifier + (IDENT)))) + (class_definition + (class_type + (MODEL)) + (class_specifier + (identifier + (IDENT)) + (T_END) + (identifier + (IDENT)))) + (class_definition + (class_type + (CLASS)) + (class_specifier + (identifier + (IDENT)) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a1-5_class_definition_function1.txt b/test/corpus/a1-5_class_definition_function1.txt new file mode 100644 index 0000000..4b1341d --- /dev/null +++ b/test/corpus/a1-5_class_definition_function1.txt @@ -0,0 +1,40 @@ +=============================== +A.1 class_definition function 1 +=============================== + + +function foo + Real x; + A.MyType y; +end foo; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_specifier + (T_REAL)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (name_path + (IDENT) + (DOT) + (IDENT))) + (component_declaration + (declaration + (IDENT)))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a1-6_class_definition_function2.txt b/test/corpus/a1-6_class_definition_function2.txt new file mode 100644 index 0000000..d419782 --- /dev/null +++ b/test/corpus/a1-6_class_definition_function2.txt @@ -0,0 +1,46 @@ +=============================== +A.1 class_definition function 2 +=============================== + +function foo + "foo documentation" + discrete input Type inx; + output Type x; +end foo; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (string_comment + (STRING)) + (composition + (element + (component_clause + (type_prefix + (DISCRETE) + (T_INPUT)) + (type_specifier + (name_path + (IDENT))) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_OUTPUT)) + (type_specifier + (name_path + (IDENT))) + (component_declaration + (declaration + (IDENT)))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a2-1_type_specifier.txt b/test/corpus/a2-1_type_specifier.txt new file mode 100644 index 0000000..aed3b26 --- /dev/null +++ b/test/corpus/a2-1_type_specifier.txt @@ -0,0 +1,153 @@ +================== +A.2 type_specifier +================== + +function foo + Real x1; + Integer x2; + Boolean x3; + String x4; + MyType x5; + List x6; + List x7; + Option x8; + Option x9; + Tuple x10; + Tuple x11; +end foo; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_specifier + (T_REAL)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_INTEGER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_BOOLEAN)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (name_path + (IDENT))) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_LIST) + (LESS) + (type_specifier + (T_REAL)) + (GREATER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_LIST) + (LESS) + (type_specifier + (name_path + (IDENT))) + (GREATER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_OPTION) + (LESS) + (type_specifier + (T_REAL)) + (GREATER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_OPTION) + (LESS) + (type_specifier + (name_path + (IDENT))) + (GREATER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_TUPLE) + (LESS) + (type_specifier + (name_path + (IDENT))) + (COMMA) + (type_specifier + (name_path + (IDENT))) + (COMMA) + (type_specifier + (name_path + (IDENT))) + (GREATER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_TUPLE) + (LESS) + (type_specifier + (name_path + (IDENT))) + (COMMA) + (type_specifier + (name_path + (IDENT))) + (COMMA) + (type_specifier + (name_path + (IDENT))) + (GREATER)) + (component_declaration + (declaration + (IDENT)))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a4-1_algorithm_clause.txt b/test/corpus/a4-1_algorithm_clause.txt new file mode 100644 index 0000000..29b3b77 --- /dev/null +++ b/test/corpus/a4-1_algorithm_clause.txt @@ -0,0 +1,23 @@ +================================ +A.4 algorithm_clause algorithm 1 +================================ + +function sum +algorithm +end sum; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (algorithm_clause + (T_ALGORITHM))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a4-2_algorithm_clause2.txt b/test/corpus/a4-2_algorithm_clause2.txt new file mode 100644 index 0000000..1bcef83 --- /dev/null +++ b/test/corpus/a4-2_algorithm_clause2.txt @@ -0,0 +1,70 @@ +================================ +A.4 algorithm_clause algorithm 2 +================================ + +function sum + input Integer a; + input Integer b; + output Integer sum; +algorithm + sum := a + b; +end sum; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_INTEGER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_INTEGER)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_OUTPUT)) + (type_specifier + (T_INTEGER)) + (component_declaration + (declaration + (IDENT))))) + (algorithm_clause + (T_ALGORITHM) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (ASSIGN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))) + (PLUS) + (component_reference_function_call + (component_reference + (IDENT))))))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a6-1_match_expression1.txt b/test/corpus/a6-1_match_expression1.txt new file mode 100644 index 0000000..11a8fff --- /dev/null +++ b/test/corpus/a6-1_match_expression1.txt @@ -0,0 +1,147 @@ +====================== +A.6 match_expression 1 +====================== + + +encapsulated package A + +protected function foo + input B.UnionType inx; + input String res; + output String res_1; +algorithm + res_1 := matchcontinue (inx,res) + case(B.Type(name = "bar"),_) + then "bar"; + else res; + end matchcontinue; +end foo; + +end A; + +--- + +(stored_definition + (class_definition + (ENCAPSULATED) + (class_type + (PACKAGE)) + (class_specifier + (identifier + (IDENT)) + (composition + (PROTECTED) + (element + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (name_path + (IDENT) + (DOT) + (IDENT))) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_OUTPUT)) + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))))) + (algorithm_clause + (T_ALGORITHM) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (ASSIGN) + (expression + (match_expression + (MATCHCONTINUE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (RPAR))) + (cases + (onecase + (CASE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (function_arguments + (named_argument + (IDENT) + (EQUALS) + (expression + (simple_expression + (STRING))))) + (RPAR))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (WILD))))) + (RPAR))) + (THEN) + (expression + (simple_expression + (STRING)))) + (elsecase + (ELSE) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (T_END) + (MATCHCONTINUE))))))) + (T_END) + (identifier + (IDENT)))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a6-2_match_expression2.txt b/test/corpus/a6-2_match_expression2.txt new file mode 100644 index 0000000..84eeaad --- /dev/null +++ b/test/corpus/a6-2_match_expression2.txt @@ -0,0 +1,188 @@ +====================== +A.6 match_expression 2 +====================== + +function makeDebugResult + input Flags.DebugFlag inFlag; + input String res; +algorithm + _ := matchcontinue (inFlag,res) + "this is a string_comment" + local + String debugstr,res_with_debug,flagstr; + case (Flags.DEBUG_FLAG(name = flagstr),_) + equation + true = Flags.isSet(inFlag); + debugstr = Print.getString(); + print("Hello World"); + then res_with_debug; + end matchcontinue; +end makeDebugResult; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (name_path + (IDENT) + (DOT) + (IDENT))) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))))) + (algorithm_clause + (T_ALGORITHM) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (WILD)))) + (ASSIGN) + (expression + (match_expression + (MATCHCONTINUE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (RPAR))) + (string_comment + (STRING)) + (local_clause + (LOCAL) + (element + (component_clause + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))) + (COMMA) + (component_declaration + (declaration + (IDENT))) + (COMMA) + (component_declaration + (declaration + (IDENT)))))) + (cases + (onecase + (CASE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (function_arguments + (named_argument + (IDENT) + (EQUALS) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (RPAR))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (WILD))))) + (RPAR))) + (EQUATION) + (equation + (simple_expression + (T_TRUE)) + (EQUALS) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (function_arguments + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))))) + (RPAR)))))) + (equation + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (EQUALS) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (RPAR)))))) + (equation + (component_reference + (IDENT)) + (function_call + (LPAR) + (function_arguments + (expression + (simple_expression + (STRING)))) + (RPAR))) + (THEN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (T_END) + (MATCHCONTINUE))))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a6-3_match_expression3.txt b/test/corpus/a6-3_match_expression3.txt new file mode 100644 index 0000000..6917882 --- /dev/null +++ b/test/corpus/a6-3_match_expression3.txt @@ -0,0 +1,192 @@ +====================== +A.6 match_expression 3 +====================== + +function makeDebugResult + input Flags.DebugFlag inFlag; + input String res; +algorithm + _ := matchcontinue (inFlag,res) + "this is a string_comment" + local + String debugstr,res_with_debug,flagstr; + Boolean isSet; + case (Flags.DEBUG_FLAG(name = flagstr),_) + algorithm + debugstr := res_with_debug; + debugstr := Print.getString(); + print("Hello World"); + then res_with_debug; + end matchcontinue; +end makeDebugResult; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (name_path + (IDENT) + (DOT) + (IDENT))) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))))) + (algorithm_clause + (T_ALGORITHM) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (WILD)))) + (ASSIGN) + (expression + (match_expression + (MATCHCONTINUE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))) + (RPAR))) + (string_comment + (STRING)) + (local_clause + (LOCAL) + (element + (component_clause + (type_specifier + (T_STRING)) + (component_declaration + (declaration + (IDENT))) + (COMMA) + (component_declaration + (declaration + (IDENT))) + (COMMA) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_specifier + (T_BOOLEAN)) + (component_declaration + (declaration + (IDENT)))))) + (cases + (onecase + (CASE) + (expression + (simple_expression + (LPAR) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (function_arguments + (named_argument + (IDENT) + (EQUALS) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (RPAR))))) + (COMMA) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (WILD))))) + (RPAR))) + (ALGORITHM) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (ASSIGN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (ASSIGN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT) + (DOT) + (IDENT)) + (function_call + (LPAR) + (RPAR))))))) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)) + (function_call + (LPAR) + (function_arguments + (expression + (simple_expression + (STRING)))) + (RPAR)))))) + (THEN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))))))) + (T_END) + (MATCHCONTINUE))))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/a6-4try.txt b/test/corpus/a6-4try.txt new file mode 100644 index 0000000..0eba9d8 --- /dev/null +++ b/test/corpus/a6-4try.txt @@ -0,0 +1,96 @@ +======= +A.6 try +======= + +function foo + input Real x; + input Real y; +protected + Real res; +algorithm + try + res := x/y; + break; + else + print("Divided by zero"); + end try; +end foo; + +--- + +(stored_definition + (class_definition + (class_type + (FUNCTION)) + (class_specifier + (identifier + (IDENT)) + (composition + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_REAL)) + (component_declaration + (declaration + (IDENT))))) + (element + (component_clause + (type_prefix + (T_INPUT)) + (type_specifier + (T_REAL)) + (component_declaration + (declaration + (IDENT))))) + (PROTECTED) + (element + (component_clause + (type_specifier + (T_REAL)) + (component_declaration + (declaration + (IDENT))))) + (algorithm_clause + (T_ALGORITHM) + (algorithm + (try_clause + (TRY) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)))) + (ASSIGN) + (expression + (simple_expression + (component_reference_function_call + (component_reference + (IDENT))) + (SLASH) + (component_reference_function_call + (component_reference + (IDENT))))))) + (algorithm + (BREAK)) + (ELSE) + (algorithm + (assign_clause_a + (simple_expression + (component_reference_function_call + (component_reference + (IDENT)) + (function_call + (LPAR) + (function_arguments + (expression + (simple_expression + (STRING)))) + (RPAR)))))) + (T_END) + (TRY))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/corpus/comment.txt b/test/corpus/comment.txt new file mode 100644 index 0000000..d9377d1 --- /dev/null +++ b/test/corpus/comment.txt @@ -0,0 +1,15 @@ +======= +Comment +======= + +// This is a comment + +/* This is a block comment + * + */ + +--- + +(stored_definition + (COMMENT) + (BLOCK_COMMENT)) diff --git a/test/corpus/package.txt b/test/corpus/package.txt new file mode 100644 index 0000000..5233509 --- /dev/null +++ b/test/corpus/package.txt @@ -0,0 +1,72 @@ +======= +Package +======= + +/* + * This is a comment over multiple lines + */ + +encapsulated package PackageA +" file: PackageA.mo + package: PackageA + description: PackageA stuff + + This is the PackageA that does nothing + but has a lot of comments." + +// public imports +public +import B = PackageB; +import PackageC.PackageD.*; +import PackageE.{foo,bar}; + +end PackageA; + +--- + +(stored_definition + (BLOCK_COMMENT) + (class_definition + (ENCAPSULATED) + (class_type + (PACKAGE)) + (class_specifier + (identifier + (IDENT)) + (string_comment + (STRING)) + (COMMENT) + (composition + (PUBLIC) + (element + (import_clause + (IMPORT) + (explicit_import_name + (IDENT) + (EQUALS) + (name_path + (IDENT))))) + (element + (import_clause + (IMPORT) + (implicit_import_name + (name_path_star + (IDENT) + (DOT) + (IDENT) + (STAR_EW))))) + (element + (import_clause + (IMPORT) + (implicit_import_name + (name_path_star + (IDENT) + (DOT) + (LBRACE) + (IDENT) + (COMMA) + (IDENT) + (RBRACE)))))) + (T_END) + (identifier + (IDENT))))) diff --git a/test/highlight/ClassDefinitions.mo b/test/highlight/ClassDefinitions.mo new file mode 100644 index 0000000..f19aa7e --- /dev/null +++ b/test/highlight/ClassDefinitions.mo @@ -0,0 +1,54 @@ +class Class +//<- keyword +// ^ module +end Class; +//<- keyword +// ^ module +optimization Opt +//<- keyword +// ^ module +end Opt; +//<- keyword +// ^ module +model MyModel +//<- keyword +// ^ module +end MyModel; +//<- keyword +// ^ module +record R +//<- keyword +// ^ type +end R; +//<- keyword +// ^ type +connector C +//<- keyword +// ^ module +end C; +//<- keyword +// ^ module +type T +//<- keyword +// ^ type +end T; +//<- keyword +// ^ type +package PackageA +//<- keyword +// ^ module +end PackageA; +//<- keyword +// ^ module +function foo +//<- keyword +// ^ function +end foo; +//<- keyword +// ^ function +uniontype T2 +//<- keyword +// ^ type +end T2; +//<- keyword +// ^ type diff --git a/test/highlight/FunctionCalls.mo b/test/highlight/FunctionCalls.mo new file mode 100644 index 0000000..87d3fa0 --- /dev/null +++ b/test/highlight/FunctionCalls.mo @@ -0,0 +1,26 @@ +function foo +//<- keyword +// ^ function + input list args "List of arguments"; +//^ keyword +// ^ type +// ^ type.builtin +// ^ variable.parameter +// ^ comment +protected +//<- keyword + String s; +//^ type.builtin +// ^ variable.parameter +algorithm +//<- keyword + s := bar1(bar2("hello", "World", args)); +//^ variable.parameter +// ^ operator +// ^ function +// ^ function +// ^ string +// ^ string +end foo; +//<- keyword +// ^ function diff --git a/test/highlight/Types.mo b/test/highlight/Types.mo new file mode 100644 index 0000000..981a4e3 --- /dev/null +++ b/test/highlight/Types.mo @@ -0,0 +1,43 @@ +function foo +// <- keyword +// ^ function + Real x1; +//^ type.builtin +// ^ @variable.parameter + Integer x2; +//^ type.builtin +// ^ @variable.parameter + Boolean x3; +//^ type.builtin +// ^ @variable.parameter + String x4; +//^ type.builtin +// ^ @variable.parameter + MyType x5; +//^ type +// ^ @variable.parameter + List x6; +//^ type.builtin +// ^ type.builtin +// ^ @variable.parameter + List x7; +//^ type.builtin +// ^ type +// ^ @variable.parameter + Option x8; +//^ type.builtin +// ^ type.builtin +// ^ @variable.parameter + Option x9; +//^ type.builtin +// ^ type +// ^ @variable.parameter + Tuple x10; +//^ type.builtin +// ^ type +// ^ type +// ^ type +// ^ @variable.parameter +end foo; +// <- keyword +// ^ function diff --git a/test/highlight/try.mo b/test/highlight/try.mo new file mode 100644 index 0000000..4830588 --- /dev/null +++ b/test/highlight/try.mo @@ -0,0 +1,39 @@ +function foo +//<- keyword +// ^ function + input Real x; +//^ keyword +// ^ type.builtin +// ^ variable.parameter + input Real y; +//^ keyword +// ^ type.builtin +// ^ variable.parameter +protected +//<- keyword + Real res; +//^ type.builtin +// ^ variable.parameter +algorithm +//<- keyword + try +//^ keyword + res := x/y; +// ^ variable.parameter +// ^ operator +// ^ variable.parameter +// ^ operator +// ^ variable.parameter + break; +// ^ keyword + else +//^ keyword + print("Divided by zero"); +// ^ function +// ^ string + end try; +//^ keyword +// ^ keyword +end foo; +//<- keyword +// ^ function