Skip to content

Commit ebd4f32

Browse files
authored
Add files via upload
1 parent ed2ce78 commit ebd4f32

2 files changed

Lines changed: 140 additions & 30 deletions

File tree

src/main/java/cod/ast/ASTFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ public static EqualityChainNode createEqualityChain(ExprNode left, String operat
140140
return chain;
141141
}
142142

143+
public static BooleanChainNode createBooleanChain(boolean isAll, List<ExprNode> expressions) {
144+
BooleanChainNode node = new BooleanChainNode();
145+
node.isAll = isAll;
146+
node.expressions = expressions != null ? expressions : new ArrayList<ExprNode>();
147+
return node;
148+
}
149+
150+
143151
public static UnaryNode createUnaryOp(String op, ExprNode operand) {
144152
UnaryNode node = new UnaryNode();
145153
node.op = op;

src/main/java/cod/ast/ManualCoderiveParser.java

Lines changed: 132 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -558,12 +558,70 @@ private StatementNode parseExpressionStatement() {
558558
return expr;
559559
}
560560

561-
private ExprNode parseExpression() { return parseComparisonExpression(); }
561+
private ExprNode parseExpression() {
562+
if (match(ALL, ANY)) {
563+
return parseBooleanChain();
564+
}
565+
return parseComparisonExpression();
566+
}
567+
568+
569+
private ExprNode parseBooleanChain() {
570+
Token startToken = currentToken();
571+
Token typeToken = consume();
572+
boolean isAll = typeToken.type == ALL;
573+
if (match(ID)) {
574+
575+
ExprNode arrayExpr = ASTFactory.createIdentifier(consume().text);
576+
577+
if (match(EQ, NEQ, GT, LT, GTE, LTE)) {
578+
Token op = consume();
579+
580+
ExprNode right = parseAdditiveExpression();
581+
582+
List<ExprNode> chainArgs = new ArrayList<ExprNode>();
583+
chainArgs.add(right);
584+
585+
EqualityChainNode chain = ASTFactory.createEqualityChain(arrayExpr, op.text, isAll, chainArgs);
586+
setNodePosition(chain, startToken);
587+
return chain;
588+
} else {
589+
throw new ParseError("Expected comparison operator after 'all/any <arrayName>' but found " +
590+
getTypeName(currentToken().type) + " ('" + currentToken().text +
591+
"') at line " + currentToken().line + ":" + currentToken().column);
592+
}
593+
} else {
594+
consume(LBRACKET);
595+
List<ExprNode> expressions = new ArrayList<ExprNode>();
596+
597+
if (!match(RBRACKET)) {
598+
expressions.add(parseExpression());
599+
if (!match(COMMA) && !match(RBRACKET)) {
600+
throw new ParseError("Boolean chain requires at least two expressions or a comma after the first expression.");
601+
}
602+
while (tryConsume(COMMA)) {
603+
expressions.add(parseExpression());
604+
}
605+
}
606+
consume(RBRACKET);
607+
BooleanChainNode node = ASTFactory.createBooleanChain(isAll, expressions);
608+
if (node != null) {
609+
node.setSourcePosition(startToken.line, startToken.column);
610+
}
611+
return node;
612+
}
613+
}
562614

563615
private ExprNode parseComparisonExpression() {
564616
Token startToken = currentToken();
565617
ExprNode left = parseAdditiveExpression();
566618

619+
// --- NEW: Check for reverse equality chain (e.g., 'x == any[...]') ---
620+
if (match(EQ, NEQ, GT, LT, GTE, LTE) && isEqualityChainReverse()) {
621+
Token op = consume();
622+
return parseEqualityChain(left, op.text);
623+
}
624+
567625
if (match(EQ, NEQ, GT, LT, GTE, LTE)) {
568626
Token op = consume();
569627

@@ -578,27 +636,53 @@ private ExprNode parseComparisonExpression() {
578636
return left;
579637
}
580638

581-
private ExprNode parseEqualityChain(ExprNode left, String operator) {
639+
private ExprNode parseEqualityChain(ExprNode left, String operator) {
582640
Token startToken = currentToken();
583641
Token chainTypeToken = consume();
584642
boolean isAllChain = chainTypeToken.type == ALL;
585643

586-
consume(LPAREN);
644+
// --- UPDATED: Looking for LBRACKET instead of LPAREN ---
645+
consume(LBRACKET);
587646

588647
List<ExprNode> chainArgs = new ArrayList<ExprNode>();
589-
if (!match(RPAREN)) {
648+
// --- UPDATED: Looking for RBRACKET instead of RPAREN ---
649+
if (!match(RBRACKET)) {
590650
chainArgs.add(parseChainArgument());
591651
while (tryConsume(COMMA)) {
592652
chainArgs.add(parseChainArgument());
593653
}
594654
}
595-
consume(RPAREN);
655+
// --- UPDATED: Consuming RBRACKET instead of RPAREN ---
656+
consume(RBRACKET);
596657

597658
EqualityChainNode chain = ASTFactory.createEqualityChain(left, operator, isAllChain, chainArgs);
598659
setNodePosition(chain, startToken);
599660
return chain;
600661
}
601662

663+
private MethodCallNode parseConditionalChainCall(MethodCallNode call) {
664+
Token chainTypeToken = consume();
665+
boolean isAllChain = chainTypeToken.type == ALL;
666+
call.chainType = isAllChain ? "all" : "any";
667+
668+
// --- UPDATED: Mandate LBRACKET and RBRACKET for chain arguments ---
669+
consume(LBRACKET);
670+
671+
List<ExprNode> chainArgs = new ArrayList<ExprNode>();
672+
if (!match(RBRACKET)) {
673+
chainArgs.add(parseChainArgument());
674+
while (tryConsume(COMMA)) {
675+
chainArgs.add(parseChainArgument());
676+
}
677+
}
678+
679+
// --- UPDATED: Consume RBRACKET ---
680+
consume(RBRACKET);
681+
682+
call.chainArguments = chainArgs;
683+
return call;
684+
}
685+
602686
private ExprNode parseAdditiveExpression() {
603687
Token startToken = currentToken();
604688
ExprNode left = parseMultiplicativeExpression();
@@ -732,29 +816,6 @@ private MethodCallNode parseMethodCall() {
732816
return call;
733817
}
734818

735-
private MethodCallNode parseConditionalChainCall(MethodCallNode call) {
736-
Token chainTypeToken = consume();
737-
boolean isAllChain = chainTypeToken.type == ALL;
738-
call.chainType = isAllChain ? "all" : "any";
739-
740-
boolean hasParens = tryConsume(LPAREN);
741-
742-
List<ExprNode> chainArgs = new ArrayList<ExprNode>();
743-
if (!match(RPAREN)) {
744-
chainArgs.add(parseChainArgument());
745-
while (tryConsume(COMMA)) {
746-
chainArgs.add(parseChainArgument());
747-
}
748-
}
749-
750-
if (hasParens) {
751-
consume(RPAREN);
752-
}
753-
754-
call.chainArguments = chainArgs;
755-
return call;
756-
}
757-
758819
private ExprNode parseChainArgument() {
759820
if (match(BANG)) {
760821
consume(BANG);
@@ -921,9 +982,50 @@ private boolean isIndexAssignment() {
921982
int p = position; try { if (tokens.get(p++).type != ID) return false; if (p >= tokens.size() || tokens.get(p++).type != LBRACKET) return false; int bd = 1; while (p < tokens.size() && bd > 0) { if (tokens.get(p).type == LBRACKET) bd++; else if (tokens.get(p).type == RBRACKET) bd--; p++; } if (bd != 0) return false; while (p < tokens.size() && tokens.get(p).type == LBRACKET) { p++; bd = 1; while (p < tokens.size() && bd > 0) { if (tokens.get(p).type == LBRACKET) bd++; else if (tokens.get(p).type == RBRACKET) bd--; p++; } if (bd != 0) return false; } return p < tokens.size() && tokens.get(p).type == ASSIGN; } catch (IndexOutOfBoundsException e) { return false; }
922983
}
923984

924-
private boolean isMethodCallFollows() {
925-
int p = position; try { if (tokens.get(p).type != ID) return false; p++; while(p < tokens.size() && tokens.get(p).type == DOT) { p++; if (p >= tokens.size() || tokens.get(p).type != ID) return false; p++; } return p < tokens.size() && tokens.get(p).type == LPAREN; } catch (IndexOutOfBoundsException e) { return false; }
985+
private boolean isMethodCallFollows() {
986+
int p = position;
987+
try {
988+
if (tokens.get(p).type != ID) return false;
989+
p++;
990+
while(p < tokens.size() && tokens.get(p).type == DOT) {
991+
p++;
992+
if (p >= tokens.size() || tokens.get(p).type != ID) return false;
993+
p++;
994+
}
995+
if (p >= tokens.size() || tokens.get(p).type != LPAREN) return false;
996+
p++;
997+
998+
if (p < tokens.size() && (tokens.get(p).type == ALL || tokens.get(p).type == ANY)) {
999+
p++;
1000+
return p < tokens.size() && tokens.get(p).type == LBRACKET;
1001+
}
1002+
1003+
return true;
1004+
} catch (IndexOutOfBoundsException e) {
1005+
return false;
1006+
}
9261007
}
1008+
1009+
// --- NEW: Helper for reverse equality chain ---
1010+
private boolean isEqualityChainReverse() {
1011+
int p = position;
1012+
try {
1013+
// Check for Operator
1014+
if (tokens.get(p).type != EQ && tokens.get(p).type != NEQ &&
1015+
tokens.get(p).type != GT && tokens.get(p).type != LT &&
1016+
tokens.get(p).type != GTE && tokens.get(p).type != LTE) return false;
1017+
p++;
1018+
1019+
// Check for ALL/ANY followed by LBRACKET
1020+
if (tokens.get(p).type != ALL && tokens.get(p).type != ANY) return false;
1021+
p++;
1022+
1023+
return tokens.get(p).type == LBRACKET;
1024+
} catch (IndexOutOfBoundsException e) {
1025+
return false;
1026+
}
1027+
}
1028+
9271029

9281030
private boolean isReturnSlotAssignment() {
9291031
int p = position; try { if (tokens.get(p++).type != ID) return false; while (p < tokens.size() && tokens.get(p).type == COMMA) { p++; if (p >= tokens.size() || tokens.get(p++).type != ID) return false; } if (p >= tokens.size() || tokens.get(p++).type != ASSIGN) return false; if (p >= tokens.size() || tokens.get(p++).type != LBRACKET) return false;

0 commit comments

Comments
 (0)