如何为表达式添加括号?
我有一个想法,可以制作一个简单的程序,它将帮助我处理 C 等语言中的运算符优先级。其中最困难的部分是为表达式加上括号。 例如,我想要这个:
*a.x++ = *b.x++
转换为:
((*(((a).(x))++)) = (*(((b).(x))++)))
我在这些步骤中手动完成的:
*a.x++ = *b.x++
*(a).(x)++ = *(b).(x)++
*((a).(x))++ = *((b).(x))++
*(((a).(x))++) = *(((b).(x))++)
(*(((a).(x))++)) = (*(((b).(x))++))
((*(((a).(x))++)) = (*(((b).(x))++)))
完成此操作的最佳方法是什么? 已经有我可以使用的解决方案了吗? 我更喜欢使用 PHP、C、C++、Python 或 Ruby 来完成此操作。
(这不是我的程序的全部想法,这只是第一步。)
I have an idea for a simple program to make that will help me with operator precedence in languages like C. The most difficult part of this is parenthesizing the expression. For example, I want this:
*a.x++ = *b.x++
Converted to this:
((*(((a).(x))++)) = (*(((b).(x))++)))
Which I did manually in these steps:
*a.x++ = *b.x++
*(a).(x)++ = *(b).(x)++
*((a).(x))++ = *((b).(x))++
*(((a).(x))++) = *(((b).(x))++)
(*(((a).(x))++)) = (*(((b).(x))++))
((*(((a).(x))++)) = (*(((b).(x))++)))
What is the best way to accomplish this? Is there already a solution out there that I could use? I'd prefer to do this in either PHP, C, C++, Python, or Ruby.
(This isn't the whole idea of my program, it is only the first step.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
最可靠的方法是解析表达式(考虑到account 优先级规则,当然),然后在 a 中处理生成的 AST(抽象语法树)自上而下的方式,在前进时添加括号
The most reliable way will be to parse the expression (taking into account precedence rules, of course) and then process the resulting AST (Abstract Syntax Tree) in a top-down manner, adding parenthesis as you move along
转换为后缀并评估怎么样?
您可以尝试以下方法是否有效。
让我们以 *a.x++
为例,现在将表达式转换为后缀表示法。 现在,对
后缀的评估就像将东西推入堆栈一样简单,当您点击运算符时,弹出前 n 个(根据运算符需要的)元素并将它们作为参数传递,将结果存储回堆栈。
在您的情况下,您将返回操作的文本表示(
如果有帮助),而不是进行评估,您可能需要查看:
http://www.spsu.edu/cs/faculty/bbrown/web_lectures /后缀/
Bart de smet 的 DynCalc 系列帖子
我尝试 TDD 类似的解决方案
How about converting to postfix and evaluating.
Can you try if the following approach works.
Lets take *a.x++
So now convert the expression to postfix notation. This should give you
Now evaluation of postfix is as simple as pushing things into a stack, when you hit an operator, pop the top n (as needed by operator) elements and pass them as arguments, store results back onto the stack.
In your case, instead of evaluating, you'd return a textual representation of the operation
if it helps, you may want to look at:
http://www.spsu.edu/cs/faculty/bbrown/web_lectures/postfix/
Bart de smet's DynCalc series of posts
My attempt at TDDing a similar solution
只需选择适合您所选语言的解析器,例如 C 解析器,解析表达式/源代码并以您想要的方式打印 AST。
测试.c:
终端:
Just pick up a parser for your selected language, for instance C parser, parse the expression/source code and print the AST back in the way you want.
test.c:
terminal:
您可以从运算符创建二叉表达式树。
我相信网上已经有几种算法可以创建这样的树。
我能想到的一种简单方法是按优先级对运算符进行排序,然后首先按优先级最低的运算符将字符串分成两部分,然后继续递归地一遍又一遍地向下拆分其他两部分,最后,你将会有二叉树形式的表达式。
然后,当您拥有二叉树形式的表达式时,您可以从树的叶子到根“加括号”。
当然,您可以通过 yacc/bison 编译一个成熟的解析器。
You could create a binary expression tree from the operators.
I believe there are several algorithms available online to create such tree already.
One simple way I could think of, is by sorting the operator by precedence, and then split the string into 2 parts by the operator with the lowest precedence first, then continue recursively splitting the other 2 parts down over and over and then eventually, you'll have the expression in binary tree form.
And then when you have the expression in binary tree form, you can then "parenthesize" up from the tree's leaves up to the root.
And of course, you could compile a full-fledged parser via yacc/bison.
举一个简单的例子:
您可以使用语法来编写翻译:
在这种情况下:
翻译为:
As a simple example:
You can uses the grammar to write the translations:
In which case:
Translates to:
解析是一个很大的话题。 由于您只是想用它来解决特定问题,因此请尽量不要沉浸在人们建议的所有这些特定解析算法中。 相反,有许多解析器生成器,例如 antler 或 bison,在给定适当的语法的情况下,它们将解析文本并允许您对组件执行编程操作 - 例如在它们周围添加括号。 其中一些系统附带了 C 语法,或者具有可用的此类语法。
antlr 可以生成您提到的任何语言的解析器; 请参阅http://www.antlr.org/
Parsing is a huge topic. Since you just want to use it to solve a specific problem, try not to get immersed in all these specific parsing algorithms that people are suggesting. Rather, there are numerous parser generators, such as antler or bison which, given an appropriate grammar, will parse text and allow you to perform programmatic operations on the components -- such as put parentheses around them. Some of these systems come with grammars for C, or have such grammars available.
antlr can generate parsers in any of the languages you mentioned; see http://www.antlr.org/
您可以在旧的 net.sources 新闻组的档案中找到“cparen”。
如果您搜索(Google)“cparen”,您会得到太多噪音,但如果您搜索
对于 net.sources 和 'cparen.c',它缩小了搜索范围,足以发挥作用。
这是一个网站:
http://www.megalextoria。 com/usenet-archive/news005f3/b14/net/sources/00000360.html
正如我所期望的那样,它不是一个 shell 存档。
它看起来像一个纯 ASCII 文本 tar 文件。
文件数量足够少,您可以
用手拆开包装。
You can find "cparen" in the archives of the old net.sources newsgroup.
If you search (Google) for 'cparen', you get too much noise, but if you search
for net.sources and 'cparen.c' that narrows the search enough to be useful.
Here is one website:
http://www.megalextoria.com/usenet-archive/news005f3/b14/net/sources/00000360.html
It is not a shell archive, as I would have expected.
It looks like a pure ASCII text tar file.
There are few enough files that you could just
unpack it by hand.
我用 Python 编写了一个程序来为表达式字符串添加括号。
I wrote a program in Python to parenthesize an expression string.
有一个非常古老的(1980 年代)开源程序可以做到这一点。
它叫“cparen”,但如果我能在网上找到它,我就该死了。 只有热情地提到它,例如
https://groups.google.com /group/comp.lang.c/tree/browse_frm/month/1990-03/1583b4728a6d94db
http://www.language-c.info/re-should-i-capitalize-const-identifiers
如果你比我更幸运地找到它,请写
There is a very old (1980's) open source program to do exactly this.
It's called "cparen", but I'm damned if I can find it on the net. Only enthusiastic mentions of it, e.g.
https://groups.google.com/group/comp.lang.c/tree/browse_frm/month/1990-03/1583b4728a6d94db
http://www.language-c.info/re-should-i-capitalize-const-identifiers
If you have more luck than me in finding it, do write
您将需要某种能够理解运算符优先级的解析器。 C 的常用版本是 Lexx/Yacc 或 flex/bison,最简单的方法是构造一个解析树。 完成此操作后,只需按“预序”顺序遍历解析树,并在进入和离开节点时发出括号。
You're going to need a parser of some sort that understands operator precendence. The usual version for C is Lexx/Yacc or flex/bison, and the easiest way to do it is construct a parse tree. Once you've done that, just walk the parse tree in the "preorder" order and emit parens as you enter and leave a node.