请考虑以下代码段:
import sys
import textwrap
import re
from PyQt5.Qt import * # noqa
from PyQt5.Qsci import QsciScintilla
from PyQt5.Qsci import QsciLexerCustom
from lark import Lark, inline_args, Transformer
class LexerJson(QsciLexerCustom):
def __init__(self, parent=None):
super().__init__(parent)
self.create_grammar()
self.create_styles()
def create_styles(self):
deeppink = QColor(249, 38, 114)
khaki = QColor(230, 219, 116)
mediumpurple = QColor(174, 129, 255)
mediumturquoise = QColor(81, 217, 205)
yellowgreen = QColor(166, 226, 46)
lightcyan = QColor(213, 248, 232)
darkslategrey = QColor(39, 40, 34)
styles = {
0: mediumturquoise,
1: mediumpurple,
2: …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一种语法来解析我设计的一些类似于Excel的公式,其中字符串开头的特殊字符表示其他来源。例如,$可以表示一个字符串,因此“ $This is text”将被视为程序中的字符串输入,并且&可以表示一个函数,因此&foo()可以被视为对内部函数的调用foo。
我面临的问题是如何正确构建语法。例如,这是MWE的简化版本:
grammar = r'''start: instruction
?instruction: simple
| func
STARTSYMBOL: "!"|"#"|"$"|"&"|"~"
SINGLESTR: (LETTER+|DIGIT+|"_"|" ")*
simple: STARTSYMBOL [SINGLESTR] (WORDSEP SINGLESTR)*
ARGSEP: ",," // argument separator
WORDSEP: "," // word separator
CONDSEP: ";;" // condition separator
STAR: "*"
func: STARTSYMBOL SINGLESTR "(" [simple|func] (ARGSEP simple|func)* ")"
%import common.LETTER
%import common.WORD
%import common.DIGIT
%ignore ARGSEP
%ignore WORDSEP
'''
parser = lark.Lark(grammar, parser='earley')
Run Code Online (Sandbox Code Playgroud)
因此,这种语法之类的东西:$This is a string,&foo(), …
我正在尝试使用lark实现记录定义 DSL 。它基于缩进,这使事情变得更加复杂。
Lark 是一个很棒的工具,但我面临一些困难。
这是我正在实施的 DSL 片段:
record Order :
"""Order record documentation
should have arbitrary size"""
field1 Int
field2 Datetime:
"""Attributes should also have
multiline documentation"""
field3 String "inline documentation also works"
Run Code Online (Sandbox Code Playgroud)
这是使用的语法:
?start: (_NEWLINE | redorddef)*
simple_type: NAME
multiline_doc: MULTILINE_STRING _NEWLINE
inline_doc: INLINE_STRING
?element_doc: ":" _NEWLINE _INDENT multiline_doc _DEDENT | inline_doc
attribute_name: NAME
attribute_simple_type: attribute_name simple_type [element_doc] _NEWLINE
attributes: attribute_simple_type+
_recordbody: _NEWLINE _INDENT [multiline_doc] attributes _DEDENT
redorddef: "record" NAME ":" _recordbody
MULTILINE_STRING: /"""([^"\\]*(\\.[^"\\]*)*)"""/
INLINE_STRING: /"([^"\\]*(\\.[^"\\]*)*)"/ …Run Code Online (Sandbox Code Playgroud) 我正在解析一个文件,其格式可以包括:
INT32 price min 10 max 100 alertIfSold ;
Run Code Online (Sandbox Code Playgroud)
min、max 和alertIfSold 令牌都是可选的,并且可以按任何顺序出现。那是
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
Run Code Online (Sandbox Code Playgroud)
都是有效的例子。
下面是我正在测试的语法的简单版本。运行 python test.py 会生成此错误:
lark.common.ParseError:检测到无限递归!(规则 <__anon_star_1 : __anon_star_1>)
我尝试使用其他语法规则表达相同的可选标记,并获得类似的结果(无限递归)。
表达可选参数的正确语法是什么?
#test.py
from lark import lark
simplified_grammar = """
start: line+
line: TYPE CNAME [MIN MAX ALERT]* ";" -> foo
TYPE: "INT32" | "INT64"
MIN: "min" /[0-9]+/
MAX: "max" /[0-9]+/
ALERT: "alertIfSold"
%import common.CNAME
%import common.WS
%ignore WS …Run Code Online (Sandbox Code Playgroud) Lark 解析器预定义了一些常见的终端,包括一个字符串。它的定义如下:
_STRING_INNER: /.*?/
_STRING_ESC_INNER: _STRING_INNER /(?<!\\)(\\\\)*?/
ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""
Run Code Online (Sandbox Code Playgroud)
我明白_STRING_INNER。我也明白ESCAPED_STRING是如何组成的。但我真的不明白的是_STRING_ESC_INNER。
如果我正确阅读了正则表达式,它只是说每当我找到两个连续的文字反斜杠时,它们前面不能有另一个文字反斜杠?
如何将这两者组合成一个正则表达式?
语法是否只需要在字符串数据中允许转义双引号?
I'm using lark, an excellent python parsing library.
It provides an Earley and LALR(1) parser and is defined through a custom EBNF format. (EBNF stands for Extended Backus–Naur form).
Lowercase definitions are rules, uppercase definitions are terminals. Lark also provides a weight for uppercase definitions to prioritize the matching.
I'm trying to define a grammar but I'm stuck with a behavior I can't seem to balance.
I have some rules with unnamed literals (the strings or characters …
我的语法中有一个优先级问题,而且我没有其他解决方法。
我正在使用云雀
这是事情(我已尽力简化了问题):
from lark import Lark
parser = Lark(r"""
start: set | set_mul
set_mul: [nb] set
set: [nb] "foo"
nb: INT "x"
%import common.INT
%import common.WS
%ignore WS
""", start='start')
input = "3xfoo"
p = parser.parse(input)
print(p.pretty())
Run Code Online (Sandbox Code Playgroud)
输出为:
start
set_mul
set
nb 3
Run Code Online (Sandbox Code Playgroud)
但是我想要的是:
start
set_mul
nb 3
set
Run Code Online (Sandbox Code Playgroud)
我试图将优先权放在我的规则中,但是没有用。
您是否知道我需要进行哪些更改才能使其正常工作?
谢谢
lark-parser ×7
python ×7
grammar ×5
parsing ×2
ebnf ×1
pyqt ×1
pyqt5 ×1
qscintilla ×1
regex ×1