在 C# 中使用已知模式解析 Lisp S 表达式

2023-12-09

我正在使用一项以类似 Lisp 的 S 表达式字符串形式提供数据的服务。这些数据到达的速度又快又厚,我想尽快地处理它,最好是直接在字节流上(它只是单字节字符)而不进行任何回溯。这些字符串可能非常长,我不希望 GC 为整个消息分配字符串而造成麻烦。

我当前的实现使用 CoCo/R 和语法,但它有一些问题。由于回溯,它将整个流分配给一个字符串。对于我的代码的用户来说,如果必须的话进行更改也有点麻烦。我宁愿有一个纯 C# 解决方案。 CoCo/R 也不允许重用解析器/扫描器对象,因此我必须为每条消息重新创建它们。

从概念上讲,数据流可以被视为一系列 S 表达式:

(item 1 apple)(item 2 banana)(item 3 chainsaw)

解析这个序列将创建三个对象。每个对象的类型可以由列表中的第一个值确定,在上面的例子中为“item”。传入流的模式/语法是众所周知的。

在开始编码之前,我想知道是否已经有库可以做到这一点。我确信我不是第一个遇到这个问题的人。


EDIT

这是我想要的更多细节,因为我认为最初的问题可能有点模糊。

给定一些 SExpressions,例如:

(Hear 12.3 HelloWorld)
(HJ LAJ1 -0.42)
(FRP lf (pos 2.3 1.7 0.4))

我想要一个与此等效的对象列表:

{
    new HearPerceptorState(12.3, "HelloWorld"),
    new HingeJointState("LAJ1", -0.42),
    new ForceResistancePerceptorState("lf", new Polar(2.3, 1.7, 0.4))
}

我正在处理的实际数据集是RoboCup 3D 模拟足球联赛中机器人模型的感知器列表。我可能还需要反序列化另一组结构更复杂的相关数据.


在我看来,解析生成器对于解析仅由列表、数字和符号组成的简单 S 表达式来说是不必要的。手写的递归下降解析器可能更简单,而且至少同样快。一般模式如下所示(在 java 中,c# 应该非常相似):

Object readDatum(PushbackReader in) {
    int ch = in.read();
    return readDatum(in, ch);
}
Object readDatum(PushbackReader in, int ch) {
    if (ch == '(')) {
        return readList(in, ch);
    } else if (isNumber(ch)) {
        return readNumber(in, ch);
    } else if (isSymbolStart(ch)) {
        return readSymbol(in, ch);
    } else {
        error(ch);
    }
}
List readList(PushbackReader in, int lookAhead) {
    if (ch != '(') {
        error(ch);
    }
    List result = new List();
    while (true) {
        int ch = in.read();
        if (ch == ')') {
            break;
        } else if (isWhiteSpace(ch)) {
            skipWhiteSpace(in);
        } else {
            result.append(readDatum(in, ch);
        }
    }
    return result;
}
String readSymbol(PushbackReader in, int ch) {
    StringBuilder result = new StringBuilder();
    result.append((char)ch);
    while (true) {
       int ch2 = in.read();
       if (isSymbol(ch2)) {
           result.append((char)ch2);
       } else if (isWhiteSpace(ch2) || ch2 == ')') {
           in.unread(ch2);
           break;
       } else if (ch2 == -1) {
           break;
       } else {
           error(ch2);
       }
    }
    return result.toString();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中使用已知模式解析 Lisp S 表达式 的相关文章

随机推荐

  • iOS相机焦点值

    有什么办法可以从具有自动对焦功能的 iPhone 相机中获取焦点值吗 我想使用这些数据来计算 iPhone 到焦点对象的距离 显然这是一个老问题 但由于自 iOS8 以来有一个获取 镜头值 的选项 它应该出现在这里 从iOS 8开始你可以通
  • cx_Freeze 错误:resource_filename() 仅支持 .egg,不支持 .zip

    我有一个完全工作的基于 wxpython 的应用程序 全部用 Python 编写 我想制作一个exe 所以我使用了cxFreeze 在构建过程中 有许多模块似乎丢失了 有时这应该不会造成问题 但是当我运行应用程序时 它给了我来自 MySQL
  • 函数隐藏和重载的区别

    我找不到函数隐藏和重载之间的任何区别 由于函数隐藏是派生类中存在的函数并隐藏基类的函数 两者的函数名称相同 重载 派生类和基类具有相同的名称但不同的签名 class A void print int class B public A voi
  • ant build 中使用 aapt 进行紧缩/资源打包使用其他项目的缓存

    我有两个使用通用库的 Android 应用程序 每个项目都为启动屏幕和其他一些项目定义了自己的背景图像 这些图像在两个应用程序中具有相同的名称 当我从 Eclipse 构建 运行时 每个应用程序都使用正确的背景图像 但是 当我运行 ant
  • jqueryposition() 在 safari 和 chrome 中无法正常工作

    我以前曾见过这个问题一两次 但从未有过适用于我的问题的答案 据我所知 我有一个单击链接时出现的工具提示 我根据链接的位置设置工具提示的位置 如下所示 tooltip css left this position left 这在 FF IE
  • 比较两个数组并用第三个数组中的值替换重复项

    var array1 a b c d var array2 a v n d i f var array3 1 2 3 4 5 6 刚开始学习Javascript 我不知道如何比较array2给那些在array1如果是这样 请将其替换为相应的
  • 一个简单的 SQL Select 查询来抓取社交图中所有有联系的人?

    爬取社交图谱的最短或最快的 SQL 选择查询或 SQL 过程是什么 想象一下我们有这张表 UId FriendId 1 2 2 1 2 4 1 3 5 7 7 5 7 8 5 9 9 7 我们这里有两个人 我正在谈论一个 sql 查询或过程
  • 嵌入式 Python 无法使用 NumPy 指向 Python35.zip - 如何修复?

    好的 这是来自 Python 网站的基本示例 用于简单说明runpy exe运行下面的 Python 脚本 引用 Python 包含并链接到后 在 x64 Windows 上使用 Visual Studio 2015 可以正常工作pytho
  • Spring Data mongodb-复制集合

    我将 spring 数据与 mongodb 一起使用 我想使用代码而不是命令行将文档从一个集合复制到另一个集合 有没有办法在不循环所有文档并执行 插入 的情况下执行此操作 除非像这样的命令一样使用它 mongoTemplate execut
  • 错误:超时间隔必须小于 2^32-2。参数名称: dueTm

    我的班级模型中有一对多关系 例子 单个角色可以附加多个权限 因此有两张表 一张来自角色 一张用于每个角色的权限 现在我有一个角色类 该角色类又具有作为该类成员的权限列表 当我需要进行更新时 我实例化一个transactionscope对象
  • 将文本添加到 div(或其他元素)的底部 - 模拟聊天控制台

    我有一个 div 应该在文本输入到输入框中时收集文本 现在它只是重现输入 但稍后它应该产生半智能响应 我希望文本出现在 div 的底部 渐变的暗端 我希望新文本始终位于底部 旧文本始终位于上部滚动区域的灰色区域 In other words
  • WPF 样式设置器不工作

    我有一个包含组合框的自定义用户控件 我添加了一个 ComboBoxWidth 依赖属性 以允许开发人员根据需要设置宽度 使用样式设置器 我想将所有这些组合框的宽度设置为另一个用户控件上的相同值 以保持大小一致性 但是 它不起作用 如果我在每
  • 在 Visual Basic 2010 中使用变量字符串引用对象

    我的表单上有几组类似的对象 标签 进度条 Windows 上的 Visual Basic 2010 在我的代码中 我有包含数据的集合 需要将其推入每个集合的值 文本属性中 我想要一个类似于 PHP 的解决方案 因为我可以分配类似于以下的值
  • 导航回具有相同状态的搜索页面 (JavaScript)

    当用户单击搜索结果但随后返回主搜索页面时 如何使用 JavaScript 保留搜索页面的状态 e g HTML https startech enterprises github io docs guides data analytics
  • 反应环境变量.env返回未定义

    我正在构建一个 React 应用程序 我需要从我的 api 获取数据 现在我想将 api url 存储为环境变量 我有我的 env 文件 我安装了 dotenv 这是我的代码 process env API URL 返回未定义 import
  • 无法使用 [UIImage imageWithContentsOfFile:] 创建 UIImage 并且文件存在

    我google了这个问题 大多数使用了错误的方法 UIImage imageNamed 我不是 并且我确定该文件存在 以下代码在iOS8 1上运行 self cachePath NSSearchPathForDirectoriesInDom
  • 如何在 VBscript 中将字符串数组转换为变体数组?

    我在 vbscript 中使用一个函数 它返回一个变量字符串数组 JobIDs objDoc ConnectedSubmit objServer 问题是我无法从该数组中获取作业 ID 值 因为 vbscript 不处理类型变量 当我尝试对
  • Laravel 5 Entrust - 用户属于许多应用程序

    我在 Laravel 5 3 中使用 Entrust 包来管理用户角色和权限 它工作得很好 问题是我的users 属于许多人 apps 所以我需要检查角色和权限 并考虑到他们在每种情况下尝试在哪个应用程序中执行操作 由于 Entrust 不
  • 保存和加载数据 - CoreData

    我是 CoreData 的新手 在我的 iPhone 应用程序中我想知道如何保存一些文本 然后将其重新加载 但诀窍是 当 UIDatePicker 中的日期与我保存它时的日期相同时加载它 就像日历一样 Update 感谢您的回复 尤其是代码
  • 在 C# 中使用已知模式解析 Lisp S 表达式

    我正在使用一项以类似 Lisp 的 S 表达式字符串形式提供数据的服务 这些数据到达的速度又快又厚 我想尽快地处理它 最好是直接在字节流上 它只是单字节字符 而不进行任何回溯 这些字符串可能非常长 我不希望 GC 为整个消息分配字符串而造成