blob: b1febc3921fb5bd37d0ab3d082db49281d35996a [file] [log] [blame] [edit]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
/* The grammar for CAmkES architecture specifications. This is intended to be
* consumed by a plyplus parser.
*/
start: (assembly_decl | component_decl | composition_decl |
configuration_decl | connector_decl | import |
procedure_decl | struct_decl | /* Allow empty statements: */ ';')*;
ID: '[a-zA-Z_]\w*'
/* Everything that's a keyword ends up matching ID, so we need to
* explicitly spell out exceptions here. Note that we don't bother with
* native types because any context they can appear in accepts
* arbitrary IDs to represent C typedefs.
*/
(%unless
ASSEMBLY: 'assembly';
ATTRIBUTE: 'attribute';
BUF: 'Buf';
CHAR: 'char';
COMPONENT: 'component';
COMPOSITION: 'composition';
CONFIGURATION: 'configuration';
CONNECTION: 'connection';
CONNECTOR: 'connector';
CONSUMES: 'consumes';
CONTROL: 'control';
DATAPORT: 'dataport';
DATAPORT_TYPE: 'Dataport';
DATAPORTS_TYPE: 'Dataports';
EMITS: 'emits';
EVENT_TYPE: 'Event';
EVENTS_TYPE: 'Events';
EXPORT: 'export';
FALSE1: 'False';
FALSE2: 'false';
FROM: 'from';
GROUP: 'group';
HARDWARE: 'hardware';
HAS: 'has';
IMPORT: 'import';
IN: 'in';
INCLUDE: 'include';
INOUT: 'inout';
INT: 'int';
INTEGER: 'integer';
INT64_T: 'int64_t';
MAYBE: 'maybe';
MUTEX: 'mutex';
OUT: 'out';
PROCEDURE: 'procedure';
PROCEDURE_TYPE: 'Procedure';
PROCEDURES_TYPE: 'Procedures';
PROVIDES: 'provides';
REFIN: 'refin';
SEMAPHORE: 'semaphore';
BINARY_SEMAPHORE: 'binary_semaphore';
COPYREGION: 'copyregion';
SIGNED: 'signed';
STRUCT: 'struct';
STRING: 'string';
THREAD: 'thread';
THREADS: 'threads';
TRUE1: 'True';
TRUE2: 'true';
TO: 'to';
UINT64_T: 'uint64_t';
UNSIGNED: 'unsigned';
USES: 'uses';
VOID: 'void';
WITH: 'with';
);
/* For the case where we need an AST-visible ID */
id: ID | BUF;
assembly_decl: ASSEMBLY id? assembly_defn;
assembly_defn: '\{' composition_sing configuration_sing? '\}'
| '\{' configuration_sing composition_sing '\}';
composition_sing: COMPOSITION reference ';'
| composition_decl;
configuration_sing: CONFIGURATION reference ';'
| configuration_decl;
attribute_decl: attribute_parameter ('=' item)? ;
component_decl: COMPONENT id? component_defn;
component_defn: '\{' (attribute | consumes | control | dataport | emits |
hardware | include | mutex | provides | semaphore | binary_semaphore |
copyregion | uses)*
((composition_sing configuration_sing?) | configuration_sing composition_sing)? '\}';
component_ref: reference | component_defn;
struct_decl: STRUCT id struct_defn;
struct_defn: '\{' (attribute_decl ';')* '\}';
struct_ref: reference | struct_defn;
@attribute: ATTRIBUTE attribute_decl ';';
consumes: maybe? CONSUMES id id ';';
control: CONTROL ';';
dataport: maybe? DATAPORT dataport_type id ';';
dataport_type: id | BUF '\(' numeric_expr '\)';
emits: EMITS id id ';';
hardware: HARDWARE ';';
mutex: HAS MUTEX id ';';
provides: PROVIDES reference id ';';
semaphore: HAS SEMAPHORE id ';';
binary_semaphore: HAS BINARY_SEMAPHORE id ';';
copyregion_size: '\(' numeric_expr '\)';
copyregion: HAS COPYREGION id copyregion_size? ';';
uses: maybe? USES reference id ';';
maybe: MAYBE;
composition_decl: COMPOSITION id? composition_defn;
composition_defn: '\{' (instance_defn | connection_defn | group_decl | export)* '\}';
instance_defn: COMPONENT component_ref id ';';
connection_defn: CONNECTION connector_ref id '\(' (connection_end (',' connection_end)* ','?)? '\)' ';';
connection_end: (from | to) reference;
from: FROM;
to: TO;
group_decl: GROUP id? group_defn;
group_defn: '\{' instance_defn* '\}';
export: EXPORT reference '->' reference ';';
configuration_decl: CONFIGURATION id? configuration_defn;
configuration_defn: '\{' setting* '\}';
setting: id '\.' id (('=' (item|query)) | ('<-' attribute_reference))';';
attribute_reference: id ('\.' id)* (dict_lookup)?;
connector_decl: CONNECTOR id? connector_defn;
connector_defn: '\{' FROM hardware_bare? connector_end_type connector_properties ';' TO hardware_bare? connector_end_type connector_properties ';'
(attribute)* '\}';
hardware_bare: HARDWARE;
connector_ref: reference | connector_defn;
connector_end_type: DATAPORT_TYPE | EVENT_TYPE | PROCEDURE_TYPE
| DATAPORTS_TYPE | EVENTS_TYPE | PROCEDURES_TYPE;
@connector_properties:
| threads;
@threads: WITH numeric_expr (THREAD | THREADS);
import: IMPORT (multi_string | angle_string) ';';
include: INCLUDE (multi_string | angle_string) ';';
method_decl: (VOID | type) id '\(' (VOID | (method_parameter (',' method_parameter)* ','?)?) '\)' ';';
@method_parameter: method_array_parameter | method_scalar_parameter;
method_array_parameter: method_scalar_parameter '\[' '\]';
method_scalar_parameter: direction? type id;
direction: IN | INOUT | OUT | REFIN;
@attribute_parameter: attribute_array_parameter | attribute_scalar_parameter;
attribute_array_parameter: attribute_scalar_parameter '\[' '\]';
attribute_scalar_parameter: type id;
type: signed_int | unsigned_int | struct_type | char | signed_char | unsigned_char | STRING | struct_ref | uint64_t | int64_t | ID;
signed_int: (SIGNED? (INT | INTEGER)) | SIGNED;
unsigned_int: UNSIGNED (INT | INTEGER)?;
uint64_t: UINT64_T;
int64_t: INT64_T;
char: CHAR;
signed_char: SIGNED CHAR;
unsigned_char: UNSIGNED CHAR;
struct_type: STRUCT id;
procedure_decl: PROCEDURE id? procedure_defn;
procedure_defn: '\{' (method_decl | attribute_decl | include)* '\}';
reference: id ('\.' id)*;
/* Numeric expressions */
@numeric_expr: precedence11;
precedence11: precedence10 ('\?' numeric_expr ':' precedence10)?;
precedence10: precedence9 (lor precedence9)*;
lor: '\|\|';
precedence9: precedence8 (land precedence8)*;
land: '&&';
precedence8: precedence7 (bor precedence7)*;
bor: '\|';
precedence7: precedence6 (xor precedence6)*;
xor: '\^';
precedence6: precedence5 (band precedence5)*;
band: '&';
precedence5: precedence4 ((eq | neq) precedence4)*;
eq: '==';
neq: '!=';
precedence4: precedence3 ((lt | lte | gt | gte) precedence3)*;
lt: '<';
lte: '<=';
gt: '>';
gte: '>=';
precedence3: precedence2 ((ls | rs) precedence2)*;
ls: '\<\<';
rs: '\>\>';
precedence2: precedence1 ((add | sub) precedence1)*;
add: '\+';
sub: '-';
precedence1: precedence0 ((mul | div | mod | pow) precedence0)*;
mod: '%';
mul: '\*';
div: '/';
pow: '\*\*';
@precedence0: number | '\(' numeric_expr '\)' | unary_minus | unary_plus
| logical_not | bitwise_not | boolean_literal;
unary_minus: '-' precedence0;
@unary_plus: '\+' precedence0;
logical_not: '!' precedence0;
bitwise_not: '~' precedence0;
/* Literals */
number: '(0x[0-9a-fA-F]+|\d+(\.\d+)?)';
multi_string: quoted_string+;
quoted_string: '"[^"]*"'; // "
angle_string: '<[^<>;,"{}]*>';
list: '\[' (item (',' item)* ','?)? '\]';
dict: '\{' (key ':' item (',' key ':' item)* ','?)? '\}';
dict_lookup: ('\[' key '\]')+;
dict_list: '\[' (dict (',' dict)* ','?)? '\]';
query: id '\(' (dict | dict_list)? '\)' (dict_lookup)?;
@key: numeric_expr | multi_string;
@item: numeric_expr | multi_string | list | dict;
boolean_literal: TRUE1 | TRUE2 | FALSE1 | FALSE2;
/* Things to ignore */
SINGLE_LINE_COMMENT: '//.*' (%ignore);
MULTILINE_COMMENT: '/\*(.|\n)*?\*/' (%ignore) (%newline);
WHITESPACE: '[ \t\f]+' (%ignore);
NEWLINE: '\r?\n' (%ignore) (%newline);
CPP_DIRECTIVE: '\#.*' (%ignore);