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

Last change on this file since 66 was 66, checked in by hkaulbersch, 10 years ago

Changed Validation:
Validation now works between different files
-unused rule
-referenced only ones
-passthrough

File size: 9.5 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 java.util.ArrayList
17import com.google.inject.Inject
18import org.eclipse.xtext.resource.IResourceDescriptions
19
20//import java.util.HashMap
21//import java.util.Set
22//import java.util.HashSet
23//import org.eclipse.xtext.validation.Check
24/**
25 * Custom validation rules.
26 *
27 * see http://www.eclipse.org/Xtext/documentation.html#validation
28 */
29class EbnfValidator extends AbstractEbnfValidator {
30
31
32        @Inject
33        IResourceDescriptions resourceDescriptions;
34       
35       
36        public static final String ruleReferencedOneDescription = "The rule is only referenced by one other rule";
37        public static final String passthroughRuleDescription = "The rule is a passthrough rule";
38        public static final String unreferencedPassthroughRuleDescription = "The rule is an unreferenced passthrough rule";
39        public static final String unusedRuleDescription = "The rule is not referenced anywhere";
40        public static final String equalAlternativeDescription = "The rule contains equal alternatives";
41        public static final String duplicateRulesDescription = "The rule is a duplicate";
42
43        //public  static final String duplicateSubRulesDescription = "A part the of rule is a duplicate";
44        public static final String nonUniqueNameDescription = "The rule has the same Name as the Rule 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 a Rule, except for the #1 is not referenced, e.g.:
173         * a::= b
174         * b::="foo"
175         * c ::= "bar"
176         */
177        @Check
178        def void checkUnusedRule(Rule rule) {
179
180                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
181                var List<Rule> references1 = EbnfAnalysisUtils.findReferences(rule,resourceDescriptions);
182                if ((references.size+references1.size == 0) && (rule.getRulenumber() != 1))
183                        warning(unusedRuleDescription, EbnfPackage$Literals::RULE__NAME, unusedRuleDescription, rule.name);
184        }
185
186        // ----------------------------------------------------------------------------------------------------
187        /*Checks if a rule got two equal alternatives, e.g.:
188         * a ::= b | "foo" | b
189         *(Problem:ignores whitespaces in literals)
190         */
191        @Check
192        def void checkEqualAlternative(Rule rule) {
193
194                var DefinitionList definitionList = rule.definitionList;
195
196                var List<SingleDefinition> singleDefinitions = definitionList.singleDefinition;
197
198                for (sDef1 : singleDefinitions) {
199                        for (sDef2 : singleDefinitions) {
200                                if (!sDef1.equals(sDef2)) {
201                                        var String d1 = NodeModelUtils.findActualNodeFor(sDef1).text.trim.replaceAll("[ \t\n\r]", "");
202                                        var String d2 = NodeModelUtils.findActualNodeFor(sDef2).text.trim.replaceAll("[ \t\n\r]", "");
203
204                                        if (d1.equals(d2))
205                                                warning(equalAlternativeDescription, EbnfPackage$Literals::RULE__NAME,
206                                                        equalAlternativeDescription, rule.name);
207                                }
208                        }
209                }
210
211        }
212
213        // ----------------------------------------------------------------------------------------------------
214        /* Checks if a rule gets just passed through, e.g.:
215         * a ::= b | "literal"
216         * b ::= c
217         * c ::= "foo.bar"
218         */
219        @Check
220        def void checkPassthroughRule(Rule rule) {
221
222                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
223                var List<Rule> references1 = EbnfAnalysisUtils.findReferences(rule,resourceDescriptions);
224                if (EbnfAnalysisUtils.isPassthroughRule(rule) && rule.rulenumber != 1) {
225                        if (references.size+references1.size == 0) {
226                                warning(unreferencedPassthroughRuleDescription, EbnfPackage$Literals::RULE__NAME);
227                        } else {
228                                warning(passthroughRuleDescription, EbnfPackage$Literals::RULE__NAME, passthroughRuleDescription,
229                                        rule.name);
230                        }
231                }
232        }
233
234// ----------------------------------------------------------------------------------------------------
235/* Checks if a subrule is used more then once, e.g.:
236         * a ::= (a b) e
237         * b ::= (a b) d
238         *       _____
239         * (Not working, under construction)
240         */
241//      @Check
242//      def void checkSubruleDuplicates(EtsiBnf bnf){
243//              var HashMap<String, DuplicateEntry> dupesMap = new HashMap<String, DuplicateEntry>();
244//              var Set<String> taggedEntries = new HashSet<String>();
245//             
246//              var List<Rule> allRules = EbnfAnalysisUtils.getAllRules(bnf);
247//             
248//              for(rule: allRules){
249//                      var List<SingleDefinition> subrules = rule.definitionList.singleDefinition
250//                      for(subrule:subrules){
251//                              var String subruleText = NodeModelUtils.findActualNodeFor(subrule).text.trim.replaceAll("[ \t\n\r]", "");
252//                             
253//                      }
254//              }
255//      }
256}
Note: See TracBrowser for help on using the repository browser.