首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在编译时解析Nimrod中的字符串?

如何在编译时解析Nimrod中的字符串?
EN

Stack Overflow用户
提问于 2013-11-13 13:40:09
回答 1查看 985关注 0票数 6

通过宁罗德教程的第二部分,我已经到达了宏的部分被解释。文档说它们是在编译时运行的,所以我想我可以对字符串进行一些解析,以创建一个特定于域的语言。但是,没有关于如何做到这一点的示例,调试宏示例不显示如何处理字符串参数。

我想转换代码如下:

代码语言:javascript
复制
instantiate("""
    height,f,132.4
    weight,f,75.0
    age,i,25
    """)

…用手写成这样的东西:

代码语言:javascript
复制
var height: float = 132.4
var weight: float = 75.0
var age: int = 25

显然,这个例子不是很有用,但是我想看看一些简单的东西(多行/逗号分裂,然后转换),它可以帮助我实现更复杂的东西。

这里的问题是宏如何获得输入字符串,解析它(在编译时!),在编译时可以运行什么样的代码(它仅仅是语言的子集吗?我可以使用来自其他导入模块的宏/代码吗?

编辑:根据答案,下面是一个可能的代码解决方案:

代码语言:javascript
复制
import macros, strutils

# Helper proc, macro inline lambdas don't seem to compile.
proc cleaner(x: var string) = x = x.strip()

macro declare(s: string): stmt =
  # First split all the input into separate lines.
  var
    rawLines = split(s.strVal, {char(0x0A), char(0x0D)})
    buf = ""

  for rawLine in rawLines:
    # Split the input line into three columns, stripped, and parse.
    var chunks = split(rawLine, ',')
    map(chunks, cleaner)

    if chunks.len != 3:
      error("Declare macro syntax is 3 comma separated values:\n" &
        "Got: '" & rawLine & "'")

    # Add the statement, preppending a block if the buffer is empty.
    if buf.len < 1: buf = "var\n"
    buf &= "  " & chunks[0] & ": "

    # Parse the input type, which is an abbreviation.
    case chunks[1]
    of "i": buf &= "int = "
    of "f": buf &= "float = "
    else: error("Unexpected type '" & chunks[1] & "'")
    buf &= chunks[2] & "\n"

  # Finally, check if we did add any variable!
  if buf.len > 0:
    result = parseStmt(buf)
  else:
    error("Didn't find any input values!")

declare("""
x, i, 314
y, f, 3.14
""")
echo x
echo y
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-13 14:28:53

大体来说,宏可以使用同一地方的一个过程所能看到的所有纯Nimrod代码。例如,您可以导入strutilspeg来解析您的字符串,然后从中构造输出。示例:

代码语言:javascript
复制
import macros, strutils

macro declare(s: string): stmt =
  var parts = split(s.strVal, {' ', ','})
  if len(parts) != 3:
    error("declare macro requires three parts")
  result = parseStmt("var $1: $2 = $3" % parts)

declare("x, int, 314")
echo x

“调用”宏基本上会在编译时评估它,就好像它是一个过程一样(请注意,宏参数实际上是s.strVal,因此需要在上面使用s而不是s),然后在宏调用的位置插入它返回的AST。

宏代码由编译器的内部虚拟机计算。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19955348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档