/^/
EasyProgramming4 min read

Function Call / Name Regex

Matches a simple function-call-shaped string: a valid identifier immediately followed by a parenthesized, non-nested argument list, such as foo() or add(a, b).

#function#identifier#programming#syntax#parsing

Regex Pattern

^[A-Za-z_][A-Za-z0-9_]*\([^)]*\)$

Pattern Breakdown

Hover over a token to see what it does.

^[A-Za-z_][A-Za-z0-9_]*\([^)]*\)$
TokenMeaning
^Anchors the match to the start of the string
[A-Za-z_]The function name must begin with a letter or underscore
[A-Za-z0-9_]*Zero or more letters, digits, or underscores complete the function name
\(A literal opening parenthesis that starts the argument list
[^)]*Zero or more characters that are not a closing parenthesis, capturing the argument list
\)$A literal closing parenthesis anchored to the end of the string, closing the call

Detailed Explanation

What it does

This pattern recognizes text that looks like a function call or definition signature: a valid identifier directly followed by parentheses that may contain a flat (non-nested) list of arguments, such as calculateTotal(a, b) or init(). It rejects a bare identifier with no parentheses and rejects unbalanced or unterminated parentheses.

Why it works

The identifier portion reuses the standard rule that a name starts with a letter or underscore and continues with word characters. Immediately after, \( requires an actual opening parenthesis, [^)]* greedily consumes everything up to (but not including) the next closing parenthesis to represent the argument list, and \)$ demands that a closing parenthesis be the very last character, guaranteeing the call is properly closed at the end of the string.

Common use cases

  • Quickly detecting function-call-shaped tokens while scanning log lines, stack traces, or source snippets
  • Extracting a lightweight list of function invocations from a script for documentation or analytics tooling
  • Validating that a user-entered formula or macro string like SUM(a, b) has correctly balanced call syntax
  • Building a simple syntax highlighter rule that flags identifier(...) sequences

Edge cases

  • An empty argument list, like foo(), matches because [^)]* allows zero characters
  • Arguments with internal parentheses, like foo(a, (b)), fail to match because [^)]* cannot cross a nested closing parenthesis
  • Whitespace inside the parentheses, like add( a, b ), is accepted since [^)]* allows any non-')' character including spaces
  • A bare identifier with no parentheses at all, like foo, is rejected since the parenthesized group is mandatory, not optional

Limitations

  • Cannot handle nested function calls or parenthesized expressions inside the argument list, such as sum(max(a, b), c)
  • Does not validate that the arguments themselves are syntactically correct expressions, only that they avoid ')'
  • Only matches a single call expression for the entire string; it is not designed to extract multiple calls from a larger source file without additional scanning logic

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

foo() calculateTotal(a, b) _init()

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const functionCallRegex = /^[A-Za-z_][A-Za-z0-9_]*\([^)]*\)$/;
console.log(functionCallRegex.test('calculateTotal(a, b)')); // true

Common Mistakes

Expecting this pattern to handle nested calls like outer(inner(x)), which fail because [^)]* stops at the first closing parenthesis

Fix: Use a real parser or a recursive-descent tokenizer for expressions with nested parentheses; regex alone cannot count arbitrary nesting depth

Forgetting the parentheses are mandatory, then being surprised that a bare identifier like foo does not match

Fix: If you want to match either a bare name or a call, wrap the parenthesized part in an optional group: (?:\([^)]*\))?

Using .* instead of [^)]* inside the parentheses, which greedily swallows the closing parenthesis and matches across multiple calls

Fix: Restrict the argument-list class to [^)]* so it stops at the very next ')' instead of the last one in the string

Performance Notes

  • The [^)]* class is a negated single-character class, so it advances in linear time with no catastrophic backtracking risk
  • Anchoring with ^ and $ lets the engine reject non-call strings quickly, often after the first mismatched character
  • Because nesting is not supported, this pattern is intentionally simple and fast rather than a full expression parser

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes