Search code examples
javascriptparsingcompiler-constructionpeg

How open files with Peg.js?


How can I read the file within my language?

I am trying to understand how languages ​​work. I would like to know how to create a simple grammar to read files using Peg.js.
In Python it is something like this

f= open("testfile.txt","w+")

Grammar Example in Peg.js

{
   var keywords = ["f=", "open"];
}

Expression =
    word:$(Word) { return { word: word } } /
    keyword:$(Keyword) { return { keyword: keyword } }

// Word will match everything except "f" and "open"
Word = word:$([a-zA-Z]+) &{ return !keywords.includes(word) }

Keyword = [a-zA-Z]+

start
  = f open symbol

open
  = attribute:',"w+"'? __ { return write; }
  = attribute:'include'? __ { return include; }

include
  = include : "'_ exp:[a-zA-Z]+ _'" _ { return include; }

symbol
  = '("' _ exp:[a-zA-Z]+ _ '")' { return [ exp.join('') ]; }

// optional whitespace
_  = [ \t\r\n]*

// mandatory whitespace
__ = [ \t\r\n]+

But I get this error:

Line 21, column 3: Expected "/", ";", comment, end of input, end of line, identifier, or whitespace but "=" found.

Sample: Peg.js

f= open("testfile.txt","w+")

Solution

  • You're getting the syntax error because your definition of open contains two =s. I assume you want the second one to be a / instead. Then open would match either the string ,"w+" (or nothing) or include.

    That's not the only issue in your code though. Here are some others I've noticed:

    • Your first three rules and the other rules don't use each other. So if you're using Expression as your start rule (the default as it comes first), only the first three rules will matter. And if you use start as the start rule, the first three rules won't matter at all.
    • You list "f=" in your array of keywords and then check whether a string matching [a-zA-Z]+ is inside that array. But f= does not match that pattern, so having it in the array is pointless.
    • You define start as f open symbol, but f isn't defined anywhere.
    • "'_ exp:[a-zA-Z]+ _'" matches the literal string '_ exp:[a-zA-Z]+ _'. That is almost certainly not what you want.