带秒差距的完整解析器示例?

2024-04-08

我正在尝试为一种简单的函数式语言(有点像 Caml)制作一个解析器,但我似乎只专注于最简单的事情。

所以我想知道是否有一些更完整的例子parsec解析器,超越“这就是解析 2 + 3 的方式”的东西。特别是术语等中的函数调用。

我读过“为你写一个方案”,但是方案的语法非常简单,对学习没有太大帮助。

我遇到最多的问题是如何使用try, <|> and choice正确地,因为我真的不明白为什么 parsec 似乎永远不会解析a(6)作为使用此解析器的函数调用:

expr = choice [number, call, ident]

number = liftM Number float <?> "Number"

ident = liftM Identifier identifier <?> "Identifier"

call = do
    name <- identifier
    args <- parens $ commaSep expr
    return $ FuncCall name args
    <?> "Function call"

EDIT添加了一些完成代码,尽管这实际上不是我要求的:

AST.hs

module AST where

data AST
    = Number Double
    | Identifier String
    | Operation BinOp AST AST
    | FuncCall String [AST]
    deriving (Show, Eq)

data BinOp = Plus | Minus | Mul | Div
    deriving (Show, Eq, Enum)

Lexer.hs

module Lexer (
            identifier, reserved, operator, reservedOp, charLiteral, stringLiteral,
            natural, integer, float, naturalOrFloat, decimal, hexadecimal, octal,
            symbol, lexeme, whiteSpace, parens, braces, angles, brackets, semi,
            comma, colon, dot, semiSep, semiSep1, commaSep, commaSep1
    ) where

import Text.Parsec
import qualified Text.Parsec.Token as P
import Text.Parsec.Language (haskellStyle)

lexer = P.makeTokenParser haskellStyle

identifier = P.identifier lexer
reserved = P.reserved lexer
operator = P.operator lexer
reservedOp = P.reservedOp lexer
charLiteral = P.charLiteral lexer
stringLiteral = P.stringLiteral lexer
natural = P.natural lexer
integer = P.integer lexer
float = P.float lexer
naturalOrFloat = P.naturalOrFloat lexer
decimal = P.decimal lexer
hexadecimal = P.hexadecimal lexer
octal = P.octal lexer
symbol = P.symbol lexer
lexeme = P.lexeme lexer
whiteSpace = P.whiteSpace lexer
parens = P.parens lexer
braces = P.braces lexer
angles = P.angles lexer
brackets = P.brackets lexer
semi = P.semi lexer
comma = P.comma lexer
colon = P.colon lexer
dot = P.dot lexer
semiSep = P.semiSep lexer
semiSep1 = P.semiSep1 lexer
commaSep = P.commaSep lexer
commaSep1 = P.commaSep1 lexer

Parser.hs

module Parser where

import Control.Monad (liftM)
import Text.Parsec
import Text.Parsec.String (Parser)
import Lexer
import AST

expr = number <|> callOrIdent

number = liftM Number float <?> "Number"

callOrIdent = do
    name <- identifier
    liftM (FuncCall name) (parens $ commaSep expr) <|> return (Identifier name)

Hmm,

*Expr> parse expr "" "a(6)"
Right (FuncCall "a" [Number 6.0])

填写缺失的部分后,该部分对我有用。

Edit:我自己写了一些内容来填补缺失的部分float解析器,可以解析整数文字。这float解析器来自Text.Parsec.Token另一方面,仅解析带有分数部分或指数的文字,因此无法解析“6”。

However,

*Expr> parse expr "" "variable"
Left (line 1, column 9):
unexpected end of input
expecting "("

当解析标识符后调用失败时,该部分输入将被消耗,因此不会尝试 ident,并且整个解析失败。你可以 a) 做到try call在选择列表中expr,以便调用在不消耗输入的情况下失败,或者 b) 编写一个解析器 callOrIdent 以在中使用expr, e.g.

callOrIdent = do
    name <- identifier
    liftM (FuncCall name) (parens $ commaSep expr) <|> return (Identifier name)

这避免了try从而可能表现得更好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带秒差距的完整解析器示例? 的相关文章

随机推荐

  • 如何在 geom_tile ggplot 中移动图块右/左端的刻度线和标签?

    我无法将 geom tile 中的 x 轴标签 包括刻度线 移动到每个图块的右端 我还想在左端添加零 我尝试过休息和标签 但没有运气 使用中断和标签也不起作用 我试图实现这个答案中所做的事情 但建议的解决方案不起作用 如何强制 x 轴刻度线
  • 如何将 $_GET 路径与 file_exists 一起使用并保证其安全?

    我有一个函数可以通过 jQuery 检查文件是否存在 该函数调用 PHP 脚本 在单击索引页面上的按钮更改某些图像时将使用该脚本 jQuery 函数 function fileExists path getJSON ajax fileExi
  • 标准化 sql server 中迄今为止不同格式的 varchar 字段

    我知道过去曾被问过类似的问题 但他们仍然没有为我的案例提供适当的解决方案 我有一个数据库表 第三方 其中有varchar列为datetime value 它包含以下格式的日期 11181980 8 18 1960 10 01 1960 04
  • 如何在 sbt 中为我的项目设置系统属性?

    我确信我错过了一些非常简单的东西 我想设置系统属性java awt headless to true对于我的 sbt 项目 正在阅读属性页面 http code google com p simple build tool wiki Pro
  • 如何在pyspark中分解数据框的多列

    我有一个数据框 其中包含类似于以下内容的列中的列表 所有列中列表的长度不相同 Name Age Subjects Grades Bob 16 Maths Physics Chemistry A B C 我想以这样的方式分解数据框 以获得以下
  • Objective-C 和 Cocoa 有什么区别?

    我正在学习 Mac 上的 Objective C Cocoa 编程 我一直使用的所有教程 书籍 博客 播客等实际上都涵盖了这两者 有没有一种简单的方法来区分哪些部分是普通的 Objective C 哪些部分来自 Cocoa Objectiv
  • 从具有不同列数的两个表中选择 *

    我如何从两个不同的表中选择不同的列 例如 SELECT username email FROM table1 UNION SELECT FROM table2 WHERE username user1 我收到错误 1222 The used
  • 在 Mac 上安装 numpy 以在 AWS Lambda 上运行

    有没有办法安装numpy在 Mac 上 以便上传到 AWS Lambda 后可以正常工作 我尝试过各种不同的方法 包括使用不同的方法pip版本 使用easy install 和以下这个帖子 https stackoverflow com q
  • 由于随机给定的字符,我无法从 firebase 更新数据

    这是我的 firebase 我不知道如何在 firebase 中输入或获取该路径 我想更改该随机字符内的密码 要更新数据库中的特定值 您必须知道该值的完整路径 如果您知道电子邮件地址 但不知道该电子邮件地址的键 则可以使用查询来查找该电子邮
  • 如何从div中获取innerHTML?

    我需要保存 div 的 innerHTML 并将其存储在 cookie 中 这是我的基本代码 The div saving function function addStatus sName getElement bottomDiv inn
  • 以编程方式确定远程桌面协议版本?

    远程桌面协议版本 6 1 更改了 RDP 会话的处理方式 将会话 0 以前表示 控制台会话 更改为非交互式会话 我需要能够从我的程序中弄清楚如何确定当前 RDP 会话正在使用哪个版本的 RD 协议 然而 我在 Windows 终端服务 AP
  • 通过 shell 脚本从文件中读取值并将值放入 WHERE 子句中

    外壳脚本 bin bash sqlplus s
  • 如何在 osx 机器上安装要在 php 中使用的“语言环境”?

    我正在开发一个需要多语言支持的网站 我正在尝试在 php 中使用语言环境 但某个语言环境 es CO 在我的开发计算机中不可用 它位于我的托管服务器上 我研究了如何添加新的区域设置 但找不到如何或在哪里获取新的区域设置文件 它应该安装在操作
  • 方法存在时出现 Java NoSuchMethodError

    我正在参考PlayerUtil getMovementSpeed player 在我的 Speed 类和 PlayerUtil 类中 我将方法定义为 public static double getMovementSpeed Player
  • Python pandas 在滚动日期窗口中最常见的值

    我有一个包含以下数据的 pandas 数据框 我想添加一个新列 对于每个日期 返回过去 3 天内最常出现的 weather type 如果结果是平局 我希望返回最近的 weather type d date 17 02 2017 18 02
  • 身份服务器流程

    IdentityServer 支持不同的 OpenId Connect 流 这些流定义在Flows https github com IdentityServer IdentityServer3 blob 4a44a9f03879c85bb
  • 如何在 ASP.NET MVC 4 中使用 Autofac 注入 HttpContextBase

    我在用ASP MVC 4 and Autofac 我已在我的中注册了以下内容global asax cs file ContainerBuilder builder new ContainerBuilder builder Register
  • 使 JButton 重叠

    我正在 Java Swing 中创建一个虚拟钢琴类型程序 我现在的钢琴键区域是一个带有水平 BoxLayout 的 JPanel 其中包含白色 JButton 作为白键 我还想添加黑键 并让它们与白键重叠 我尝试过两种不同的方法 一种是使用
  • 移动产品描述 Div Woocommerce

    我正在寻找一种方法将产品描述 div 移到我的 site inner wrap 下方的 container 之外 我已经取消注册了这些选项卡 并使用这些功能移动了我的描述 Remove all tabs remove action wooc
  • 带秒差距的完整解析器示例?

    我正在尝试为一种简单的函数式语言 有点像 Caml 制作一个解析器 但我似乎只专注于最简单的事情 所以我想知道是否有一些更完整的例子parsec解析器 超越 这就是解析 2 3 的方式 的东西 特别是术语等中的函数调用 我读过 为你写一个方