好的,所以我问过一些关于这个项目的小问题,但我对我想出的设计仍然没有多少信心,所以我会在更广泛的范围内提出一个问题.
我正在解析课程目录的先决条件描述.描述几乎总是遵循某种形式,这使我认为我可以解析其中的大多数.
从文本中,我想生成一个关于课程必备关系的图表.(在我解析数据之后,那部分会很简单.)
一些样本输入和输出:
"CS 2110" => ("CS", 2110) # 0
"CS 2110 and INFO 3300" => [("CS", 2110), ("INFO", 3300)] # 1
"CS 2110, INFO 3300" => [("CS", 2110), ("INFO", 3300)] # 1
"CS 2110, 3300, 3140" => [("CS", 2110), ("CS", 3300), ("CS", 3140)] # 1
"CS 2110 or INFO 3300" => [[("CS", 2110)], [("INFO", 3300)]] # 2
"MATH 2210, 2230, 2310, or 2940" => [[("MATH", 2210), ("MATH", 2230), ("MATH", 2310)], [("MATH", 2940)]] # 3
Run Code Online (Sandbox Code Playgroud)
如果整个描述只是一个过程,则直接输出.
如果课程是连接的("和"),则它们都输出在同一列表中
如果课程脱离("或"),则它们位于不同的列表中
在这里,我们有"和"和"或". …
我的目标是像Python一样解析字符串.
问题:如何编写lex以支持以下内容:
"string..."
'string...'
"""multi line string \n \n end"""
'''multi line string \n \n end'''
一些代码:
states = ( ('string', 'exclusive'), ) # Strings def t_begin_string(self, t): r'(\'|(\'{3})|\"|(\"{3}))' t.lexer.push_state('string') def t_string_end(self, t): r'(\'|(\'{3})|\"|(\"{3}))' t.lexer.pop_state() def t_string_newline(self, t): r'\n' t.lexer.lineno += 1 def t_string_error(self, t): print("Illegal character in string '%s'" % t.value[0]) t.lexer.skip(1)
我目前的想法是创建4个独特的状态,将匹配4个不同的字符串案例,但我想知道是否有更好的方法.
谢谢你的帮助!
我有一个包含人脸3D点云的.PLY文件:我想绘制它并用Python可视化它.
我的.PLY文件只包含顶点和非面.
你能否指出我一个简单的Python库,它将负责绘制3D点云,以便我可以想象它?
重要的是要注意我对绘制MESH不感兴趣,而只是POINT CLOUD.
任何帮助将非常感激.
我正在使用需要识别FORTRAN字符串文字的ply编写解析器.这些引号用单引号引用,转义字符加倍单引号.即
'I don''t understand what you mean'
是一个有效的转义FORTRAN字符串.
Ply以正则表达式输入.到目前为止我的尝试不起作用,我不明白为什么.
t_STRING_LITERAL = r"'[^('')]*'"
有任何想法吗?
我在PLY中使用一个相当简单的解析器,我的一个规则采用以下形式:
def p_things(p):
'''
things : thing things
things : thing
'''
p[0] = [p[1]]
if len(p) == 3:
p[0] += p[2]
Run Code Online (Sandbox Code Playgroud)
输入文件通常是简单的thing
s 列表,因此解析本身并不复杂.但是我的一些输入文件非常大(相当规律地超过100,000行,极端情况下超过1,000,000行).在分析中(通过cProfile和pstats),大部分运行时通过重复调用来占用p_things
- 可能是,对things
列表中的每个项目进行一次调用.
有没有办法减少这个时间,或者更有效的方法来构建这个规则?到目前为止我看到的大多数答案(以及我发现的规范编译器信息)已经将此方法列为构建可解析项目列表的普遍接受的方式,无论长度如何.
我知道还有其他工具来解析SQL语句,但我出于教育目的推出了自己的工具.我现在卡住了我的语法..如果你能快速发现错误请告诉我.
SELECT = r'SELECT'
FROM = r'FROM'
COLUMN = TABLE = r'[a-zA-Z]+'
COMMA = r','
STAR = r'\*'
END = r';'
t_ignore = ' ' #ignores spaces
statement : SELECT columns FROM TABLE END
columns : STAR
| rec_columns
rec_columns : COLUMN
| rec_columns COMMA COLUMN
Run Code Online (Sandbox Code Playgroud)
当我尝试解析像'SELECT a FROM b;'这样的语句时 我在FROM令牌上遇到语法错误...非常感谢任何帮助!
(编辑)代码:
#!/usr/bin/python
import ply.lex as lex
import ply.yacc as yacc
tokens = (
'SELECT',
'FROM',
'WHERE',
'TABLE',
'COLUMN',
'STAR',
'COMMA',
'END',
)
t_SELECT = r'select|SELECT'
t_FROM = r'from|FROM'
t_WHERE …
Run Code Online (Sandbox Code Playgroud) 我正在研究一个简单的SQL选择,如查询解析器,我需要能够捕获可以在某些地方字面上出现的子查询.我发现lexer状态是最好的解决方案,并且能够使用花括号来标记开始和结束.但是,子查询将用括号分隔,而不是用卷曲分隔,括号也可以在其他地方出现,所以我不能成为每个开放状态的状态.解析器随时可以使用此信息,因此我希望在解析器规则中的适当位置调用begin和end.然而这并不起作用,因为词法分析器似乎一次性标记了流,因此令牌在INITIAL状态下生成.这个问题有解决方法吗?以下是我尝试做的概述:
def p_value_subquery(p):
"""
value : start_sub end_sub
"""
p[0] = "( " + p[1] + " )"
def p_start_sub(p):
"""
start_sub : OPAR
"""
start_subquery(p.lexer)
p[0] = p[1]
def p_end_sub(p):
"""
end_sub : CPAR
"""
subquery = end_subquery(p.lexer)
p[0] = subquery
Run Code Online (Sandbox Code Playgroud)
start_subquery()和end_subquery()定义如下:
def start_subquery(lexer):
lexer.code_start = lexer.lexpos # Record the starting position
lexer.level = 1
lexer.begin('subquery')
def end_subquery(lexer):
value = lexer.lexdata[lexer.code_start:lexer.lexpos-1]
lexer.lineno += value.count('\n')
lexer.begin('INITIAL')
return value
Run Code Online (Sandbox Code Playgroud)
词法分析器令牌只是用于检测近距离:
@lex.TOKEN(r"\(")
def t_subquery_SUBQST(t):
lexer.level += 1
@lex.TOKEN(r"\)")
def t_subquery_SUBQEN(t):
lexer.level -= …
Run Code Online (Sandbox Code Playgroud) 我在命令行应用程序中使用PLY,我将其打包为要安装的Python egg pip
.每次我从命令行运行我的脚本时,都会看到以下消息:
"Generating LALR tables"
Run Code Online (Sandbox Code Playgroud)
此外,parser.out和parsetab.py文件将写入调用脚本的目录.有没有办法用应用程序发送这些文件,以便它不会每次都重新生成表?
我正在用PLY编写自己的解析器。我想分别封装lex和yacc
这是Lex类的代码:
class Lex:
tokens = (
'NAME', 'NUMBER',
)
literals = ['=', '+', '-', '*', '/', '(', ')']
# Tokens
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
...
Run Code Online (Sandbox Code Playgroud)
解析器代码(使用yacc):
class Parser:
# Parsing rules
tokens = Lex.tokens
def p_statement_assign(self, p):
'statement : NAME "=" expression'
self.names[p[1]] = p[3]
...
def run(self):
print self.tokens
lex.lex(module=Lex) # ----what should I do here?-----
parser = yacc.yacc(module=self)
parser.parse("1+2")
Run Code Online (Sandbox Code Playgroud)
我收到以下错误?必须以Lex实例作为第一个参数调用未绑定的方法t_NUMBER()(改为使用LexToken实例)
我尝试使用module=Lex
lex,就像一样yacc.yacc(module=self)
,但是它没有用,任何人都可以告诉解决方案。
背景:作为一个关于寒假的短期项目,我正在尝试使用Python和PLY实现一种名为Ax(专为图形计算器设计)的编程语言.简要说明:该语言仅允许全局变量并大量使用指针.
我正试图用这种语言实现goto,但不知道该怎么做.
我的一般方法是首先使用PLY将代码解析为ast,然后在我执行时执行它.
例如,声明
If 3
Disp 4
Disp 6
End
Run Code Online (Sandbox Code Playgroud)
......会变成......
['PROGRAM',
['BLOCK',
['IF',
['CONDITION', 3],
['BLOCK',
['DISP', 4],
['DISP', 6]
]
]
]
]
Run Code Online (Sandbox Code Playgroud)
...我将以递归方式执行(为了便于阅读,我添加了缩进).
因为ast是树,我不确定如何在不同节点之间跳转.我考虑过将树转换成平面数组,['IF', ['CONDITION', 3], ['DISP', 4], ['DISP', 6]]
这样我就可以使用flat-ish数组的索引转到代码中的特定行,但这似乎缺乏一定的优雅,几乎感觉就像一步向后(虽然我可能是错的).
我看过这个,但无法理解它是如何工作的.
任何帮助或提示将不胜感激.
ply ×10
python ×9
parsing ×4
lexer ×2
yacc ×2
3d ×1
fortran ×1
goto ×1
interpreter ×1
nlp ×1
optimization ×1
point-clouds ×1
pyparsing ×1
python-2.7 ×1
regex ×1
sql ×1