如何在Nimrod编译时解析字符串? [英] How do I parse a string at compile time in Nimrod?

查看:106
本文介绍了如何在Nimrod编译时解析字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过 Nimrod教程的第二部分,我已经到达了解释宏的部分.文档说它们在编译时运行,所以我认为我可以对字符串进行一些解析以创建属于自己的领域特定语言.但是,没有有关如何执行此操作的示例,调试宏示例却没有不会显示如何处理字符串参数.

Going through the second part of Nimrod's tutorial I've reached the part were macros are explained. The documentation says they run at compile time, so I thought I could do some parsing of strings to create myself a domain specific language. However, there are no examples of how to do this, the debug macro example doesn't display how one deals with a string parameter.

我想转换如下代码:

instantiate("""
    height,f,132.4
    weight,f,75.0
    age,i,25
    """)

…变成我用手会写的东西:

…into something which by hand I would write like:

var height: float = 132.4
var weight: float = 75.0
var age: int = 25

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

Obviously this example is not very useful, but I want to look at something simple (multiline/comma splitting, then transformation) which could help me implement something more complex.

我的问题是宏如何获取输入字符串,在解析时解析它(在编译时!),以及在编译时可以运行哪种代码(仅仅是languaje的子集吗?我可以使用宏/吗?其他导入模块的代码)?

My issue here is how does the macro obtain the input string, parse it (at compile time!), and what kind of code can run at compile time (is it just a subset of a languaje? can I use macros/code from other imported modules)?

EDIT :根据答案,这里是该问题的可能代码解决方案:

EDIT: Based on the answer here's a possible code solution to the question:

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

推荐答案

Macro可以大体上利用同一地方的程序可以看到的所有纯Nimrod代码.例如,您可以导入strutilspeg来解析您的字符串,然后从中构造输出.示例:

Macros can, by and large, utilize all pure Nimrod code that a procedure in the same place could see, too. E.g., you can import strutils or peg to parse your string, then construct output from that. Example:

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

调用"宏将基本上在编译时对其进行评估,就好像它是一个过程(注意:宏参数实际上将是AST,因此需要使用上面的s.strVal而不是s),然后在宏调用的位置插入它返回的AST.

"Calling" a macro will basically evaluate it at compile time as though it were a procedure (with the caveat that the macro arguments will actually be ASTs, hence the need to use s.strVal above instead of s), then insert the AST that it returns at the position of the macro call.

宏代码由编译器的内部虚拟机评估.

The macro code is evaluated by the compiler's internal virtual machine.

这篇关于如何在Nimrod编译时解析字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆