Any python module for customized BNF parser?

2024/10/11 18:25:37

friends.

I have a 'make'-like style file needed to be parsed. The grammar is something like:

samtools=/path/to/samtools
picard=/path/to/picardtask1: des: descriptionpath: /path/to/task1para: [$global.samtools,$args.input,$path]task2: task1

Where $global contains the variables defined in a global scope. $path is a 'local' variable. $args contains the key/pair values passed in by users.

I would like to parse this file by some python libraries. Better to return some parse tree. If there are some errors, better to report them. I found this one: CodeTalker and yeanpypa. Can they be used in this case? Any other recommendations?

Answer

I had to guess what your makefile structure allows based on your example, but this should get you close:

from pyparsing import *
# elements of the makefile are delimited by line, so we must
# define skippable whitespace to include just spaces and tabs
ParserElement.setDefaultWhitespaceChars(' \t')
NL = LineEnd().suppress()EQ,COLON,LBRACK,RBRACK = map(Suppress, "=:[]")
identifier = Word(alphas+'_', alphanums)symbol_assignment = Group(identifier("name") + EQ + empty + restOfLine("value"))("symbol_assignment")
symbol_ref = Word("$",alphanums+"_.")def only_column_one(s,l,t):if col(l,s) != 1:raise ParseException(s,l,"not in column 1")
# task identifiers have to start in column 1
task_identifier = identifier.copy().setParseAction(only_column_one)task_description = "des:" + empty + restOfLine("des")
task_path = "path:" + empty + restOfLine("path")
task_para_body = delimitedList(symbol_ref)
task_para = "para:" + LBRACK + task_para_body("para") + RBRACK
task_para.ignore(NL)
task_definition = Group(task_identifier("target") + COLON + Optional(delimitedList(identifier))("deps") + NL +(Optional(task_description + NL) & Optional(task_path + NL) & Optional(task_para + NL)))("task_definition")makefile_parser = ZeroOrMore(symbol_assignment |task_definition |NL)if __name__ == "__main__":test = """\
samtools=/path/to/samtools
picard=/path/to/picardtask1:  des: description path: /path/to/task1 para: [$global.samtools, $args.input, $path ] task2: task1 
"""# dump out what we parsed, including results names
for element in makefile_parser.parseString(test):print element.getName()print element.dump()print

Prints:

symbol_assignment
['samtools', '/path/to/samtools']
- name: samtools
- value: /path/to/samtoolssymbol_assignment
['picard', '/path/to/picard']
- name: picard
- value: /path/to/picardtask_definition
['task1', 'des:', 'description ', 'path:', '/path/to/task1 ', 'para:', '$global.samtools', '$args.input', '$path']
- des: description 
- para: ['$global.samtools', '$args.input', '$path']
- path: /path/to/task1 
- target: task1task_definition
['task2', 'task1']
- deps: ['task1']
- target: task2

The dump() output shows you what names you can use to get at the fields within the parsed elements, or to distinguish what kind of element you have. dump() is a handy, generic tool to output whatever pyparsing has parsed. Here is some code that is more specific to your particular parser, showing how to use the field names as either dotted object references (element.target, element.deps, element.name, etc.) or dict-style references (element[key]):

for element in makefile_parser.parseString(test):if element.getName() == 'task_definition':print "TASK:", element.target,if element.deps:print "DEPS:(" + ','.join(element.deps) + ")"else:printfor key in ('des', 'path', 'para'):if key in element:print " ", key.upper()+":", element[key]elif element.getName() == 'symbol_assignment':print "SYM:", element.name, "->", element.value

prints:

SYM: samtools -> /path/to/samtools
SYM: picard -> /path/to/picard
TASK: task1DES: description PATH: /path/to/task1 PARA: ['$global.samtools', '$args.input', '$path']
TASK: task2 DEPS:(task1)
https://en.xdnf.cn/q/118292.html

Related Q&A

How to draw an histogram with multiple categories in python

I am a freshman in python, and I have a problem of how to draw a histogram in python.First of all, I have ten intervals that are divided evenly according to the length of flowers petal, from min to max…

Turtle in Tkinter creating multiple windows

I am attempting to create a quick turtle display using Tkinter, but some odd things are happening.First two turtle windows are being created, (one blank, one with the turtles), secondly, any attempt of…

Array tkinter Entry to Label

Hey Guys I am beginner and working on Project Linear and Binary search GUI application using Tkinter, I want to add multiple Entry boxes values to label and in an array here, I tried but its not workin…

Grid search and cross validation SVM

i am implementing svm using best parameter of grid search on 10fold cross validation and i need to understand prediction results why are different i got two accuracy results testing on training set not…

Accessing dynamically created tkinter widgets

I am trying to make a GUI where the quantity of tkinter entries is decided by the user.My Code:from tkinter import*root = Tk()def createEntries(quantity):for num in range(quantity):usrInput = Entry(roo…

Graphene-Django Filenaming Conventions

Im rebuilding a former Django REST API project as a GraphQL one. I now have queries & mutations working properly.Most of my learning came from looking at existing Graphene-Django & Graphene-Py…

Summing up CSV power plant data by technology and plant name

Ive got a question regarding the Form 860 data about US power plants.It is organized block-wise and not plant-wise. To become useful, the capacity numbers must be summed up.How may I get the total capa…

Send and receive signals from another class pyqt

I am needing a way to receive signals sent by a Class to another class. I have 2 classes: In my first class I have a function that emits a signal called asignal In my second class I call the first cla…

I can not add many values in one function

I have a gui applicationI put text into text box1, text box2,………… text box70 ,and then click on the pushButton, The function return_text () in the module_b.py be called. Now I can call one instance…

Close browser popup in Selenium Python

I am scraping a page using Selenium, Python. On opening the page one Popup appears. I want to close this popup anyway. I tried as below:url = https://shopping.rochebros.com/shop/categories/37browser = …