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

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

initial commit

File size: 6.9 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
16//import java.util.HashMap
17//import java.util.Set
18//import java.util.HashSet
19
20//import org.eclipse.xtext.validation.Check
21/**
22 * Custom validation rules.
23 *
24 * see http://www.eclipse.org/Xtext/documentation.html#validation
25 */
26class EbnfValidator extends AbstractEbnfValidator {
27
28        static final String ruleReferencedOneDescription = "The rule is only referenced by one other rule";
29        static final String passthroughRuleDescription = "The rule is a passthrough rule";
30        static final String unreferencedPassthroughRuleDescription = "The rule is an unreferenced passthrough rule";
31        static final String unusedRuleDescription = "The rule is not referenced anywhere";
32        static final String equalAlternativeDescription = "The rule contains equal alternatives";
33        static final String duplicateRulesDescription = "The rule is a duplicate";
34        //       static final String duplicateSubRulesDescription = "A part the of rule is a duplicate";
35        static final String nonUniqueNameDescription = "The rule has the same Name as the Rule in Line ";
36
37        // ----------------------------------------------------------------------------------------------------
38        /* Checks if a rule is only referenced by one other Rule, e.g.:
39                 * a ::= b
40                 * b ::= "foo"
41                 */
42        @Check
43        def void checkReferencedOnlyOnce(Rule rule) {
44
45                if (EbnfAnalysisUtils.isTokenRule(rule))
46                        return;
47
48                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
49
50                if (references.size() == 1 && rule.rulenumber != 1) {
51                        warning(ruleReferencedOneDescription, EbnfPackage$Literals::RULE__NAME);
52                }
53        }
54
55        // ----------------------------------------------------------------------------------------------------
56        /*Checks if a a rule has the same definition as another rule e.g.:
57         * a ::= "test"
58         * b ::= "test"
59         * (Problem: does not check if there is a permutation)
60         */
61        @Check
62        def void checkDuplicateRules(Rule rule) {
63
64                //load bnf
65                var EtsiBnf etsiBnf = rule.eContainer().eContainer() as EtsiBnf;
66
67                // find the rule in the parsetree
68                var ICompositeNode definitionList = NodeModelUtils.findActualNodeFor(rule.getDefinitionList());
69
70                //get the definitionList as  formatted string
71                var String rightHandSideText = definitionList.text.trim().replaceAll("[ \t\n\r]", "");
72
73                //get All Rules
74                var List<Rule> allRules = EbnfAnalysisUtils.getAllRules(etsiBnf);
75
76                // run through all Rules
77                for (currentRule : allRules) {
78                        if (currentRule != rule) {
79                                var ICompositeNode currentRuleDefinitionList = NodeModelUtils.findActualNodeFor(
80                                        currentRule.getDefinitionList());
81                                var String currentRuleRightHandSideText = currentRuleDefinitionList.text.trim().replaceAll("[ \t\n\r]",
82                                        "");
83
84                                if (currentRuleRightHandSideText.equals(rightHandSideText)) {
85                                        var String description = duplicateRulesDescription + " with rule \"" + currentRule.getName() +
86                                                "\" (Line " + NodeModelUtils.findActualNodeFor(currentRule).getStartLine() + ")";
87                                        warning(description, EbnfPackage$Literals::RULE__NAME);
88                                }
89                        }
90                }
91        }
92
93        // ----------------------------------------------------------------------------------------------------
94        /*Checks if a Rule got the same Name as another Rule, e.g.:
95         * a ::= "foo"
96         * a ::= "bar"
97         */
98        @Check
99        def void checkNameIsUnique(Rule rule) {
100                val EtsiBnf bnf = rule.eContainer.eContainer as EtsiBnf;
101                for (r : EbnfAnalysisUtils.getAllRules(bnf)) {
102                        if (rule.name.equals(r.name)) {
103                                if (!r.equals(rule)) {
104                                        error(nonUniqueNameDescription + NodeModelUtils.findActualNodeFor(r).startLine,
105                                                EbnfPackage$Literals::RULE__NAME)
106
107                                }
108                        }
109                }
110        }
111
112        // ----------------------------------------------------------------------------------------------------
113        /*Checks if a Rule, except for the #1 is not referenced, e.g.:
114         * a::= b
115         * b::="foo"
116         * c ::= "bar"
117         */
118        @Check
119        def void checkUnusedRule(Rule rule) {
120
121                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
122
123                if ((references.size() == 0) && (rule.getRulenumber() != 1))
124                        warning(unusedRuleDescription, EbnfPackage$Literals::RULE__NAME);
125        }
126
127        // ----------------------------------------------------------------------------------------------------
128        /*Checks if a rule got two equal alternatives, e.g.:
129         * a ::= b | "foo" | b
130         *(Problem:ignores whitespaces in literals)
131         */
132        @Check
133        def void checkEqualAlternative(Rule rule) {
134
135                var DefinitionList definitionList = rule.definitionList;
136
137                var List<SingleDefinition> singleDefinitions = definitionList.singleDefinition;
138
139                for (sDef1 : singleDefinitions) {
140                        for (sDef2 : singleDefinitions) {
141                                if (!sDef1.equals(sDef2)) {
142                                        var String d1 = NodeModelUtils.findActualNodeFor(sDef1).text.trim.replaceAll("[ \t\n\r]", "");
143                                        var String d2 = NodeModelUtils.findActualNodeFor(sDef2).text.trim.replaceAll("[ \t\n\r]", "");
144
145                                        if (d1.equals(d2))
146                                                warning(equalAlternativeDescription, EbnfPackage$Literals::RULE__NAME,equalAlternativeDescription);
147                                }
148                        }
149                }
150
151        }
152
153        // ----------------------------------------------------------------------------------------------------
154        /* Checks if a rule gets just passed through, e.g.:
155         * a ::= b | "literal"
156         * b ::= c
157         * c ::= "foo.bar"
158         */
159        @Check
160        def void checkPassthroughRule(Rule rule) {
161
162                var List<RuleReference> references = EbnfAnalysisUtils.findReferences(rule);
163
164                if (EbnfAnalysisUtils.isPassthroughRule(rule)) {
165                        if (references.size() == 0) {
166                                warning(unreferencedPassthroughRuleDescription, EbnfPackage$Literals::RULE__NAME);
167                        } else {
168                                warning(passthroughRuleDescription, EbnfPackage$Literals::RULE__NAME,passthroughRuleDescription);
169                        }
170                }
171        }
172
173
174        // ----------------------------------------------------------------------------------------------------
175        /* Checks if a subrule is used more then once, e.g.:
176         * a ::= (a b) e
177         * b ::= (a b) d
178         *       _____
179         * (Not working, under construction)
180         */
181//      @Check
182//      def void checkSubruleDuplicates(EtsiBnf bnf){
183//              var HashMap<String, DuplicateEntry> dupesMap = new HashMap<String, DuplicateEntry>();
184//              var Set<String> taggedEntries = new HashSet<String>();
185//             
186//              var List<Rule> allRules = EbnfAnalysisUtils.getAllRules(bnf);
187//             
188//              for(rule: allRules){
189//                      var List<SingleDefinition> subrules = rule.definitionList.singleDefinition
190//                      for(subrule:subrules){
191//                              var String subruleText = NodeModelUtils.findActualNodeFor(subrule).text.trim.replaceAll("[ \t\n\r]", "");
192//                             
193//                      }
194//              }
195//      }
196}
Note: See TracBrowser for help on using the repository browser.