c++ - 使用 C++11 正则表达式捕获上下文无关语法文件的内容

标签 c++ regex parsing context-free-grammar lexer

前言

我正在尝试编写我自己的上下文无关语法规范,以与我的词法分析器/解析器的规则相关联。它与 ANTLR 的相似。的,其中大写标识符归类为 Lexer 规则,小写标识符归类为 Parser 规则。它旨在接受词法分析器规则的字符串文字和/或正则表达式的任何组合,以及分析器规则的词法分析器/正则表达式规则和/或其他分析器标识符的任何组合。每条规则都是:;

的格式

这是一个语法示例:

integer      : DIGIT+;        //parser rule containing at least one lexer rule
twodigits    : DIGIT DIGIT;   //parser rule containing two consecutive lexer rules
DIGIT        : [0-9];         //lexer rule containing regex
string       : '"' CHAR* '"'; //parser rule containing zero or more 
                              //  lexer rules, wrapped in two string literals
CHAR         : (LCHAR|UCHAR); //lexer rule containing two lexer rules which
                              //  will later evaluate to one of two tokens
LCHAR        : [a-z];         //lexer rule containing regex
UCHAR        : [A-Z];         //lexer rule containing regex
SPACE        : ' ';           //lexer rule containing string literal


问题

我遇到的问题是匹配表达式字符串的能力,因为它们的内容往往会有所不同。
我原来是这样写的:
([a-zA-Z0-9_]*)(?:\s*)(?:\:)(?:\s*)((?:\'?).*(?:\' ?)(?:\;))
作为匹配规则,它适用于用单引号括起来的单个字符串文字表达式,但我需要扩展它以允许多个非贪婪字符串文字,以及由任意数量的空格分隔的组合语句。我不关心在匹配的表达式中匹配潜在的正则表达式,甚至捕获表达式的分离部分,因为稍后由单独的正则表达式操作处理,所以我真的只需要验证标识符和表达式...

总而言之,我需要 regex_search 操作来查看语法的内容,使用以下语法进行匹配:

  • 一个有效的标识符,以一个或多个小写或大写字母开头,可选地后跟任意数量的字母数字字符(可选地可以包含任意数量的下划线字符,只要标识符不不以一个开头或结尾)。
  • 任意数量的空白字符、制表符、换行符等,无需捕获。
  • 一个冒号而不捕获它。
  • 任意数量的空白字符、制表符、换行符等,无需捕获。
  • 至少一个:(以任何顺序)任意数量的字符串文字(用单引号括起来,不捕获引号),任意数量的词法分析器/解析器标识符,任意数量的正则表达式的(括在方括号中)。此匹配规则的结果应将整个表达式捕获为单个字符串,稍后将进入后处理阶段。
  • 任意数量的空白字符、制表符、换行符等,无需捕获。
  • 一个分号(可选)后跟任何未捕获的空格。
  • 可选,任意数量的未捕获空格后跟单个捕获的行注释
  • 任意数量的空白字符、制表符、换行符等,无需捕获。

问题

是否可以将其放入单个 regex_search 操作中?
我在 Expresso 搞砸了而且似乎无法正确处理...


更新

到目前为止,我已经能够想出以下内容:

#/////////////////////
# Identifier
#/////////////////////
(
    (?:[a-zA-Z]+)           # At least one lower/uppercase letter
    (?:
        (?:[a-zA-Z0-9_]*)   # Zero or more alphanumeric/underscore characters,
        (?:\w+)             # explicitly followed by one or more alphanumeric
    )?                      #   characters
)

#/////////////////////
# Separator
#/////////////////////
(?:\s*)                     # Any amount of uncaptured whitespace
(?:\:)                      # An uncaptured colon
(?:\s*)                     # Any amount of uncaptured whitespace

#///////////////////////
# Expression
#///////////////////////
(
    # String Literals:
    (?:\'?)                 # An optional single quote,
    (?:                     #   which is meant to start and end a string
        (?:[^'\\] | \\.)*   #   literal, but issues several problems for
    )                       #   me (see comments below, after this code block)
    (?:\'?)
    # Other expressions
    # ????????????
)

#/////////////////////
# Line End
#/////////////////////
(?:\s*)                     # Any amount of uncaptured whitespace
(?:\;)                      # An uncaptured colon
(?:\s*)                     # Any amount of uncaptured whitespace

如您所见,我的标识符分隔符行尾 工作得很好。但是表达式是我完全卡住的地方!

我如何告诉正则表达式库我想要EITHER一个非贪婪字符串文字,OR行尾之前的任何字符集,AND 任意数量,任意顺序?

即使我只允许一个字符串文字,我怎么说 "The closing single quote is NOT optional if the first one exists"?

最佳答案

它可能不是完美无缺的,并且可能需要在如何处理匹配结果方面进行额外编码,但这似乎可行:

#/////////////////////
# Identifier
#/////////////////////
(
    (?:[a-zA-Z]+)
    (?:
        (?:[a-zA-Z0-9_]*)
        (?:\w+)
    )?
)

#/////////////////////
# Separator
#/////////////////////
(?:\s*\:\s*)

#///////////////////////
# Expression
#///////////////////////
(
    '(?:\\\\.|[^'])*'|[^']+     # Might need to be processed separately
)

#/////////////////////
# Line End
#/////////////////////
(?:\s*\;\s*)

关于c++ - 使用 C++11 正则表达式捕获上下文无关语法文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15351153/

相关文章:

c# - 在 C# 中使用 Regex 比较两个不同的文件夹

r - 如何将表达式传递给 ggplot 中的 geom_text 标签? (继续)

c++ - 如何选择从QCPCurve的哪一侧填充渐变?

c++ - 将 gethostbyname 替换为 ICMP 的 getaddrinfo (IcmpSendEcho)

c++ - 为什么shared_ptr不能解析函数接口(interface)中的继承关系?

java - 使用带有多个分隔符的 String.split()

c++ - for循环中的混合声明

JavaScript 模式匹配

c++ - 解析不同的 xml 消息。版本

parsing - X 后响应退出