如何使用ParseKit语法来解析一个简单的布尔表达式语言

时间:2013-03-19 19:04:23

标签: parsing expression grammar parsekit

尝试构建一个解析简单bool表达式的语法 当有多个表达时,我遇到了一个问题 我需要能够解析1..n and/or'ed表达式。

以下每个示例都是完整的表达式:

  1. (myitem.isavailable("1234") or myitem.ispresent("1234")) and myitem.isready("1234")
  2. myitem.value > 4 and myitem.value < 10
  3. myitem.value = yes or myotheritem.value = no
  4. 语法:

    @start = conditionalexpression* | expressiontypes;
    
    conditionalexpression = condition expressiontypes;
    
    expressiontypes = expression | functionexpression;
    
    expression = itemname dot property condition value;
    
    functionexpression = itemname dot functionproperty;
    
    itemname = Word;
    
    propertytypes = property | functionproperty;
    
    property = Word;
    
    functionproperty =  Word '(' value ')';
    
    value = Word | QuotedString | Number;
    
    condition = textcondition;
    
    dot = '.';
    
    textcondition = 'or' | 'and' | '<' | '>' | '=';
    

1 个答案:

答案 0 :(得分:1)

ParseKit的开发人员。

这是一个匹配您的示例输入的ParseKit语法:

@start = expr;

expr = orExpr;

orExpr = andExpr orTerm*;
orTerm = 'or' andExpr;

  // 'and' should bind more tightly than 'or'
andExpr = relExpr andTerm*;
andTerm = 'and' relExpr;

  // relational expressions should bind more tightly than 'and'/'or'
relExpr = callExpr relTerm*;
relTerm = relOp callExpr;

  // func calls should bind more tightly than relational expressions
callExpr = primaryExpr ('(' argList ')')?;
argList = Empty | atom (',' atom)*;

primaryExpr     = atom | '(' expr ')';
atom            = obj | literal;

  // member access should bind most tightly
obj     = id member*;
member  = ('.' id);

id      = Word;
literal = Number | QuotedString | bool;
bool    = 'yes' | 'no';

relOp   = '<' | '>' | '=';

让你知道我是如何达到这个语法的:

  1. 我意识到您的语言是一个简单,可组合的表达式语言。
  2. 我记得XPath 1.0也是一个相对简单的表达语言,具有易于使用/可读的语法。
  3. 我访问了XPath 1.0 spec online并快速扫描了XPath基本语言语法。这有助于提供一个快速的起点,用于设计您的语言语法。 如果忽略XPath表达式的路径表达式部分,XPath是基本表达式语言的一个非常好的模板。
  4. 上面的语法成功解析了所有示例输入(见下文)。希望这会有所帮助。

    [foo, ., bar, (, "hello", ), or, (, bar, or, baz, >, bat, )]foo/./bar/(/"hello"/)/or/(/bar/or/baz/>/bat/)^
    [myitem, ., value, >, 4, and, myitem, ., value, <, 10]myitem/./value/>/4/and/myitem/./value/</10^
    [myitem, ., value, =, yes, or, myotheritem, ., value, =, no]myitem/./value/=/yes/or/myotheritem/./value/=/no^