【问题标题】:How to describe conditional statement (if-then-else) using PEG如何使用 PEG 描述条件语句(if-then-else)
【发布时间】:2017-08-01 21:55:44
【问题描述】:

我正在研究 Qt 的 qmake 项目文件解析器(开源项目)。 而且我在描述 qmake 的条件语句变体时遇到了麻烦,在文档中称为“范围”。

EBNF(简体):

ScopeStatement -> Condition ScopeBody

Condition -> Identifier | TestFunctionCall | NotExpr | OrExpr | AndExpr
NotExpr -> "!" Condition
OrExpr   -> Condition "|" Condition
AndExpr -> Condition ":" Condition

ScopeBody -> COLON Statement | BR_OPEN Statement:*  BR_CLOSE

Statement -> AssignmentStatement
AssignmentStatement -> Identifier EQ String

// There are many others built-in boolean functions
TestFunctionCall -> ("defined" | ...)  ARG_LIST_OPEN (String COMMA:?):* ARG_LIST_CLOSE

Identifier -> Letter (Letter | Digit | UNDERSCP):+ String -> (Letter | Digit | UNDERSCP):+

EQ -> "="
COLON -> ":"
COMMA -> ","
ARG_LIST_OPEN -> "("
ARG_LIST_CLOSE -> ")"
BLOCK_OPEN -> "{"
BLOCK_CLOSE -> "}"
UNDERSCP -> "_"

第一个问题:如何区分 AND 运算符冒号和条件终结符?有可能吗?

附:我的语法草案(没有函数调用支持)即使对于像这样的简单案例也不起作用

win32:xml: x = y

PEG.JS代码:

Start
  = ScopeStatement

// qmake scope statement
ScopeStatement
  = BooleanExpression ws* ((":" ws* SingleLineStatement) / ("{" ws* MultiLineStatement ))

SingleLineStatement
  = Identifier ws* "=" ws* Identifier lb* 

MultiLineStatement
  = (SingleLineStatement lb*)+

// qmake condition statement
BooleanExpression
  = BooleanOrExpression

BooleanOrExpression
  = left:BooleanAndExpression ws* "|" ws* right:BooleanOrExpression  { return {type: "OR", left:left, right:right} }
  / BooleanAndExpression

BooleanAndExpression
  = left:BooleanNotExpression ws* ":" ws* right:BooleanAndExpression  { return {type: "AND", left:left, right:right} }
  / BooleanNotExpression


BooleanNotExpression
  = "!" ws* operand:BooleanNotExpression { return {type: "NOT", operand: operand } }
  / BooleanComplexExpression


BooleanComplexExpression
  = Identifier
  / "(" logical_or:BooleanOrExpression ")" { return logical_or; }

Identifier
  = token:[a-zA-Z0-9_]+ { return token.join(""); }

ws 
  = [ \t]

lb
  = [\r\n]

谢谢!

【问题讨论】:

  • 条件是否总是由另一个冒号终止?
  • 是的,与条件的格式为 bool_expr1:bool_expr2:...:bool_exprN:

标签: parsing grammar bnf peg pegjs


【解决方案1】:

对于任何BooleanAndExpression 的内容,您需要在BooleanAndExpression 之后包含一个否定的前瞻,否则它将继续贪婪地消耗额外的“和”表达式。

Start
  = ScopeStatement

// qmake scope statement
ScopeStatement
  = bool:BooleanExpression ws* state:Statement  { return {bool:bool, state:state} }

Statement
  = ":" ws* state:SingleLineStatement  { return state }

SingleLineStatement
  = left:Identifier ws* "=" ws* right:Identifier lb*  { return {type: "ASSIGN", left:left, right:right} }

MultiLineStatement
  = (SingleLineStatement lb*)+

// qmake condition statement
BooleanExpression
  = BooleanOrExpression

BooleanOrExpression
  = left:BooleanAndExpression ws* "|" ws* right:BooleanOrExpression  { return {type: "OR", left:left, right:right} }
  / BooleanAndExpression

BooleanAndExpression
  = left:BooleanNotExpression ws* !(":" ws* SingleLineStatement) ":" ws* right:BooleanAndExpression  { return {type: "AND", left:left, right:right} }
  / BooleanNotExpression


BooleanNotExpression
  = "!" ws* operand:BooleanNotExpression { return {type: "NOT", operand: operand } }
  / BooleanComplexExpression


BooleanComplexExpression
  = Identifier
  / "(" logical_or:BooleanOrExpression ")" { return logical_or; }

Identifier
  = token:[a-zA-Z0-9_]+ { return token.join(""); }

ws 
  = [ \t]

lb
  = [\r\n]

【讨论】:

  • 谢谢,这真的很管用!我只是错过了 !SingleLineStatement 的地方
猜你喜欢
  • 2023-03-08
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多