# F-07 — Minor findings across multiple files

**Severity:** Minor / Observation  
**Category:** Consistency, correctness, and dead code  

---

## F-07a — `hashModeValidator.js`: Mixed token-stream and regex approach

**Lines:** 35 (token stream), 48 and 63 (regex)

ACU-SYN-003 (NOTE in HASH-ON context) is correctly implemented using the **token stream**:
```javascript
const { tokens } = buildDocumentAst(document);
// ... scan for HASH_PREFIX immediately followed by IDENTIFIER "NOTE"
```

ACU-SYN-001 (redundant HASH-ON) and the HASH-mode state tracking still use regex:
```javascript
if (/^\s*#?\s*HASH-ON\b/i.test(lineText)) { ... }
if (/^\s*#?\s*HASH-OFF\b/i.test(lineText)) { ... }
```

The AST has `HashOnDirective` and `HashOffDirective` nodes. These could replace the regex
detection for consistency. However, the ACU-SYN-001 logic also needs to track the **current
hash mode** across lines — this requires either the ECM or a sequential AST walk. The token
stream (which is also available here) does have `KEYWORD` tokens for `HASH-ON` / `HASH-OFF`
with correct positions.

**Recommendation:** Use the token stream for HASH-ON/HASH-OFF detection (consistent with
ACU-SYN-003). Scan tokens for `KEYWORD` tokens whose `value.toUpperCase()` is `"HASH-ON"`
or `"HASH-OFF"`. This gives exact column positions without regex. Tier 2.

---

## F-07b — `executionContext.js:isLikelyExecutableLine()`: `ELSEIF` in keyword regex is dead code

**Line:** 79

```javascript
if (/^(option|newinterpreter|var|set|if|elseif|else|endif|while|do|...) b/i.test(trimmed)) {
```

`ELSEIF` appears in this list but is not an Architect keyword. It was removed from the language
(see memory: ELSEIF removed 2026-04-06). The regex will never match it for valid code.

**Recommendation:** Remove `elseif` from the regex. Add a comment explaining that ELSEIF was
removed. Minor.

---

## F-07c — `functionValidator.js`: `ELSEIF` in `extractStandaloneCallName` exclusion list

**Line:** 56

```javascript
if (/^(set|if|elseif|while|until|do|case|value|otherwise|return|function|macro|var|...)\b/i.test(withoutHash)) {
    return null;
}
```

Same dead-code `ELSEIF` entry. Minor. Remove it when cleaning up `extractStandaloneCallName`.

---

## F-07d — `macroValidator.js`: regex to find macro name position on a known-macro line

**Lines:** 39–47

```javascript
const startPos = lowerLineText.indexOf("macro");
const nameMatch = lineText.substring(startPos).match(/macro\s+([A-Za-z_][A-Za-z0-9_]*)/i);
const nameStart = startPos + nameMatch.index + nameMatch[0].length - nameMatch[1].length;
```

This is needed to find the column of the macro name for the `ACU-MAC-001` diagnostic. The AST's
`MacroDeclaration` node has `name: string` and `line: number`, but not the column of the name
token directly. The name token's `char` position would give this directly from the token stream.

`documentFacts.buildMacroCatalogFromAst` has access to the AST node — it could be extended to
also store `nameChar: stmt.nameTok.char` if the AST parser is extended to record the name token.
Alternatively, since `MacroDeclaration.name` is a string with a known position in the statement,
the token at `macroDuplicates[i].lineIndex` that is type `IDENTIFIER` after the `MACRO` KEYWORD
gives the position.

**Recommendation:** Minor — accept the current regex as a position-finding fallback. When the
AST is extended to carry name token positions, update this. Observation level.

---

## F-07e — `parser.js` (old): `parseAssignment` indexOf may find wrong position (v1 residual)

**Status:** The v1 TRACKER marks this as "Done" but let's verify the current state.

```javascript
const prefixMatch = text.match(/^\s*#?\s*(?:SET\s+)?/);
const searchFrom = prefixMatch ? prefixMatch[0].length : 0;
const targetIndex = lineText.indexOf(target, searchFrom);
```

This is improved from v1 (it now searches from after the `SET` prefix). However, the search is
still on the original `lineText` (which may include the `//` comment text) rather than on `text`
(the comment-stripped version). If the target variable name appears in a trailing comment, and
the comment-stripped line has the target at a different position than the first match in the raw
line, `targetIndex` is still wrong.

This is now less critical because F-01/F-02/F-03 recommend replacing `parseAssignment` usage
with AST nodes. Once those are implemented, `parseAssignment` becomes unused and can be deleted.

**Recommendation:** Accept as-is. Marked for deletion when F-03 is applied.

---

## F-07f — `hashModeValidator.js:INCOMPLETE_ASSIGNMENT` — only used for ACU-SYN-006

**Line:** 117 (implied — grep shows `INCOMPLETE_ASSIGNMENT.test(effective)`)

This regex is used for ACU-SYN-006 (incomplete assignment — `SET x =` with no RHS). The AST's
`UnknownLine` nodes could surface this: a `SET` keyword followed by an identifier followed by
`=` but with nothing after would be parsed as an UnknownLine or a degenerate SetStatement.
However, the parser currently produces `UnknownLine` for lines that don't match the expected
pattern, which conflates all parse failures under one node type.

This is a case where the AST is genuinely less specific than the regex check — the AST doesn't
distinguish "incomplete assignment" from "other unknown line". ACU-SYN-006 as implemented in the
hashModeValidator using regex is therefore **correct current design** — not AST compensation.

**Recommendation:** Accept as-is. If the AST parser is extended to produce specific error nodes
(e.g. `MalformedAssignmentNode`), this could be revisited.
