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')
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):