Pyparsing 是一个python写的很好的DSL语法解析器

Element

  • Word / Literal
Word(nums)
Word(alphas + "_")
...
Literal("=")
Literal("&&")
Literal("(").suppress()
  • Forward
expr = Forword()
atom = (Word(num) | '(' + expr + ')')
expr << atom + ('+' | '-') + atom
  • ZeroOrMore / OneOrMore / delimitedList
complexStmt = stmt + ZeroOrMore(Group(";" + stmt))
complexStmt = delimitedList(stmt, ";")
  • Optional / Combine
signNumber = Combine(Optional("-") + number)

Example

我自己写的streem的parser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
plusorminus = Literal('+') | Literal('-')
point = Literal('.')
number = Word(nums)
integer = Combine( Optional(plusorminus) + number ).setParseAction(lambda t: int(t[0]))
floatnumber = Combine( integer + Optional( point + number ) ).setParseAction(lambda t: float(t[0]))

lpar  = Literal( "(" ).suppress()
rpar  = Literal( ")" ).suppress()
assign = Literal( "=" ).suppress()

normalVariable = Word(string.ascii_uppercase, alphanums + '_').setParseAction(lambda t: Variable(t[0]))
specialVariable = Literal(ISYMBOL).setParseAction(lambda t: KVariable(t[0]))
pipeVarialble = Literal("INPUT").setParseAction(lambda t: Input(t[0]))
variable = (pipeVarialble | specialVariable | normalVariable)
funcName = Word(string.ascii_lowercase, alphanums + '_').setParseAction(lambda t: FuncName(t[0]))
constant = (integer | floatnumber | quotedString.setParseAction(lambda t: t[0][1:-1])).setParseAction(lambda t : Constant(t[0]))

addop = plusorminus
multop = Literal("*") | Literal("/") | Literal("%")

expr = Forward()
funcCall = Forward()
atom = (constant | funcCall | variable | ( lpar + expr + rpar )).setParseAction(lambda t: Atom(t[0]))
term = Group(atom.setResultsName("left") + ZeroOrMore(( Group(multop.setResultsName("op") + atom.setResultsName("atom")))).setResultsName("right")).setParseAction(lambda t: Term(t[0]))
expr << Group(term.setResultsName("left") + ZeroOrMore( ( Group(addop.setResultsName("op") + term.setResultsName("term")))).setResultsName("right")).setParseAction(lambda t: Expr(t[0]))

funcCall << Group(funcName.setResultsName("name") + lpar + delimitedList(expr).setResultsName("params") + rpar).setParseAction(lambda t: FuncCall(t[0]))

assignStmt = Group(variable.setResultsName("key") + assign + expr.setResultsName("value")).setParseAction(lambda t: AssignStmt(t[0]))
simpleStmt = ( assignStmt | expr )
complexFunc = Group(delimitedList(variable).setResultsName("args") + Suppress("->") + delimitedList(simpleStmt, ';').setResultsName("stmts")).setParseAction(lambda t: Func(t[0]))

func = (complexFunc | expr | funcName)

funcSep = (Literal('|=') | Literal('|'))

#codeContent = delimitedList(func, funcSep).setResultsName("blocks").setParseAction(lambda t: CodeContent(t))
codeContent = Group(func.setResultsName("left") + ZeroOrMore(Group(funcSep.setResultsName("op") + func.setResultsName("func"))).setResultsName("right")).setParseAction(lambda t: CodeContent(t[0]))

这个解析器可以解析streem类语言

eg:

range(4) |= str | echo
===>
['1', '2', '3', '4']