-
Notifications
You must be signed in to change notification settings - Fork 4
parser
###parser builtins(parser.coffee/.js)
daonode solver have no special demand on solver'state, so we can develop any kind of parser command, to parse different kind of object, such as array, sequence, list, binary stream, tree, even any other general object, not limit to text.
parser builtins can be used by companion with any other builtins and user command.
logic var can be used in parser as parameter, parameterized grammar is the unique feature of dao.
similar to develop parser, dao can be as the base to develop a generator. We can also generate stuff at th same time of parsing.
####parser state control/access
parse, setstate, getstate have no demand on solver.state
parsesequence/ parsetext, setsequence/ settext, getsequence/ gettext, getpos, step, lefttext, nextchar: demand that solver.state should look like [sequence, index], and sequence can be indexed by integer. index is an integer.
lefttext, subtext, eoi, boi: demand that sequence should have length property
eol, bol: demand that sequence should be an string(check "\r\n").
parse(state): parse exp on state
parsetext(exp, sequence), parsesequence(exp, sequence): parse exp on [sequence, 0]
setstate(state): solver.state = state
settext(sequence), setsequence, settext: solver.state = [sequence, 0]
getstate: get solver.state
gettext, getsequence: get solver.state[0]
In the description below, [text, pos] = solver.state
getpos: solver.state[1]
eoi: end of input, means pos>=text.length
boi: begin of input, means pos==0
eol: end of line text[pos] in "\r\n"
bol: begin of line text[pos-1] in "\r\n"
step(n=1): step to next char in text
lefttext: return left text
subtext: return text[start...start+length]
nextchar: text[pos]
####general predicate
follow(item):
if item is followed, succeed, else fail. after eval, state is restored
notfollow(item):
if item is NOT followed, succeed, else fail. after eval, state is restored
parallel(args, checkFunction = (state, baseState) -> state[1] is baseState[1]):
between current state and right, all args succeed,
and reach the right where checkParallel(solver.state, right) is true
in a simple case: all clauses succeed in same length piece
######normal mode, lazy mode, greedy mode
normal mode: try the goal at first,
after succeed, if need, backtracking happens to try the goal again.
greedy mode: goes forward at first,
after succeed, no backtracking happens on the goal.
lazy mode: goes foward without trying the goal,
if failed, backtrack to goal and try again.
see test_parser for more informations.
######result and template
The builtins below may have result and template as parameter. The usage of them is below:
result: should be an dao.Var, and always be bound to the result array.
template: the item in result array is by calling getvalue(template)
######may, lazymay, greedymay
may(exp): aka optional
lazymay(exp): lazy optional
greedymay(exp): greedy optional
######any, lazyany, greedyany
any(exp):
any(exp, result, template): zero or more exp, normal mode
lazyany(exp),
lazyany(exp, result, template): zero or more exp, lazy mode
greedyany(exp),
greedyany(exp, result, template): zero or more exp, greedy mode
######some, lazysome, greedysome
some(exp):
some(exp, result, template): zero or more exp, normal mode
lazysome(exp),
lazysome(exp, result, template): zero or more exp, lazy mode
greedysome(exp),
greedysome(exp, result, template): zero or more exp, greedy mode
times(exp, expectTimes)
times(exp, expectTimes, result, template)
expectTimes may be integer, variable bound to integer, or free variable.
if expectTimes is free variable, then times behaviour like any, may match zero times of exp!!!
seplist(exp, options={}):
one or more exp separated by sep
expectTimes should be integer or dao.Var
if expectTimes is free dao.Var, then seplist behaviour like some(normal node), at least one exp is matched.
sep = options.sep or char(' ');
expectTimes = options.times or null
result = options.result or null;
template = options.template or null
####terminals
char(x): match one char
if x is char or bound to char, then match that given char with next
else match with next char, and bound x to it.
followChar(x): follow given char?
x should be char or be bound to char
notFollowChar(x): not follow given char?
x should be char or be bound to char
followChars(chars): follow one of given chars?
chars should be string or be bound to string
notFollowChars(chars):not follow one of char in chars
chars should be string or be bound to string
charWhen(test): next char pass test?
test should be an function with single argument
charBetween(start, end)
charIn(set): match one of char in set?
theses terminal below should be used directly, NO suffix with ()
digit = charWhen((c)->'0'<=c<='9')
digit1_9 = charWhen((c)->'1'<=c<='9')
lower = charWhen((c)->'a'<=c<='z')
upper = charWhen((c)->'A'<=c<='Z')
letter = charWhen((c)-> ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetter = charWhen((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetterDight = charWhen((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z') or ('0'<=c<='9'))
tabspace = charIn(' \t')
whitespace = charIn(' \t\r\n')
newline = charIn('\r\n')
spaces: one or more spaces(' ')
usage: spaces # !!! NOT spaces()
spaces0: zero or more spaces(' ')
usage: spaces0 # !!! NOT spaces0()
stringWhile(test): match a string, every char in the string should pass test
test: a function with single argument
the string should contain on char at least!!!
stringBetween(start, end): match a string, every char in which is between start and end
stringIn(set): match a string, every char in which is in set
theses terminals below should be used directly, NO suffix with ()
digits = stringWhile((c)->'0'<=c<='9')
digits1_9 = stringWhile((c)->'1'<=c<='9')
lowers = stringWhile((c)->'a'<=c<='z')
uppers = stringWhile((c)->'A'<=c<='Z')
letters = stringWhile((c)-> ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetters = stringWhile((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetterDights = stringWhile((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z') or ('0'<=c<='9'))
tabspaces = stringIn(' \t')
whitespaces = stringIn(' \t\r\n')
newlinespaces = stringIn('\r\n')
stringWhile0(test): match a string, every char in it passes test
test: a function with single argument
the string can be empty string!!!
stringBetween0(start, end)
stringIn0(set)
theses terminals below should be used directly, NO suffix with ()
digits0 = stringWhile0((c)->'0'<=c<='9')
digits1_90 = stringWhile0((c)->'1'<=c<='9')
lowers0 = stringWhile0((c)->'a'<=c<='z')
uppers0 = stringWhile0((c)->'A'<=c<='Z')
letters0 = stringWhile0((c)-> ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetters0 = stringWhile0((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z'))
underlineLetterDights0 = stringWhile0((c)-> (c is '') or ('a'<=c<='z') or ('A'<=c<='Z') or ('0'<=c<='9'))
tabspaces0 = stringIn0(' \t')
whitespaces0 = stringIn0(' \t\r\n')
newlines0 = stringIn0('\r\n')
float(arg): match a number, which can be float format..
if arg is free dao.Var, after matching, arg would be bound to the number
else arg should equal to the number.
literal(arg): match given literal arg,
arg is a string or a var bound to a string.
followLiteral(arg): follow given literal arg
arg is a string or a var bound to a string.
solver.state is restored after match.
notfollowLiteral(arg): not follow given literal arg
arg is a string or a var bound to a string.
solver.state is restored after match.
quoteString(quote): match a quote string quoted by quote, quote can be escapedby
dqstring: double quoted string "..."
usage: dqstring #!!! not dqstring()
sqstring: single quoted string '...'
usage: sqstring #!!! not sqstring()