ometa M <: Parser { ident = , expr = expr:x "." ident:f -> ['FieldAccess', x, f] | expr:x "(" ")" -> ['Call', x] | ident:x -> ['Var', x] } M.matchAll('x.y.z()', "expr") M.matchAll('x.y().z', "expr") M.matchAll('x().y.z', "expr") ometa M2 <: M { expr2 = expr:e validate(e) -> e, validate = ['FieldAccess' :x :f] } M2.matchAll('x.y.z()', "expr2") M2.matchAll('x.y().z', "expr2") M2.matchAll('x().y.z', "expr2") ometa M3 <: Parser { ident = , expr = ident validEnding, validEnding = "." ident validEnding | "." ident | "(" ")" validEnding, consumedByExpr = } M3.matchAll('x.y.z()', "consumedByExpr") --> x.y.z M3.matchAll('x.y().z', "consumedByExpr") --> x.y().z M3.matchAll('x().y.z', "consumedByExpr") --> x().y.z