Skip to content

twxs/peg-cmake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

peg-cmake

Build Status

peg-cmake is a simple CMake parser written in javascript. It aims to provide a core lib for tools such as formatting, refactoring, etc...

The library is under developement and not stable.

Usage

npm install peg-cmake

var CMake = require('peg-cmake');
var fs = require('fs');

function traversAST(ast, matcher) {
   ast.forEach((element)=>{
       if(matcher[element.type])
       matcher[element.type](element);
   });
}

fs.readFile('CMakeLists.txt', 'utf8', function (err,data) {
 if (!err) {
   try {
       var ast = CMake.parse(data);
       // print all functions defined in the script
       function FunctionsVisitor() {
             this._func = (elt)=>{
              console.log("- " +elt.identifier + " : line:" + elt.location.start.line )
             }
             this.macro = this._func;
             this.function = this._func;
             this.if=(elt)=>{
               traversAST(elt.body, this);
               elt.elseif.foreach((e)=>{traversAST(elt.body, this);});      
               if(elt.else)traversAST(elt.else.body, this);
             }
       };
       traversAST(result, new FindFunctions());
   }catch(e) {
       console.log(e.name + " line " + e.location.start.line 
       + ", " + e.location.start.column
       + "\n"+ e.message);
   }
 }
});

AST

The the parse result is an array of node. Each node owns at least a type which can be one of the following :

  • "bracket_argument"
  • "bracket_comment"
  • "command_invocation"
  • "foreach"
  • "function"
  • "identifier"
  • "if"
  • "line_comment"
  • "macro"
  • "newline"
  • "quoted_argument"
  • "script"
  • "unquoted_argument"
  • "while"

and a location :

   {
       "start": {
           "offset": 31,
           "line": 1,
           "column": 32
       },
      "end": {
           "offset": 43,
           "line": 1,
           "column": 44
       }
   }
**Type** **CMake** **ASTNode**
`line_comment`
# A single line comment
   
{
    "type": "line_comment",
    "value": " A single line comment"
}
  
`bracket_comment`
#[[This is a bracket comment.
It runs until the close bracket.]]
message("1st Arg\n" #[[Bracket Comment]] "2nd Arg")

{
    "type": "bracket_comment",
    "value": "Bracket Comment"
}
  
`newline`
{
    "type":'newline'
}
`command_invocation`
message(FATAL "Hello")
{
    "type": "command_invocation", 
    "name": "message", 
    "arguments": [
        { "type" = "unquoted_argument" /*...*/ },
        { "type" = "quoted_argument" /*...*/ }
        ]
}
`bracket_argument`
message([=[
This is the first line in a 
bracket argument with bracket length 1.
No \-escape sequences or ${variable}
references are evaluated.
This is always one argument even
 though it contains a ; character.
The text does not end on a closing
 bracket of length 0 like ]].
It does end in a closing bracket
 of length 1.
]=])
 {
     "type": "bracket_argument", 
     "value": "This is [...] of length 1.",
     "len": 1
 }
`if`
if(TRUE)
elseif(PREDICATE)
else()
endif()
 {
     "type": "if", 
     "predicate" : [{"type":"unquoted_argument", "value":"TRUE"}],
     "body": [],
     "elseif" : [
         {
             "predicate" : [{"type":"unquoted_argument", "value":"PREDICATE"}],
             "body": []
         }
     ],
     "else" : {
        "predicate" : [{"type":"unquoted_argument", "value":"TRUE"}],
        "body": []
     }
 }
`function`
function(my_func ARG)
# body
endfunction()
{
    "type": "function", 
    "identifier": {type:"identifier", value:"my_func"}, 
    "arguments": [ {"type": "unquoted_argument" /*, ...*/} ]
    "body": [
        { "type" = "line_comment" /*...*/ }
        ]
}
`macro`
macro(my_macro ARG)
# body
endmacro()
{
    "type": "macro", 
    "name": "my_macro", 
    "arguments": [ {"type": "unquoted_argument" /*, ...*/} ]
    "body": [
        { "type" = "line_comment" /*...*/ }
        ]
}
`foreach`
foreach(F ${FILES})
# body
endforeach()
{
    "arguments": [ {"type": "unquoted_argument", "value": "F"}, 
                   {"type": "unquoted_argument", "value": "${FILES}"} ]
    "body": [
        { "type" = "line_comment" /*...*/ }
        ]
}
`while`
while(F ${FILES})
# body
endwhile()
{
    "arguments": [ {"type": "unquoted_argument", "value": "F"}, 
                   {"type": "unquoted_argument", "value": "${FILES}"} ]
    "body": [
        { "type" = "line_comment" /*...*/ }
        ]
}

Release notes

0.0.6

  • fix :
CMake versions prior to 2.8.12 silently accept an Unquoted Argument or a Quoted Argument immediately following a Quoted Argument and not separated by any whitespace. For compatibility, CMake 2.8.12 and higher accept such code but produce a warning.
  • add experimental cmake formater

Known Issues

  • Thes buffer must end with "\n", as a workaround the parse function append a new line to the buffer passed as argument.