Parsing 解析项的FParsec和后缀修饰符
作为我自己的一个练习,我正在使用FParsec编写一个函数,该函数可以从(有限的)正则表达式形式的规范中生成随机字符串 例如 我有很多工作要做,但我对后缀词的概念有点困惑(即解析器可能需要返回并修改输出,而不仅仅是字符流中的位置)。例如“a”对“a+” 以下是我的域类型的精简版本:Parsing 解析项的FParsec和后缀修饰符,parsing,f#,fparsec,Parsing,F#,Fparsec,作为我自己的一个练习,我正在使用FParsec编写一个函数,该函数可以从(有限的)正则表达式形式的规范中生成随机字符串 例如 我有很多工作要做,但我对后缀词的概念有点困惑(即解析器可能需要返回并修改输出,而不仅仅是字符流中的位置)。例如“a”对“a+” 以下是我的域类型的精简版本: type Count = | ExactCount of int | MinCount of int | MaxCount of int | RangeCount of int * i
type Count =
| ExactCount of int
| MinCount of int
| MaxCount of int
| RangeCount of int * int
type Term =
| CharLiteral of char
| Count of Term * Count
type RandExpSpec = Term list
因此输入ab
应该生成[CharLiteral'a';CharLiteral'b']
,但是ab+
应该生成[CharLiteral'a';Count(CharLiteral'b',MinCount 1)]
。这意味着,在流中遇到Count
术语时,解析器需要回溯输出,以便将最后一个术语包装到另一个对象中
现在,我不知道怎么做。以下是我当前的解析定义,它确实(大部分)有效,但效率非常低:
let parseCharLiteral = choice [ letter; digit ] |>> CharLiteral
let rec parseTerm =
parse.Delay(fun () -> choice [ parseCharLiteral ])
and parseCount =
parseTerm
.>>. choice [ skipChar '*' >>% (MinCount 0)
skipChar '+' >>% (MinCount 1)
skipChar '?' >>% (RangeCount(0, 1)) ]
|>> Count
let parseTerms =
many ((attempt parseCount) <|> parseTerm) .>> eof
但是我不能这样做,因为
parseCount
q需要包装parseTerm返回的上一个术语,我认为您可以使用opt
允许parseCount
在没有计数的情况下不查找计数:
=
语法术语
.>>. 选项(选项[skipChar'*'>>%(最小计数0)
skipChar“+”>>%(最小计数1)
skipChar'?'>>%(范围计数(0,1)))
|>>作用
|术语,无->术语
|术语,某些计数->计数(术语,计数)
让我们来分析术语=
许多parseCount.>>eof
let parseCharLiteral = choice [ letter; digit ] |>> CharLiteral
let rec parseTerm =
parse.Delay(fun () -> choice [ parseCharLiteral ])
and parseCount =
parseTerm
.>>. choice [ skipChar '*' >>% (MinCount 0)
skipChar '+' >>% (MinCount 1)
skipChar '?' >>% (RangeCount(0, 1)) ]
|>> Count
let parseTerms =
many ((attempt parseCount) <|> parseTerm) .>> eof
let parseCharLiteral = choice [ letter; digit ] |>> CharLiteral
let rec parseTerm =
parse.Delay(fun () -> choice [ parseCharLiteral ] .>>. (attempt parseCount))
and parseCount =
choice [ skipChar '*' >>% (MinCount 0)
skipChar '+' >>% (MinCount 1)
skipChar '?' >>% (RangeCount(0, 1)) ]
|>> Count
let parseTerms =
many parseTerm .>> eof