source: default/v2/trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfValidator.xtend @ 102

Last change on this file since 102 was 102, checked in by phdmakk, 8 years ago

+ added checking of rule numbering

File size: 10.6 KB
Line 
1/*
2 * generated by Xtext
3 */
4package de.ugoe.cs.swe.bnftools.validation
5
6import de.ugoe.cs.swe.bnftools.ebnf.EbnfPackage
7import java.util.List
8import org.eclipse.xtext.validation.Check
9import de.ugoe.cs.swe.bnftools.ebnf.Rule
10import org.eclipse.xtext.nodemodel.util.NodeModelUtils
11import org.eclipse.xtext.nodemodel.ICompositeNode
12import de.ugoe.cs.swe.bnftools.ebnf.EtsiBnf
13import de.ugoe.cs.swe.bnftools.ebnf.RuleReference
14import de.ugoe.cs.swe.bnftools.ebnf.DefinitionList
15import de.ugoe.cs.swe.bnftools.ebnf.SingleDefinition
16import com.google.inject.Inject
17import org.eclipse.xtext.resource.IResourceDescriptions
18
19//import java.util.HashMap
20//import java.util.Set
21//import java.util.HashSet
22//import org.eclipse.xtext.validation.Check
23/**
24 * Custom validation rules.
25 *
26 * see http://www.eclipse.org/Xtext/documentation.html#validation
27 */
28class EbnfValidator extends AbstractEbnfValidator {
29
30
31        @Inject
32        IResourceDescriptions resourceDescriptions;
33       
34       
35        public static final String ruleReferencedOneDescription = "The rule is only referenced by one other rule";
36        public static final String passthroughRuleDescription = "The rule is a passthrough rule";
37        public static final String unreferencedPassthroughRuleDescription = "The rule is an unreferenced passthrough rule";
38        public static final String unusedRuleDescription = "The rule is not referenced anywhere";
39        public static final String equalAlternativeDescription = "The rule contains equal alternatives";
40        public static final String duplicateRulesDescription = "The rule is a duplicate";
41
42        //public  static final String duplicateSubRulesDescription = "A part the of rule is a duplicate";
43        public static final String nonUniqueNameDescription = "The rule has the same Name as the Rule in Line ";
44        public static final String wrongNumbering = "The rule numbering is wrong in Line ";
45
46        // ----------------------------------------------------------------------------------------------------
47        /* Checks if a rule is only referenced by one other Rule, e.g.:
48                 * a ::= b
49                 * b ::= "foo"
50                 */
51        @Check
52        def void checkReferencedOnlyOnce(Rule rule) {
53
54                if (EbnfAnalysisUtils.isTokenRule(rule))
55                        return;
56
57                var List<Rule> references = EbnfAnalysisUtils.findReferences(rule,resourceDescriptions);
58                var List<RuleReference> references1 = EbnfAnalysisUtils.findReferences(rule);
59                if (references.size+references1.size == 1 && rule.rulenumber != 1) {
60                        warning(ruleReferencedOneDescription, EbnfPackage$Literals::RULE__NAME, ruleReferencedOneDescription,
61                                rule.name);
62                }
63        }
64
65        // ----------------------------------------------------------------------------------------------------
66        /*Checks if a a rule has the same definition as another rule e.g.:
67         * a ::= "test"
68         * b ::= "test"
69         * (Problem: does not check if there is a permutation)
70         */
71        @Check
72        def void checkDuplicateRules(Rule rule) {
73
74                //load bnf
75                var EtsiBnf etsiBnf = rule.eContainer().eContainer() as EtsiBnf;
76
77                // find the rule in the parsetree
78                var ICompositeNode definitionList = NodeModelUtils.findActualNodeFor(rule.getDefinitionList());
79
80                //get the definitionList as  formatted string
81                var String rightHandSideText = definitionList.text.trim().replaceAll("[ \t\n\r]", "");
82
83                //get All Rules
84                var List<Rule> allRules = EbnfAnalysisUtils.getAllRules(etsiBnf);
85
86                // run through all Rules
87                                                for (currentRule : allRules) {
88                                                        if (currentRule != rule) {
89                                                                var ICompositeNode currentRuleDefinitionList = NodeModelUtils.findActualNodeFor(
90                                                                        currentRule.getDefinitionList());
91                                                                var String currentRuleRightHandSideText = currentRuleDefinitionList.text.trim().replaceAll("[ \t\n\r]",
92                                                                        "");
93                               
94                                                                if (currentRuleRightHandSideText.equals(rightHandSideText)) {
95                                                                        var String description = duplicateRulesDescription + " with rule \"" + currentRule.getName() +
96                                                                                "\" (Line " + NodeModelUtils.findActualNodeFor(currentRule).getStartLine() + ")";
97                                                                        warning(description, EbnfPackage$Literals::RULE__NAME);
98                                                                }
99                                                        }
100                                                }
101               
102//              //get all Single Definitions as Trimmed Strings
103//              var List<String> singleDefsAsString = new ArrayList<String>();
104//
105//              for (SingleDefinition s : (rule.definitionList).singleDefinition) {
106//                      singleDefsAsString.add(NodeModelUtils.findActualNodeFor(s).text.trim().replaceAll("[ \t\n\r]", ""));
107//              }
108//
109//              // for every rule get the single definitions as Strings
110//              var int j = 0;
111//              while (j<allRules.size) {
112//                      var currentRule=allRules.get(j);
113//                      if (currentRule != rule) {
114//                              var List<String> singleDefsAsString1 = new ArrayList<String>();
115//
116//                              for (SingleDefinition s : ( currentRule.definitionList).singleDefinition) {
117//                                      singleDefsAsString1.add(NodeModelUtils.findActualNodeFor(s).text.trim().replaceAll("[ \t\n\r]", ""));
118//                              }
119//
120//                              //for every String SingleDefinition find a corresponding ind the current rule
121//                              if (singleDefsAsString.size == singleDefsAsString1.size) {
122//                                      var List<String> singleDefsAsStringCpy = singleDefsAsString.clone;
123//                                      var boolean equal = true;
124//                                      while (equal) {
125//                                              var String momentaryString = singleDefsAsStringCpy.get(0);
126//                                              var int i = 0;
127//                                              var boolean found = false;
128//                                              while (i < singleDefsAsString1.size && !found) {
129//                                                      if (singleDefsAsString1.get(i).equals(momentaryString)) {
130//                                                              singleDefsAsStringCpy.remove(0);
131//                                                              singleDefsAsString1.remove(i);
132//                                                              found = true
133//                                                      }
134//                                                      i++;
135//                                              }
136//                                              if (!found) {
137//                                                      equal = false;
138//                                              }
139//                                              if (singleDefsAsStringCpy.empty) {
140//                                                      var String description = duplicateRulesDescription + " with rule \"" + currentRule.getName() +
141//                                                              "\" (Line " + NodeModelUtils.findActualNodeFor(currentRule).getStartLine() + ")";
142//                                                      warning(description, EbnfPackage$Literals::RULE__NAME)
143//                                              }
144//                                      }
145//                              }
146//
147//                      }
148//                      j++;
149//              }
150        }
151
152        // ----------------------------------------------------------------------------------------------------
153        /*Checks if a Rule got the same Name as another Rule, e.g.:
154         * a ::= "foo"
155         * a ::= "bar"
156         */
157        @Check
158        def void checkNameIsUnique(Rule rule) {
159                val EtsiBnf bnf = rule.eContainer.eContainer as EtsiBnf;
160                for (r : EbnfAnalysisUtils.getAllRules(bnf)) {
161                        if (rule.name.equals(r.name)) {
162                                if (!r.equals(rule)) {
163                                        error(nonUniqueNameDescription + NodeModelUtils.findActualNodeFor(r).startLine,
164                                                EbnfPackage$Literals::RULE__NAME)
165
166                                }
167                        }
168                }
169        }
170
171        // ----------------------------------------------------------------------------------------------------
172        /*Checks if the rule numbering is correct:
173         * 1. a ::= "foo"
174         * 3. b ::= "bar"
175         */
176        @Check
177        def void checkRuleNumbering(Rule rule) {
178                val EtsiBnf bnf = rule.eContainer.eContainer as EtsiBnf;
179                if (EbnfAnalysisUtils.getAllRules(bnf).indexOf(rule)+1 != rule.rulenumber) {
180                        warning(wrongNumbering + NodeModelUtils.findActualNodeFor(rule).startLine,
181                                EbnfPackage$Literals::RULE__RULENUMBER)
182                }
183        }
184
185        //alternative implementation, does not work for some reason
186        @Check
187        def void checkRuleNumberingG(EtsiBnf bnf) {
188//              var lastNumber = 0;
189//              for (r : EbnfAnalysisUtils.getAllRules(bnf)) {
190//                      println(lastNumber + " : " + r.rulenumber)
191//                      if (lastNumber!=0 && r.rulenumber != lastNumber+1) {
192//                              warning(wrongNumbering + NodeModelUtils.findActualNodeFor(r).startLine,
193//                                      EbnfPackage$Literals::RULE__RULENUMBER)
194//                      }
195//                      lastNumber = r.rulenumber
196//              }
197        }
198
199
200        // ----------------------------------------------------------------------------------------------------
201        /*Checks if a Rule, except for the #1 is not referenced, e.g.:
202         * a::= b
203         * b::="foo"
204         * c ::= "bar"
205         */
206        @Check
207        def void checkUnusedRule(Rule rule) {
208
209                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
210                var List<Rule> references1 = EbnfAnalysisUtils.findReferences(rule,resourceDescriptions);
211                if ((references.size+references1.size == 0) && (rule.getRulenumber() != 1))
212                        warning(unusedRuleDescription, EbnfPackage$Literals::RULE__NAME, unusedRuleDescription, rule.name);
213        }
214
215        // ----------------------------------------------------------------------------------------------------
216        /*Checks if a rule got two equal alternatives, e.g.:
217         * a ::= b | "foo" | b
218         *(Problem:ignores whitespaces in literals)
219         */
220        @Check
221        def void checkEqualAlternative(Rule rule) {
222
223                var DefinitionList definitionList = rule.definitionList;
224
225                var List<SingleDefinition> singleDefinitions = definitionList.singleDefinition;
226
227                for (sDef1 : singleDefinitions) {
228                        for (sDef2 : singleDefinitions) {
229                                if (!sDef1.equals(sDef2)) {
230                                        var String d1 = NodeModelUtils.findActualNodeFor(sDef1).text.trim.replaceAll("[ \t\n\r]", "");
231                                        var String d2 = NodeModelUtils.findActualNodeFor(sDef2).text.trim.replaceAll("[ \t\n\r]", "");
232
233                                        if (d1.equals(d2))
234                                                warning(equalAlternativeDescription, EbnfPackage$Literals::RULE__NAME,
235                                                        equalAlternativeDescription, rule.name);
236                                }
237                        }
238                }
239
240        }
241
242        // ----------------------------------------------------------------------------------------------------
243        /* Checks if a rule gets just passed through, e.g.:
244         * a ::= b | "literal"
245         * b ::= c
246         * c ::= "foo.bar"
247         */
248        @Check
249        def void checkPassthroughRule(Rule rule) {
250
251                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
252                var List<Rule> references1 = EbnfAnalysisUtils.findReferences(rule,resourceDescriptions);
253                if (EbnfAnalysisUtils.isPassthroughRule(rule) && rule.rulenumber != 1) {
254                        if (references.size+references1.size == 0) {
255                                warning(unreferencedPassthroughRuleDescription, EbnfPackage$Literals::RULE__NAME);
256                        } else {
257                                warning(passthroughRuleDescription, EbnfPackage$Literals::RULE__NAME, passthroughRuleDescription,
258                                        rule.name);
259                        }
260                }
261        }
262
263// ----------------------------------------------------------------------------------------------------
264/* Checks if a subrule is used more then once, e.g.:
265         * a ::= (a b) e
266         * b ::= (a b) d
267         *       _____
268         * (Not working, under construction)
269         */
270//      @Check
271//      def void checkSubruleDuplicates(EtsiBnf bnf){
272//              var HashMap<String, DuplicateEntry> dupesMap = new HashMap<String, DuplicateEntry>();
273//              var Set<String> taggedEntries = new HashSet<String>();
274//             
275//              var List<Rule> allRules = EbnfAnalysisUtils.getAllRules(bnf);
276//             
277//              for(rule: allRules){
278//                      var List<SingleDefinition> subrules = rule.definitionList.singleDefinition
279//                      for(subrule:subrules){
280//                              var String subruleText = NodeModelUtils.findActualNodeFor(subrule).text.trim.replaceAll("[ \t\n\r]", "");
281//                             
282//                      }
283//              }
284//      }
285}
Note: See TracBrowser for help on using the repository browser.