fix(pp): #xcommand/#xtranslate patterns with paren-attached keyword
Real Harbour headers write parameterised commands with no space between the keyword and its opening paren: #xcommand MAKE_TEST( <obj>, <v> ) => ... ParseRule stored the rule keyword as `MAKE_TEST(` (stripping only <>, [] marker wrappers), but firstToken normalised source lines by stopping the first-word scan at `(` — so `MAKE_TEST( o, 42 )` produced `MAKE_TEST` for the lookup. The two strings didn't match and the fast-path keyword check rejected every invocation, leaving the macro unexpanded and the call site as a bare undeclared identifier. Trim everything from the first `(` onward during keyword extraction so both halves agree on the dispatch key. The marker tokens inside the parens are still parsed normally by parseMarkers / matchPattern. Verified with /tmp/test_xcmd2.prg (`MAKE_TEST( o, 99 )` expands and dispatches to the object's :hVar access). FiveSql2 43/43, Harbour compat 56/56, Go test ALL PASS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,13 +81,19 @@ func ParseRule(directive string, isCommand, caseSens bool) *Rule {
|
||||
ResultTmpl: result,
|
||||
}
|
||||
|
||||
// Extract first keyword for fast matching
|
||||
// Extract first keyword for fast matching. The first whitespace-
|
||||
// delimited token of the pattern becomes the dispatch key; we
|
||||
// strip marker wrappers and any trailing `(` so a pattern like
|
||||
// `MAKE_TEST( <obj>, <v> )` hashes on `MAKE_TEST`, matching how
|
||||
// firstToken normalises source lines.
|
||||
words := strings.Fields(pattern)
|
||||
if len(words) > 0 {
|
||||
kw := words[0]
|
||||
// Remove marker brackets
|
||||
kw = strings.TrimLeft(kw, "<[")
|
||||
kw = strings.TrimRight(kw, ">]")
|
||||
if idx := strings.IndexByte(kw, '('); idx >= 0 {
|
||||
kw = kw[:idx]
|
||||
}
|
||||
if !strings.ContainsAny(kw, "!*,:") {
|
||||
rule.Keyword = kw
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user