我在C / C ++程序中嵌入了python。
我要做的是解析C / C ++程序中的python脚本文件,将文件分解为“块”,以便每个“块”都是python代码中的有效命令。我需要将每个块放入std::string
。例如:
#PythonScript.py
import math
print "Hello Python"
i = 0;
while (i < 10):
print "i = " , i;
i = i + 1;
print "GoodBye Python"
在这个脚本中有5个不同的“块”:
"import math;"
"print "Hello Python;"
"i = 0;"
,第四个是
while (i < 10):\n\tprint "i = " , i;\n\ti = i + 1;
我在python中的知识非常基础,我不熟悉python代码语法。执行此操作的最佳方法是,是否有支持此功能的Python C / C ++ API函数?
为什么我需要它 - &gt;用于GUI目的。我的程序,用C语言编写,使用python进行一些计算。我运行C代码,使用python C API,python脚本,我需要的是一种在程序中捕获python输出的方法。我抓住它并且一切都好,问题是当脚本涉及用户输入时。发生的事情是我在脚本完成后捕获python的输出,因此,当脚本中有输入命令时,我得到一个黑屏......我需要在输入命令之前获得所有打印。
我尝试的第一个解决方案是将脚本解析为有效命令并一个接一个地运行每个命令,为此我需要解析脚本并确定什么是命令而不是什么。 .. 问题是:这样做的最佳方式是什么,以及是否已经完成了某些事情?
答案 0 :(得分:4)
我不知道你为什么要这样做,但最安全的方法是让Python自己做解析工作。如果您使用的是早于2.6的Python,则可以使用compiler
模块。对于2.6及更高版本,请使用内置的compile
函数和ast
模块。在3.x中, 要使用这些,因为compiler
模块已被删除。
答案 1 :(得分:1)
我认为你正在努力做额外的工作,因为(至少)Embedding Python in Another Application facility你可以通过Python / C API执行你的脚本。我想你不想从头开始编写Python解释器,对吗?
答案 2 :(得分:1)
如果你想进行语法分析,你应该研究Pythons语法(也许使用Bison作为解析器生成器)
Python语法规范:
答案 3 :(得分:0)
你为什么需要这个?如果你正在嵌入Python,你不需要自己解析Python代码 - 甚至不需要远程解析。
但回答这个问题:你可以使用Python的ast
模块(内部使用内置模块_ast
- 我不知道你是否以及如何在C中使用它)。 ast.parse("""... your code ...""")
给出一个Module
对象,该对象具有body
属性,该属性是模块组成的AST节点列表。在这个例子中,使用Python 3(手头没有Python 2)它(仅命名类)[Import,Expr,Assign,While,Expr]。不是你要求的,但是尽可能接近。
好的,增加了:很多比这更简单。证明没有任何东西从stdin读取是非常困难的,它需要大量的静态分析(是的,如果你选择那条路径,使用CPython的AST仍然比构建你自己的解析器容易一百倍)。这是一般情况 - 所以你可能能够几乎为你的特定用例工作,并做了大量的工作。但是,首先要防范它会容易得多 - 我不太了解C API,但必须有一些方法来调整__builtins__
并删除input
,{ {1}},raw_input
等
答案 4 :(得分:0)
@genesiss提供了您需要的所有信息。
我10年前学过Python,所以我的知识并不比你的好。但我确实记得白色空格和换行符是Python中的实际语法元素。
查看Official Python Grammar,与“块”最匹配的语法元素为statement
。
statement ::=
stmt_list NEWLINE | compound_stmt
因此,您只需查看换行符即可成功分离Python语句。
还要注意词汇结构的第4号:
在字符串文字之外,换行符(下面用NEWLINE表示)非常重要,除非
它们前面紧跟一个反斜杠(“\”)字符,在这种情况下,反斜杠和换行符(实际上)都被一个空格所取代,连接它们分开的两行。
它们包含在匹配的开始和结束括号中:“(”和“)”,“[”和“]”或“{”和“}”。在这种情况下,换行也被视为空格。
因此,通过char读取输入char,查找'\','\ n'和分隔符。
下面的示例代码(仅概念草图):
std::string input;
std::string::const_iterator it = input.begin();
std::string::const_iterator itEnd = input.end();
int delim = 0;
bool escape = false;
std::string block;
while (it != itEnd)
{
char c = *it;
switch (c) {
case '\\':
if (!delim) escape = true;
break;
case '\n':
if (!delim && !escape)
write_block(); // handle contents of the block variable
escape = false;
break;
case '(': case '[': case '{':
++delim; escape = false;
break;
case ')': case ']': case '}':
--delim; escape = false;
break;
}
block.append(c, 1);
++it;
}
EDITED
缺少字符串文字处理,但我相信你肯定会像这样滚动完整的词汇分析。