UNPKG

4.78 kBJavaScriptView Raw
1import Expression from './expression';
2import RRLoop from '../ui/rrloop';
3import RRSequence from '../ui/rrsequence';
4import RuleReference from './rulereference';
5import Repetition from './repetition';
6import Literal from './literal';
7import GrammarToRRDiagram from './grammartorrdiagram';
8import RRElement from '../ui/rrelement';
9import GrammarToBNF from './grammartobnf';
10
11export default class Sequence extends Expression {
12
13 /**
14 * @param {(Expression | Expression[])} expressions
15 */
16 constructor(expressions) {
17 super();
18 if (arguments.length == 0) {
19 expressions = [];
20 } else if (expressions.constructor !== Array) {
21 expressions = arguments;
22 }
23 this.expressions = expressions;
24 }
25
26 /**
27 * @param {Expression[]}
28 */
29 getExpressions() {
30 return this.expressions;
31 }
32
33 /**
34 * @param {GrammarToRRDiagram} grammarToRRDiagram
35 * @return {RRElement}
36 */
37 toRRElement(grammarToRRDiagram) {
38 const rrElementList = [];
39 for (let i = 0; i < this.expressions.length; i++) {
40 const expression = this.expressions[i];
41 let rrElement = expression.toRRElement(grammarToRRDiagram);
42 // Treat special case of: "a (',' a)*" and "a (a)*"
43 if (i < this.expressions.length - 1 && this.expressions[i + 1] instanceof Repetition) {
44 const repetition = this.expressions[i + 1];
45 const repetitionExpression = repetition.getExpression();
46 if (repetitionExpression instanceof Sequence) {
47 // Treat special case of: "expr (',' expr)*"
48 const subExpressions = repetitionExpression.getExpressions();
49 if (subExpressions.length == 2 && subExpressions[0] instanceof Literal) {
50 if(expression.equals(subExpressions[1])) {
51 const maxRepetitionCount = repetition.getMaxRepetitionCount();
52 if (maxRepetitionCount == null || maxRepetitionCount > 1) {
53 rrElement = new RRLoop(expression.toRRElement(grammarToRRDiagram), subExpressions[0].toRRElement(grammarToRRDiagram), repetition.getMinRepetitionCount(), (maxRepetitionCount == null ? null : maxRepetitionCount));
54 i++;
55 }
56 }
57 }
58 } else if(expression instanceof RuleReference) {
59 const ruleLink = expression;
60 // Treat special case of: a (a)*
61 if (repetitionExpression instanceof RuleReference && repetitionExpression.getRuleName().equals(ruleLink.getRuleName())) {
62 const maxRepetitionCount = repetition.getMaxRepetitionCount();
63 if (maxRepetitionCount == null || maxRepetitionCount > 1) {
64 rrElement = new RRLoop(ruleLink.toRRElement(grammarToRRDiagram), null, repetition.getMinRepetitionCount(), (maxRepetitionCount == null ? null : maxRepetitionCount));
65 i++;
66 }
67 }
68 }
69 }
70 rrElementList.push(rrElement);
71 }
72 return new RRSequence(rrElementList);
73 }
74
75 /**
76 * @param {GrammarToBNF} grammarToBNF
77 * @param {string[]} sb
78 * @param {boolean} isNested
79 */
80 toBNF(grammarToBNF, sb, isNested) {
81 if (this.expressions.length == 0) {
82 sb.push("( )");
83 return;
84 }
85 if (isNested && this.expressions.length > 1) {
86 sb.push("( ");
87 }
88 const isCommaSeparator = grammarToBNF.isCommaSeparator;
89 for (let i = 0; i < this.expressions.length; i++) {
90 if (i > 0) {
91 if (isCommaSeparator) {
92 sb.push(" ,");
93 }
94 sb.push(" ");
95 }
96 this.expressions[i].toBNF(grammarToBNF, sb, this.expressions.length == 1 && isNested || !isCommaSeparator);
97 }
98 if (isNested && this.expressions.length > 1) {
99 sb.push(" )");
100 }
101 }
102
103 /**
104 * @param {*} o
105 * @return {boolean}
106 */
107 equals(o) {
108 if(!(o instanceof Sequence)) {
109 return false;
110 }
111 if(this.expressions.length != o.expressions.length) {
112 return false;
113 }
114 for (let i = 0; i < this.expressions.length; i++) {
115 if(!this.expressions[i].equals(o.expressions[i])) {
116 return false;
117 }
118 }
119 return true;
120 }
121
122}