• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

leeonky / test-charm-java / 290

08 Sep 2025 03:25PM UTC coverage: 74.312% (-0.003%) from 74.315%
290

push

circleci

leeonky
Introduce PropertyWriterDecorator

10 of 25 new or added lines in 6 files covered. (40.0%)

20 existing lines in 10 files now uncovered.

8155 of 10974 relevant lines covered (74.31%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.5
/DAL-java/src/main/java/com/github/leeonky/dal/compiler/Compiler.java
1
package com.github.leeonky.dal.compiler;
2

3
import com.github.leeonky.dal.ast.node.*;
4
import com.github.leeonky.dal.ast.node.table.*;
5
import com.github.leeonky.dal.ast.node.text.*;
6
import com.github.leeonky.dal.ast.opt.DALOperator;
7
import com.github.leeonky.dal.runtime.RuntimeContextBuilder.DALRuntimeContext;
8
import com.github.leeonky.interpreter.*;
9

10
import java.util.ArrayList;
11
import java.util.List;
12
import java.util.Optional;
13
import java.util.function.Function;
14

15
import static com.github.leeonky.dal.ast.node.DALExpression.expression;
16
import static com.github.leeonky.dal.ast.opt.Factory.exclamation;
17
import static com.github.leeonky.dal.compiler.Constants.PROPERTY_DELIMITER_STRING;
18
import static com.github.leeonky.dal.compiler.DALProcedure.*;
19
import static com.github.leeonky.interpreter.ClauseParser.Mandatory.clause;
20
import static com.github.leeonky.interpreter.ClauseParser.positionClause;
21
import static com.github.leeonky.interpreter.NodeParser.positionNode;
22
import static com.github.leeonky.interpreter.Parser.*;
23
import static com.github.leeonky.interpreter.Rules.*;
24
import static com.github.leeonky.interpreter.Syntax.many;
25
import static com.github.leeonky.interpreter.Syntax.single;
26
import static com.github.leeonky.util.function.When.when;
27
import static java.util.Optional.empty;
28

29
//TODO splite to sub classes
30
public class Compiler {
31
    private static final EscapeChars SINGLE_QUOTED_ESCAPES = new EscapeChars()
1✔
32
            .escape("\\\\", '\\')
1✔
33
            .escape("\\'", '\'');
1✔
34
    private static final EscapeChars DOUBLE_QUOTED_ESCAPES = new EscapeChars()
1✔
35
            .escape("\\\\", '\\')
1✔
36
            .escape("\\n", '\n')
1✔
37
            .escape("\\r", '\r')
1✔
38
            .escape("\\t", '\t')
1✔
39
            .escape("\\\"", '"');
1✔
40
    private static final EscapeChars REGEX_ESCAPES = new EscapeChars()
1✔
41
            .escape("\\/", '/');
1✔
42

43
    //    TODO private
44
    NodeParser<DALNode, DALProcedure>
1✔
45
            PROPERTY, OBJECT, SORTED_LIST, LIST, PARENTHESES, VERIFICATION_SPECIAL_OPERAND, VERIFICATION_VALUE_OPERAND,
46
            TABLE, SHORT_VERIFICATION_OPERAND, CELL_VERIFICATION_OPERAND, GROUP_PROPERTY, OPTIONAL_PROPERTY_CHAIN,
47
            OBJECT_VERIFICATION_PROPERTY,
48
            ROOT_INPUT = procedure -> when(procedure.isCodeBeginning()).optional(() -> InputNode.Root.INSTANCE),
1✔
49
            NUMBER = Tokens.NUMBER.nodeParser(NodeFactory::constNumber),
1✔
50
            INTEGER = Tokens.INTEGER.nodeParser(NodeFactory::constInteger),
1✔
51
            SINGLE_QUOTED_STRING = Notations.SINGLE_QUOTED.with(many(charNode(SINGLE_QUOTED_ESCAPES))
1✔
52
                    .and(endWith(Notations.SINGLE_QUOTED.getLabel())).as(NodeFactory::constString)),
1✔
53
            DOUBLE_QUOTED_STRING = Notations.DOUBLE_QUOTED.with(many(charNode(DOUBLE_QUOTED_ESCAPES))
1✔
54
                    .and(endWith(Notations.DOUBLE_QUOTED.getLabel())).as(NodeFactory::constString)),
1✔
55
            TEXT_BLOCK = positionNode(many(Notations.TEXT_BLOCK).and(atLeast(3)).as(TextBlockNotationNode::new))
1✔
56
                    .concat(clause(this::textAttribute)).concat(clause(node -> many(charNode(new EscapeChars()))
1✔
57
                            .and(endWithPosition(((NotationAttributeNode) node).endNotation()))
1✔
58
                            .as(ls -> new TextBlockNode((NotationAttributeNode) node, ls)))),
1✔
59
            STRING = oneOf(TEXT_BLOCK, SINGLE_QUOTED_STRING, DOUBLE_QUOTED_STRING),
1✔
60
            CONST_TRUE = Notations.Keywords.TRUE.wordNode(NodeFactory::constTrue, PROPERTY_DELIMITER_STRING),
1✔
61
            CONST_FALSE = Notations.Keywords.FALSE.wordNode(NodeFactory::constFalse, PROPERTY_DELIMITER_STRING),
1✔
62
            CONST_NULL = Notations.Keywords.NULL.wordNode(NodeFactory::constNull, PROPERTY_DELIMITER_STRING),
1✔
63
            REGEX = Notations.OPEN_REGEX.with(many(charNode(REGEX_ESCAPES))
1✔
64
                    .and(endWith(Notations.CLOSE_REGEX.getLabel())).as(NodeFactory::regex)),
1✔
65
            WILDCARD = Notations.Operators.WILDCARD.node(WildcardNode::new),
1✔
66
            ROW_WILDCARD = Notations.Operators.ROW_WILDCARD.node(WildcardNode::new),
1✔
67
            CONST = oneOf(STRING, CONST_TRUE, CONST_FALSE, CONST_NULL, this::compileUserDefinedLiteral, NUMBER),
1✔
68
            ELEMENT_ELLIPSIS = Notations.Operators.ELEMENT_ELLIPSIS.node(token -> new ListEllipsisNode()),
1✔
69
            SCHEMA = Tokens.SCHEMA.nodeParser(NodeFactory::schema),
1✔
70
            INTEGER_OR_STRING = oneOf(INTEGER, STRING),
1✔
71
            STRING_PROPERTY = procedure -> procedure.isEnableRelaxProperty() ? single(STRING)
1✔
72
                    .as(NodeFactory::stringSymbol).parse(procedure) : empty(),
1✔
73
            NUMBER_PROPERTY = procedure -> procedure.isEnableNumberProperty() ? single(NUMBER)
1✔
74
                    .as(NodeFactory::numberSymbol).parse(procedure) : empty(),
1✔
75
            SYMBOL = procedure -> (procedure.isEnableRelaxProperty() ? Tokens.RELAX_SYMBOL : Tokens.SYMBOL)
1✔
76
                    .nodeParser(NodeFactory::symbolNode).parse(procedure),
1✔
77
            TEXT_ATTRIBUTE = Tokens.RELAX_SYMBOL.nodeParser(t -> new TextBlockAttributeNode(t.getContent())),
1✔
78
            DOT_SYMBOL = procedure -> (procedure.isEnableRelaxProperty() ? Tokens.RELAX_DOT_SYMBOL : Tokens.DOT_SYMBOL)
1✔
79
                    .nodeParser(NodeFactory::symbolNode).parse(procedure),
1✔
80
            META_SYMBOL = Tokens.DOT_SYMBOL.nodeParser(NodeFactory::metaSymbolNode),
1✔
81
            PROPERTY_PATTERN = this::propertyPattern,
82
            OPTIONAL_VERIFICATION_PROPERTY = lazyNode(() -> enableSlashProperty(enableRelaxProperty(OPTIONAL_PROPERTY_CHAIN))),
1✔
83
            CONST_REMARK;
84

85
    private NodeParser.Mandatory<DALNode, DALProcedure> textAttribute(DALNode notationNode) {
86
        return many(TEXT_ATTRIBUTE).and(endWithLine()).as(attributes ->
1✔
87
                new NotationAttributeNode((TextBlockNotationNode) notationNode, new TextBlockAttributeListNode(attributes)));
1✔
88
    }
89

90
    private Optional<DALNode> propertyPattern(DALProcedure dalProcedure) {
91
        ClauseParser<DALNode, DALProcedure> patternClause =
1✔
92
                Notations.THIS.clause((token, symbol) -> new PropertyPattern(symbol));
1✔
93
        return oneOf(Notations.THIS.node(n -> new PropertyThis()), SYMBOL.with(patternClause)).parse(dalProcedure);
1✔
94
    }
95

96
    public NodeParser.Mandatory<DALNode, DALProcedure>
1✔
97
            PROPERTY_CHAIN, OPERAND, EXPRESSION, VERIFICATION_PROPERTY,
98
            DEFAULT_INPUT = procedure -> new InputNode.StackInput(procedure.getRuntimeContext()),
1✔
99
            SCHEMA_COMPOSE = Notations.OPENING_BRACKET.with(single(many(SCHEMA.mandatory("Expect a schema"))
1✔
100
                    .and(splitBy(Notations.SCHEMA_AND)).as(NodeFactory::elementSchemas))
1✔
101
                    .and(endWith(Notations.CLOSING_BRACKET)).as()).or(many(SCHEMA.mandatory("Expect a schema"))
1✔
102
                    .and(splitBy(Notations.SCHEMA_AND)).as(NodeFactory::schemas)),
1✔
103
            EXPRESSION_RELAX_STRING = Tokens.EXPRESSION_RELAX_STRING.nodeParser(NodeFactory::relaxString),
1✔
104
            OBJECT_SCOPE_RELAX_STRING = Tokens.OBJECT_SCOPE_RELAX_STRING.nodeParser(NodeFactory::relaxString),
1✔
105
            LIST_SCOPE_RELAX_STRING = Tokens.LIST_SCOPE_RELAX_STRING.nodeParser(NodeFactory::relaxString),
1✔
106
            TABLE_CELL_RELAX_STRING = Tokens.TABLE_CELL_RELAX_STRING.nodeParser(NodeFactory::relaxString),
1✔
107
            BRACKET_RELAX_STRING = Tokens.BRACKET_RELAX_STRING.nodeParser(NodeFactory::relaxString),
1✔
108
            DEFAULT_INDEX_HEADER = procedure -> new DefaultIndexColumnHeaderRow(),
1✔
109
            DATA_REMARK = positionNode(many(charNode(new EscapeChars())).and(endWith(Notations.CLOSING_PARENTHESES.getLabel())).
1✔
110
                    as(NodeFactory::dataRemarkNode));
1✔
111

112
    public ClauseParser<DALNode, DALProcedure>
1✔
113
            ARITHMETIC_CLAUSE, VERIFICATION_CLAUSE,
114
            SCHEMA_CLAUSE = Operators.IS.clause(SCHEMA_COMPOSE),
1✔
115
            WHICH_CLAUSE = lazyClause(() -> Operators.WHICH.clause(EXPRESSION)),
1✔
116
            ELEMENT_ELLIPSIS_CLAUSE = Notations.Operators.ELEMENT_ELLIPSIS.clause((token, input) -> new ListEllipsisNode()),
1✔
117
            ROW_WILDCARD_CLAUSE = Notations.Operators.ROW_WILDCARD.clause((token, input) -> new WildcardNode(token.getContent())),
1✔
118
            LIST_MAPPING_CLAUSE = Notations.LIST_MAPPING.clause((token, symbolNode) -> new ListMappingNode(symbolNode)),
1✔
119
            EXCLAMATION_CLAUSE = positionNode(many(Notations.Operators.EXCLAMATION).and(atLeast(1)).as(ExclamationNode::new)
1✔
120
                    .notStartWith(Notations.Operators.NOT_EQUAL)).clause((n1, n2) -> expression(n1, exclamation(), n2)),
1✔
121
            DATA_REMARK_CLAUSE = Operators.DATA_REMARK.clause(DATA_REMARK),
1✔
122
            PROPERTY_POSTFIX = oneOf(EXCLAMATION_CLAUSE, DATA_REMARK_CLAUSE),
1✔
123
            META_LIST_MAPPING_CLAUSE = Notations.LIST_MAPPING.clause((token, symbolNode) -> new ListMappingNodeMeta(symbolNode)),
1✔
124
            IMPLICIT_PROPERTY_CLAUSE = Operators.PROPERTY_IMPLICIT.clause(oneOf(PROPERTY_PATTERN,
1✔
125
                    oneOf(STRING_PROPERTY, NUMBER_PROPERTY, SYMBOL).concat(LIST_MAPPING_CLAUSE))).concatAll(PROPERTY_POSTFIX),
1✔
126
            EXPLICIT_PROPERTY_CLAUSE = oneOf(Operators.PROPERTY_DOT.clause(PROPERTY_PATTERN.or(propertyChainNode())),
1✔
127
                    Operators.PROPERTY_SLASH.clause(propertyChainNode()),
1✔
128
                    Operators.PROPERTY_META.clause(symbolClause(META_SYMBOL.concat(META_LIST_MAPPING_CLAUSE))),
1✔
129
                    Operators.PROPERTY_IMPLICIT.clause(Notations.OPENING_BRACKET.with(single(INTEGER_OR_STRING.or(BRACKET_RELAX_STRING))
1✔
130
                            .and(endWith(Notations.CLOSING_BRACKET))
1✔
131
                            .as(NodeFactory::bracketSymbolNode).concat(LIST_MAPPING_CLAUSE))),
1✔
132
                    Operators.PROPERTY_IMPLICIT.clause(lazyNode(() -> GROUP_PROPERTY))).concatAll(PROPERTY_POSTFIX);
1✔
133

134
    private NodeParser.Mandatory<DALNode, DALProcedure> propertyChainNode() {
135
        return symbolClause(oneOf(STRING_PROPERTY, DOT_SYMBOL, NUMBER_PROPERTY).concat(LIST_MAPPING_CLAUSE));
1✔
136
    }
137

138
    private NodeParser.Mandatory<DALNode, DALProcedure> symbolClause(
139
            NodeParser<DALNode, DALProcedure> nodeParser) {
140
        return nodeParser.mandatory("Expect a symbol");
1✔
141
    }
142

143
    private ClauseParser.Mandatory<DALNode, DALProcedure> shortVerificationClause(
144
            OperatorParser.Mandatory<DALRuntimeContext, DALNode, DALOperator, DALProcedure, DALExpression> operatorMandatory,
145
            NodeParser.Mandatory<DALNode, DALProcedure> operand) {
146
        return SCHEMA_CLAUSE.concat(Operators.VERIFICATION_OPERATORS.clause(operand)).or(operatorMandatory.clause(operand));
1✔
147
    }
148

149
    private ClauseParser<DALNode, DALProcedure> objectVerificationClauseChain(
150
            OperatorParser<DALRuntimeContext, DALNode, DALOperator, DALProcedure, DALExpression> operator,
151
            NodeParser.Mandatory<DALNode, DALProcedure> operand) {
152
        return oneOf(SCHEMA_CLAUSE.concat(Operators.VERIFICATION_OPERATORS.clause(operand)), operator.clause(operand));
1✔
153
    }
154

155
    private ClauseParser<DALNode, DALProcedure> ARITHMETIC_CLAUSE_CHAIN, VERIFICATION_CLAUSE_CHAIN,
156
            EXPLICIT_PROPERTY_CHAIN, WHICH_CLAUSE_CHAIN, SCHEMA_CLAUSE_CHAIN, EXPRESSION_CLAUSE;
157

158
    public Compiler() {
1✔
159
        PARENTHESES = lazyNode(() -> enableCommaAnd(Notations.OPENING_PARENTHESES.with(single(EXPRESSION).and(endWith(Notations.CLOSING_PARENTHESES))
1✔
160
                .as(NodeFactory::parenthesesNode))));
1✔
161
        PROPERTY = DEFAULT_INPUT.with(oneOf(EXPLICIT_PROPERTY_CLAUSE, IMPLICIT_PROPERTY_CLAUSE));
1✔
162
        OPTIONAL_PROPERTY_CHAIN = PROPERTY.concatAll(EXPLICIT_PROPERTY_CLAUSE);
1✔
163
        PROPERTY_CHAIN = OPTIONAL_PROPERTY_CHAIN.mandatory("Expect a object property");
1✔
164
        VERIFICATION_PROPERTY = enableNumberProperty(enableRelaxProperty(enableSlashProperty(PROPERTY_CHAIN)));
1✔
165
        OBJECT_VERIFICATION_PROPERTY = many(VERIFICATION_PROPERTY).and(atLeast(1)).and(splitBy(Notations.COMMA))
1✔
166
//                TODO miss test for error message
167
                .and(endWith(this::verificationNotations, () -> "Expect a verification operator")).as(NodeFactory::createVerificationGroup);
1✔
168
        OBJECT = lazyNode(() -> disableCommaAnd(Notations.OPENING_BRACES.with(single(ELEMENT_ELLIPSIS).and(endWith(Notations.CLOSING_BRACES))
1✔
169
                .as(ObjectScopeNode::new).or(many(OBJECT_VERIFICATION_PROPERTY.concat(shortVerificationClause(Operators.VERIFICATION_OPERATORS
1✔
170
                                .mandatory("Expect operator `:` or `=`"), SHORT_VERIFICATION_OPERAND.or(OBJECT_SCOPE_RELAX_STRING)))
1✔
171
                        .concatAll(objectVerificationClauseChain(Operators.VERIFICATION_OPERATORS, SHORT_VERIFICATION_OPERAND.or(OBJECT_SCOPE_RELAX_STRING))))
1✔
172
                        .and(optionalSplitBy(Notations.COMMA)).and(endWith(Notations.CLOSING_BRACES)).as(ObjectScopeNode::new)))));
1✔
173
        SORTED_LIST = oneOf(Notations.Operators.PLUS.before(pureList(ListScopeNode::sortedNaturalOrder)),
1✔
174
                Notations.Operators.SUBTRACTION.before(pureList(ListScopeNode::sortedReverseOrder)));
1✔
175
        LIST = oneOf(pureList(ListScopeNode::new), SORTED_LIST);
1✔
176
        TABLE = oneOf(Notations.TRANSPOSE_MARK.with(EMPTY_TRANSPOSED_HEAD.with(transposeTable())),
1✔
177
                positionNode(Notations.COLUMN_SPLITTER.before(Notations.TRANSPOSE_MARK.before(Notations.COLUMN_SPLITTER.before(tableLine(ROW_PREFIX)
1✔
178
                        .as(TransposedRowHeaderRow::new))))).concat(transposeTable()),
1✔
179
                positionNode(Notations.COLUMN_SPLITTER.before(tableLine(TABLE_HEADER).as(ColumnHeaderRow::new))).concat(TABLE_BODY_CLAUSE),
1✔
180
                positionNode(Notations.MATRIX_COLUMN_SPLITTER.before(DEFAULT_INDEX_HEADER).concat(TABLE_BODY_CLAUSE)));
1✔
181
        VERIFICATION_SPECIAL_OPERAND = oneOf(REGEX, OBJECT, LIST, WILDCARD, TABLE);
1✔
182
        CONST_REMARK = CONST.concat(PARENTHESES.clause(NodeFactory::constRemarkNode));
1✔
183
        OPERAND = lazyNode(() -> oneOf(CONST_REMARK, Operators.UNARY_OPERATORS.unary(OPERAND), PROPERTY, PARENTHESES, ROOT_INPUT))
1✔
184
                .mandatory("Expect a value or expression");
1✔
185
        VERIFICATION_VALUE_OPERAND = oneOf(CONST_REMARK, Operators.UNARY_OPERATORS.unary(OPERAND), DEFAULT_INPUT.with(EXPLICIT_PROPERTY_CLAUSE), PARENTHESES);
1✔
186
        ARITHMETIC_CLAUSE = Operators.BINARY_ARITHMETIC_OPERATORS.clause(OPERAND);
1✔
187
        VERIFICATION_CLAUSE = Operators.VERIFICATION_OPERATORS.clause(oneOf(VERIFICATION_SPECIAL_OPERAND,
1✔
188
                VERIFICATION_VALUE_OPERAND).or(EXPRESSION_RELAX_STRING));
1✔
189
        ARITHMETIC_CLAUSE_CHAIN = lazyClause(() -> ARITHMETIC_CLAUSE.concat(EXPRESSION_CLAUSE));
1✔
190
        VERIFICATION_CLAUSE_CHAIN = lazyClause(() -> VERIFICATION_CLAUSE.concat(EXPRESSION_CLAUSE));
1✔
191
        EXPLICIT_PROPERTY_CHAIN = lazyClause(() -> EXPLICIT_PROPERTY_CLAUSE.concat(EXPRESSION_CLAUSE));
1✔
192
        WHICH_CLAUSE_CHAIN = lazyClause(() -> WHICH_CLAUSE.concat(EXPRESSION_CLAUSE));
1✔
193
        SCHEMA_CLAUSE_CHAIN = lazyClause(() -> SCHEMA_CLAUSE.concat(oneOf(VERIFICATION_CLAUSE_CHAIN,
1✔
194
                WHICH_CLAUSE_CHAIN, SCHEMA_CLAUSE_CHAIN)));
195
        EXPRESSION_CLAUSE = oneOf(ARITHMETIC_CLAUSE_CHAIN, VERIFICATION_CLAUSE_CHAIN, EXPLICIT_PROPERTY_CHAIN,
1✔
196
                WHICH_CLAUSE_CHAIN, SCHEMA_CLAUSE_CHAIN);
197
        EXPRESSION = OPERAND.concat(EXPRESSION_CLAUSE);
1✔
198
        SHORT_VERIFICATION_OPERAND = oneOf(VERIFICATION_SPECIAL_OPERAND, VERIFICATION_VALUE_OPERAND
1✔
199
                .concatAll(oneOf(ARITHMETIC_CLAUSE, EXPLICIT_PROPERTY_CLAUSE)));
1✔
200
        CELL_VERIFICATION_OPERAND = single(oneOf(oneOf(REGEX, OBJECT, LIST, WILDCARD), VERIFICATION_VALUE_OPERAND
1✔
201
                .concatAll(oneOf(ARITHMETIC_CLAUSE, EXPLICIT_PROPERTY_CLAUSE)))).and(enabledBefore(Notations.COLUMN_SPLITTER)).as();
1✔
202
        GROUP_PROPERTY = disableCommaAnd(Notations.OPENING_GROUP.with(many(VERIFICATION_PROPERTY)
1✔
203
                .and(optionalSplitBy(Notations.COMMA)).and(endWith(Notations.CLOSING_GROUP)).as(GroupExpression::new)));
1✔
204
    }
1✔
205

206
    private boolean verificationNotations(DALProcedure procedure) {
207
        SourceCode sourceCode = procedure.getSourceCode();
1✔
208
        return sourceCode.startsWith(Notations.Operators.EQUAL)
1✔
209
                || sourceCode.startsWith(Notations.Operators.MATCHER, Notations.Operators.META.getLabel())
1✔
210
                || Notations.Operators.IS.postfix(Constants.PROPERTY_DELIMITER).stream().anyMatch(sourceCode::startsWith);
1✔
211
    }
212

213
    private NodeParser<DALNode, DALProcedure> pureList(Function<List<Clause<DALNode>>, DALNode> factory) {
214
        return lazyNode(() -> disableCommaAnd(Notations.OPENING_BRACKET.with(many(ELEMENT_ELLIPSIS_CLAUSE.or(
1✔
215
                shortVerificationClause(Operators.VERIFICATION_OPERATORS.or(Operators.DEFAULT_VERIFICATION_OPERATOR),
1✔
216
                        SHORT_VERIFICATION_OPERAND.or(LIST_SCOPE_RELAX_STRING)))).and(optionalSplitBy(Notations.COMMA))
1✔
217
                .and(endWith(Notations.CLOSING_BRACKET)).as(factory))));
1✔
218
    }
219

220
    public List<DALNode> compile(SourceCode sourceCode, DALRuntimeContext DALRuntimeContext) {
221
        return new ArrayList<DALNode>() {{
1✔
222
            DALProcedure dalParser = new DALProcedure(sourceCode, DALRuntimeContext);
1✔
223
            add(EXPRESSION.parse(dalParser));
1✔
224
            if (sourceCode.isBeginning() && sourceCode.hasCode())
1✔
UNCOV
225
                throw sourceCode.syntaxError("Unexpected token", 0);
×
226
            while (sourceCode.hasCode())
1✔
227
                add(EXPRESSION.parse(dalParser));
1✔
228
        }};
1✔
229
    }
230

231
    public List<Object> toChainNodes(String sourceCode) {
232
        return PROPERTY_CHAIN.parse(new DALProcedure(new SourceCode(sourceCode, Notations.LINE_COMMENTS),
1✔
233
                null)).propertyChain();
1✔
234
    }
235

236
    private final NodeParser<DALNode, DALProcedure>
1✔
237
            SEQUENCE_AZ = Notations.SEQUENCE_AZ.node(SortSymbolNode::new),
1✔
238
            SEQUENCE_ZA = Notations.SEQUENCE_ZA.node(SortSymbolNode::new),
1✔
239
            SEQUENCE_AZ_2 = Notations.SEQUENCE_AZ_2.node(SortSymbolNode::new),
1✔
240
            SEQUENCE_ZA_2 = Notations.SEQUENCE_ZA_2.node(SortSymbolNode::new),
1✔
241
            ROW_KEY = oneOf(INTEGER, OPTIONAL_VERIFICATION_PROPERTY);
1✔
242

243
    private final NodeParser.Mandatory<DALNode, DALProcedure>
1✔
244
            SEQUENCE = oneOf(
1✔
245
            many(SEQUENCE_AZ).and(atLeast(1)).as(SortGroupNode::new),
1✔
246
            many(SEQUENCE_AZ_2).and(atLeast(1)).as(SortGroupNode::new),
1✔
247
            many(SEQUENCE_ZA).and(atLeast(1)).as(SortGroupNode::new),
1✔
248
            many(SEQUENCE_ZA_2).and(atLeast(1)).as(SortGroupNode::new)).or(procedure -> SortGroupNode.noSequence()),
1✔
249
            EMPTY_TRANSPOSED_HEAD = procedure -> new EmptyTransposedRowHeaderRow();
1✔
250

251
    public ClauseParser<DALNode, DALProcedure> ROW_HEADER_CLAUSE = oneOf(DATA_REMARK_CLAUSE, SCHEMA_CLAUSE, EXCLAMATION_CLAUSE)
1✔
252
            .concatAll(oneOf(DATA_REMARK_CLAUSE, SCHEMA_CLAUSE, EXCLAMATION_CLAUSE));
1✔
253

254
    private final NodeParser.Mandatory<DALNode, DALProcedure>
1✔
255
            ROW_PREFIX = procedure -> new RowHeader(ROW_KEY.parse(procedure), ROW_HEADER_CLAUSE.parse(procedure),
1✔
256
            Operators.VERIFICATION_OPERATORS.parse(procedure)),
1✔
257
            TABLE_HEADER = procedure -> new ColumnHeader((SortGroupNode) SEQUENCE.parse(procedure),
1✔
258
                    VERIFICATION_PROPERTY.concat(SCHEMA_CLAUSE).parse(procedure),
1✔
259
                    Operators.VERIFICATION_OPERATORS.parse(procedure));
1✔
260

261
    private final ClauseParser.Mandatory<DALNode, DALProcedure>
1✔
262
            TABLE_BODY_CLAUSE = procedure -> head -> new TableNode((ColumnHeaderRow) head, (Body) many(ROW_PREFIX.with(oneOf(
1✔
263
            Notations.COLUMN_SPLITTER.before(singleCellRow(ELEMENT_ELLIPSIS, (ColumnHeaderRow) head)),
1✔
264
            Notations.COLUMN_SPLITTER.before(singleCellRow(ROW_WILDCARD, (ColumnHeaderRow) head)),
1✔
265
            Notations.COLUMN_SPLITTER.before(tableRow((ColumnHeaderRow) head, procedure.getRuntimeContext())))))
1✔
266
            .and(endWithOptionalLine()).as(Body::new).parse(procedure));
1✔
267

268
    private ClauseParser<DALNode, DALProcedure> singleCellRow(NodeParser<DALNode, DALProcedure> nodeParser,
269
                                                              ColumnHeaderRow head) {
270
        return single(single(nodeParser).and(endWith(Notations.COLUMN_SPLITTER)).as()).and(endWithLine()).as()
1✔
271
                .clause((prefix, cell) -> new Row(prefix, cell, head));
1✔
272
    }
273

274
    private ClauseParser.Mandatory<DALNode, DALProcedure> tableCell(DALNode rowPrefix, ColumnHeaderRow head,
275
                                                                    DALRuntimeContext context) {
276
        return positionClause(ClauseParser.<DALNode, DALProcedure>
1✔
277
                columnMandatory(column -> shortVerificationClause(oneOf(Operators.VERIFICATION_OPERATORS,
1✔
278
                head.getHeader(column, context).operator(), ((RowHeader) rowPrefix).operator()).or(
1✔
279
                Operators.DEFAULT_VERIFICATION_OPERATOR), CELL_VERIFICATION_OPERAND.or(TABLE_CELL_RELAX_STRING))));
1✔
280
    }
281

282
    private ClauseParser.Mandatory<DALNode, DALProcedure> tableRow(ColumnHeaderRow columnHeaderRow,
283
                                                                   DALRuntimeContext context) {
284
        return clause(rowPrefix -> tableLine(tableCell(rowPrefix, columnHeaderRow, context))
1✔
285
                .as(cells -> new Row(rowPrefix, cells, columnHeaderRow)));
1✔
286
    }
287

288
    private ClauseParser.Mandatory<DALNode, DALProcedure> transposeTableCell(DALNode prefix, DALNode header) {
289
        return positionClause(ClauseParser.<DALNode, DALProcedure>
1✔
290
                columnMandatory(column -> oneOf(ELEMENT_ELLIPSIS_CLAUSE, ROW_WILDCARD_CLAUSE)
1✔
291
                .or(shortVerificationClause(oneOf(Operators.VERIFICATION_OPERATORS, ((ColumnHeader) prefix).operator(),
1✔
292
                        ((TransposedRowHeaderRow) header).getRowHeader(column).operator())
1✔
293
                        .or(Operators.DEFAULT_VERIFICATION_OPERATOR), CELL_VERIFICATION_OPERAND.or(TABLE_CELL_RELAX_STRING)))));
1✔
294
    }
295

296
    private ClauseParser.Mandatory<DALNode, DALProcedure> transposeTable() {
297
        return procedure -> header -> new TransposedTableNode(header, many(positionNode(Notations.COLUMN_SPLITTER.before(
1✔
298
                single(TABLE_HEADER).and(endWith(Notations.COLUMN_SPLITTER)).as())).concat(clause(prefix -> tableLine(
1✔
299
                transposeTableCell(prefix, header)).as(cells -> new TransposedRow(prefix, cells))))).and(atLeast(1))
1✔
300
                .and(endWithOptionalLine()).as(TransposedBody::new).mandatory("Expecting a table").parse(procedure));
1✔
301
    }
302

303
    private static Syntax<DALNode, DALProcedure, NodeParser<DALNode, DALProcedure>, NodeParser.Mandatory<DALNode,
304
            DALProcedure>, DALNode, NodeParser.Mandatory<DALNode, DALProcedure>, List<DALNode>> tableLine(
305
            NodeParser.Mandatory<DALNode, DALProcedure> mandatory) {
306
        return many(mandatory).and(mandatorySplitBy(Notations.COLUMN_SPLITTER)).and(endOfRow(Notations.COLUMN_SPLITTER));
1✔
307
    }
308

309
    private static Syntax<DALNode, DALProcedure, ClauseParser<DALNode, DALProcedure>, ClauseParser.Mandatory<DALNode,
310
            DALProcedure>, Clause<DALNode>, NodeParser.Mandatory<DALNode, DALProcedure>, List<Clause<DALNode>>> tableLine(
311
            ClauseParser.Mandatory<DALNode, DALProcedure> mandatory) {
312
        return many(mandatory).and(mandatorySplitBy(Notations.COLUMN_SPLITTER)).and(endOfRow(Notations.COLUMN_SPLITTER));
1✔
313
    }
314

315
    private Optional<DALNode> compileUserDefinedLiteral(DALProcedure dalProcedure) {
316
        return dalProcedure.getSourceCode().tryFetch(() -> Tokens.USER_LITERAL_SYMBOL.scan(dalProcedure.getSourceCode())
1✔
317
                .flatMap(token -> dalProcedure.getRuntimeContext().takeUserDefinedLiteral(token.getContent())
1✔
318
                        .map(result -> new ConstValueNode(result.getValue()).setPositionBegin(token.getPosition()))));
1✔
319
    }
320

321
    private ObjectParser.Mandatory<DALProcedure, Character> charNode(EscapeChars escapeChars) {
322
        return procedure -> procedure.getSourceCode().popChar(escapeChars);
1✔
323
    }
324
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc