STATEMENT = CONDITION | OPERATION | SUBTREE
OPERATION = WS VARNAME WS ( '=' | '+=' ) WS EXPRESSION
-SUBTREE = WS VARNAME WS '{' BLOCK '}'
+SUBTREE = WS VARNAME WS '{' BLOCK WS '}'
CONDITION = WS 'if' FORMULA WS '{' BLOCK WS '}'
FORMULA = WS (( EXPRESSION WS ( '!=' | '==' ) WS EXPRESSION ) | '(' AND WS ')' | '(' OR WS ')' | NOT )
OR = FORMULA WS 'or' FORMULA
NOT = WS 'not' FORMULA
+NOTE: ';' or '\n' is currently required even after CONDITION and SUBTREE block
+ TODO: change to OPERATION only
NOTE: Formula may contain additional/extra parentheses
EXPRESSION = '"' ( ECHAR | '{' VARNAME '}' )* '"' | re"'[^'\\n]*'"
import re, types, itertools, logging as log
import traceback
-import conf
+import moe.conf
-class ConfigSyntaxError(Exception):
- # TODO: choose a better superclass
+class ConfigSyntaxError(conf.ConfigError):
def __init__(self, msg, fname='<unknown>', line=None, column=None):
self.msg = msg
self.fname = fname
def __str__(self):
return('ConfigSyntaxError %s:%d:%d: %s'%(self.fname, self.line, self.column, self.msg))
-"Variable name regexp, dots (separators) must be separated from edges and each other."
-re_VARNAME = re.compile(r'\A([A-Za-z0-9_-]+\.)*[A-Za-z0-9_-]+\Z')
-
class ConfigParser(object):
c_varname_sep = u'.'
c_comment = u'#'
def next(self, l = 1):
"Eat and return next `l` unicode characters. Raise exception on EOF."
if not self.preread(l):
- raise ConfigSyntaxError("Unexpected end of file")
+ self.syntax_error("Unexpected end of file")
s = self.buf[self.bufpos:self.bufpos+l]
self.bufpos += l
rnl = s.rfind('\n')
def p_CONDITION(self):
self.dbg() # Debug
self.p_WS()
+ t = u"condition at %s:%d:%d"%(self.fname, self.line, self.column)
self.expect(self.c_if)
self.p_WS()
f = self.p_FORMULA()
- cnd = conf.ConfigCondition(f)
+ cnd = conf.ConfigCondition(f, text=t, parent=(self.conditions and self.conditions[-1]) or None)
self.conditions.append(cnd)
# Parse a block
self.p_WS()
while self.peek().isalnum() or self.peek() in u'-_.':
vnl.append(self.next())
vn = u''.join(vnl)
- if not re_VARNAME.match(vn):
+ if not conf.re_VARNAME.match(vn):
self.syntax_error('Invalid variable name %r', vn)
return vn
def p_EXPRESSION(self):