• Non ci sono risultati.

A complete DSTM model, is composed by data declarations and a definition of the control flow. Both of them, must be compliant to the syntax and the semantics of DSTM, specified in Chapter4In order to address constraints demanded by the syntax and semantics of the language, different approaches can be followed. For

example, the metamodel can be enriched with additional constraints, by exploit-ing facilities of the metamodellexploit-ing environment or by usexploit-ing an ad-hoc language for constraints (e.g. OCL). Another approach, instead, is to demand the verifi-cation of such constraints to an external tool. The DSTMVerifier component, is based on this second approach; in fact, in order to maintain modelling activities as simple as possible, a specific tools has been developed with the responsibilities of:

• verify the data flow of the model, i.e. the declarations related to custom data types, variables and channels

• verify the decorations of transitions, i.e. their triggers, conditions and ac-tions;

• verify the correctness of the model based on the well-formedness constraints not defined at the metamodel level.

The first two objectives can be achieved by the definition of a syntax analysis process. The syntax analysis, or parsing is the process that allows to verify if sequences of symbols (or streams) are conform to a set of formal rules called grammars. The syntax analysis process is composed by three phases:

• Lexical analysis: streams are examined and grouped on the basis of their meanings. Such groups, called tokens are then matched with a set of rules typically given as regular expressions. This phase produce sequences of tokens.

• Syntactical analysis: the token streams are matched with another set of rules, called grammars. Each rule in the grammar, is called production. A produc-tion describes a valid tree-like structure in terms of tokens and, recursively, in terms of other productions. This process is usually performed by a rou-tine called syntactical analyser. The rules we consider, are expressed in form of context-free grammars (Subsection2.5.2). CFGs allow to perform an effi-cient analysis of recursive tree-structured text, which means that each struc-ture identified can be viewed as a tree node interconnected with each other node to compose the syntax tree. Thus, the syntax tree can be represented in different ways. Two of the most important are the Abstract Syntax Tree (AST) and the Concrete Syntax Tree (CST). CSTs are a more concrete view of the input token stream, since they represent in a tree-like form the input as it is parsed during the syntax analysis. The AST instead is more abstract

then the CST and allows to reproduce the structure of the input in a hierar-chical data structure, useful for further analysis and transformations [62].

In the translation between different languages, ASTs are needed because of the nature of languages. Languages are often ambiguous by nature. In or-der to avoid this ambiguity, CFGs are useful but there are some aspects that they cannot address, such as details which require a context to determine their validity and behaviour.

• Semantic analysis since most languages (included the domain-specific ones) cannot be specified completely using a CFG. In fact there is the need to ad-ditional rules to define other constraints of the language. Thus, costraints, can be given using natural language or specific languages for constraints.

The realization of the DSTMVerifier, have been performed by following the below steps:

• Definition of the grammars related to data declarations, triggers, conditions and actions of transitions. Grammars have been expressed by using a BNF notation (Subsection2.5.2) and used to verify the lexical correctness of the model structure.

• Generation, with a parser generator, called SableCC [80], of the packages to check the consistency of the data flow of the DSTM models;

• Analysis of model constraints, trough a java-based software module, in charge of make an exhaustive verification of such constraints on edited models.

An example of BNF grammar, defined for the syntactical verification of trig-gers on the transition decorations is reported in Listing6.1.

LISTING6.1: BNF grammar for Triggers

1 Helpers

2 e o l = 11 | 9 | 10 | 13 | 10 1 3 ; 3 sp = ’ ’ ;

4 d i g i t = [ ’ 0 ’ . . ’ 9 ’ ] ;

5 char = [ [ ’ a ’ . . ’ z ’ ] + [ ’A ’ . . ’Z ’ ] ] ;

6 e c h a r = [ [ [ ’ a ’ . . ’ z ’ ] + [ ’A ’ . . ’Z ’ ] ] + ’ _ ’ ] ; 7 plus = ’ + ’ ;

8 minus= ’− ’ ;

9 Tokens

10 i n t = ’ I n t ’ ; 11 bool = ’ Bool ’ ; 12 enum = ’Enum ’ ; 13 chn = ’Chn ’ ; 14 s t r u c t = ’ S t r u c t ’ ; 15 mtype= ’ Mtype ’ ;

16 o f = ’ o f ’ ; 17 t r u e = ’ t r u e ’ ; 18 f a l s e = ’ f a l s e ’ ; 19 f u l l = ’ f u l l ’ ; 20 empty= ’ empty ’ ; 21 s p a c e s = e o l + ; 22 space = sp + ;

23 e x t e r n a l = ’ e x t e r n a l ’ ; 24 i n t e r n a l = ’ i n t e r n a l ’ ;

25 i d e n t i f i e r = char ( d i g i t | e c h a r ) * ; 26 numbers = d i g i t * ;

27 semi = ’ ; ’ ; 28 comma = ’ , ’ ; 29 qmark = ’ ? ’ ; 30 colon= ’ : ’ ; 31 plus = ’ + ’ ; 32 minus = ’− ’ ; 33 s t a r = ’ * ’ ; 34 s l a s h = ’ / ’ ; 35 a s s i g n = ’ : = ’ ; 36 l t = ’ < ’ ; 37 g t = ’ > ’ ; 38 eq = ’ == ’ ; 39 not= ’ ! ’ ; 40 amp_amp= ’&&’ ; 41 b a r _ b a r= ’ || ’ ; 42 l t e q = ’ <= ’ ; 43 gteq = ’ >= ’ ; 44 p l u s _ p l u s = ’ ++ ’ ; 45 minus_minus = ’−− ’ ; 46 l _ p a r = ’ ( ’ ; 47 r _ p a r = ’ ) ’ ; 48 l _ b k t = ’ [ ’ ; 49 r _ b k t = ’ ] ’ ; 50 l _ b r c = ’ { ’ ; 51 r _ b r c = ’ } ’ ; 52

53 Ignored Tokens 54 space , s p a c e s ; 55

56 P r o d u c t i o n s 57 t r i g g e r = 58 { unique } term ; 59

60 term =

61 { n e st e d } l _ p a r term r _ p a r|

62 { unary } not term | 63 { simple } atomic |

64 { b i n a r y } l _ p a r f i r s t binop second r _ p a r ; 65

66 binop =

67 { andop } amp_amp | 68 { orop } b a r _ b a r ; 69

70 f i r s t = 71 { l e f t } term ; 72

73 second=

74 { r i g h t } term ; 75

76 atomic =

77 { message } var qmark |

78 { messagetype } var qmark simpletype ; 79

80 simpletype=

81 { b a s i c } b a s i c |

82 { compound } compound_name ; 83

84 compound_name=

85 { i d } d e f i n e d ; 86

87 b a s i c = 88 { i n t } i n t | 89 { bool } bool | 90 { ename } e_name|

91 { chant } chn l _ b k t d e f i n e d r _ b k t | 92 { chn } chn ;

93

94 e_name=

95 { enum } d e f i n e d ; 96

97 var=

98 { simple } d e f i n e d ; 99

100 d e f i n e d =

101 { simple } i d e n t i f i e r ;

As stated before, each rule of the grammar is represented as a production in the form A→ α which states that the symbol on the left-hand side must be replaced by one of the alternatives on the right-hand side. The package structure of the generated parser, from the grammars, is represented in Figure6.4.

According to the Figure 6.4, a package is created for each defined grammar (data, trigger, condition, action and parameter). However since transition deco-ration and parameters are related to data decladeco-rations, the Data package is com-mon. Moreover, each package is further divided in the following subpackages:

• Lexer package, which contains the Lexer and LexerException classes, re-spectively in charge of perform the lexical analysis and rise exceptions if such analysis fails;

• Parser package, which contains Parser and ParserException classes with the same aims of the previous;

• Node package containing all the classes to define the typed AST. As dis-cussed, the AST consists in an intermediate representation of the model that serves for further analysis or transformations.

Data Model

lexer Node

Analysis Parser

Parameter

lexer Node

Analysis Parser

CrossCompiler.Trigger

lexer Node

Analysis Parser

CrossCompiler.Condition

lexer Node

Analysis Parser

CrossCompiler.Action

lexer Node

DSTM Package

<<uses>>

<<uses>>

<<uses>>

<<uses>>

<<uses>>

<<uses>>

Analysis Parser P

FIGURE6.4: DSTMVerifier package diagram

• Analysis package containing the AST walkers. A tree-walkers is a class that visit all the nodes of an AST in a predefined order. Walkers allow to cross the AST in a depth-first traversal by calling proper in and out methods, when nodes are entered and exited. The adoption of walkers makes the parser easy to reuse and extend because the same tree-walkers can be used as the parents of many different walker classes.

The above packages allow to perform a syntax analysis of transition decora-tions and data. With the respect to the verification well-formedness constraints, a dedicated package has been developed and named Model package. Model straints are expressed by means of java code. As for example, a relevant con-straint is that for each machine only one InitialNode must exist. Such concon-straint can be expressed, by exploiting the primitives of the DSTMPackage. Listing6.2 represents the uniqueness constraint.

LISTING6.2: Uniqueness constraint of InitialNode

1 f o r ( Machine machine : model . getMachines ( ) ) { 2 i n t count = 0 ;

3 f o r ( Vertex v e r t e x : machine . g e t V e r t e x e s ( ) ) {

4 i f( v e r t e x . g e t C l a s s ( ) . getName ( ) . compareTo ( " DSTM4Rail . impl . I n i t i a l N o d e I m p l " ) ==0) {

5 count ++;

6 i f( count >1) {

7 V i o l a t i o n v = new ModelViolation ( "UNQINIT" , " Machine " , ( EObject ) machine ) ;

8 t h i s. v i o l a t i o n s . add ( v ) ;

9 r e t v a l = f a l s e;

10 }

11 }

12 }

13 }