Search code examples
javascriptparsinggrammarpegpegjs

How to describe function arguments in PEG grammar


I'm still fighting with ambiguous grammar of Qt's qmake.

Now I can't find a way to describe function arguments that can contain parenthesis (e.g. regex):

functionName(arg1, "arg2", ^(arg3)+$)

I've tried to describe function call like this:

FunctionCall = Identifier space* "(" space* FunctionArgumentList? space* ")" space* eol*

FunctionArgumentList = FunctionArgumentString ((space* "," space* FunctionArgumentString)* / (blank* FunctionArgumentString)*)
FunctionArgumentString = ReplaceFunctionCall / TestFunctionCall / EnquotedString / RegularFunctionArgumentString
RegularFunctionArgumentString = RegularFunctionArgumentStringChar+
RegularFunctionArgumentStringChar = !(")" / blank / "," / quote / doublequote) SourceCharacter
SourceCharacter <- [\u0000-\uFFFC]

How do I add support for embedded parenthesis WITHOUT quotes/double quotes in such grammar? How do I distinguish the parenthesis inside function arguments and function closing one?

Valid function call example:

contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*)

Solution

  • Well, i found a pretty hacky solution myself:
    just look further for a next statement.
    Here is a simplified grammar fragment using this way:

    FunctionCall = Identifier _* "(" _* FunctionArgumentList? _* ")" _*
    FunctionArgumentList = CommaSeparatedList / FunctionArgument
    CommaSeparatedList = FunctionArgument (COMMA_WS FunctionArgument?)+
    
    FunctionArgument = FunctionArgumentImpl FunctionArgumentImpl*
    FunctionArgumentImpl = EnquotedString / FunctionArgumentString
    FunctionArgumentString = FunctionArgumentStringChar+
    FunctionArgumentStringChar = !(COMMA / QUOTE / DOUBLEQUOTE / EndOfFunction) SourceCharacter
    
    EndOfFunction = ")" _* (
         eoi / eol
        / "=" / "+=" / "*=" / "-=" / "~="
        / "," / "." / "_"
        / "(" / ")"
        "{" / "}" / ":" / "|"
    )
    
    COMMA_WS = _ "," _
    COMMA = ","
    QUOTE = "'"
    DOUBLEQUOTE = '"'
    BACKSLASH = "\\"
    _ = [ \t]
    

    Hope this will be useful for somebody.