Last active
May 14, 2020 01:01
-
-
Save ligfx/35fc7b8234d28097feeef3a63f516dfc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
**CAOS2PRAY | |
*# Pray-File "elevines.agents" | |
*# DS-Name "Elevines" | |
*# Depend blnk.c16 | |
*# attach elevinehelp.catalogue elevines.c16 | |
*# desc = "An easy-to-use custom elevator system. Read the help file included for details. Lovely sprites by Mea." | |
*# Agent Animation File = "elevines.c16" | |
*# Agent Sprite First Image = 4 | |
*# Agent Animation Gallery = "elevines" | |
*# Web URL = "naturingnurturing.blogspot.com" | |
*# Web Label = "Naturing :: Nurturing" | |
*lift teleporting ball things. | |
new: comp 3 1 21051 "elevines" 13 4 2000 | |
*Inject it where it belongs: | |
*Why are you including a C3 inject script when this isn't even C3 compatible? | |
*Probably because I am lazy and just want to copypaste my install script.... | |
doif gnam eq "Docking Station" | |
setv $creatorx game "CreatorX" | |
setv $creatory game "CreatorY" | |
doif $creatorx eq 0 and $creatory eq 0 | |
setv $creatorx 6110 | |
setv $creatory 9200 | |
endi | |
doif tmvt $creatorx $creatory eq 1 | |
mvto $creatorx $creatory | |
else | |
mvsf $creatorx $creatory | |
endi | |
elif gnam eq "Creatures 3" | |
doif tmvt 5671 3599 eq 1 | |
mvto 5671 3599 | |
else | |
mvsf 5671 3599 | |
endi | |
endi | |
clac 1000 | |
bhvr 3 | |
*activate 1 (1) activate 2 (2) | |
tick 30 | |
attr 198 | |
*mouse pickupable (2) mouseclickable (4) collisions (64) physics (128) | |
accg 30 | |
elas 20 | |
fric 100 | |
perm 100 | |
object_variable $unique_pose ov96 | |
object_variable $unique_tintr ov97 | |
object_variable $unique_tintg ov98 | |
object_variable $unique_tintb ov99 | |
*ov98 and 99 are going to be the random tints, ov97 is the random -pose- | |
setv ov96 rand 0 12 | |
setv ov97 rand 50 200 | |
setv ov98 rand 50 200 | |
setv ov99 rand 50 200 | |
pose ov96 | |
tint ov97 ov98 ov99 128 128 | |
*We'll base your ID number off your tints, just for fun: | |
sets ov00 vtos ov97 | |
adds ov00 vtos ov98 | |
adds ov00 vtos ov99 | |
*parts-- 1, top button, 2, bottom | |
pat: dull 1 "elevines" 0 6 21 1 | |
pat: dull 2 "elevi\nesd\d .. dd" 2 12 72 1 | |
*Push -- Want to go up | |
scrp 3 1 21051 1 | |
inst | |
lock | |
*first off, is it actually possible to go up? | |
*check where you are | |
setv ov10 posy | |
*set the little serchagent to null | |
seta $targetring null | |
*enum through other circles | |
enum 3 1 21051 | |
*only check ones of your code | |
doif mv00 eq ov00 | |
*see if it's on a higher level-- that is, the y coord is less than mv10 | |
doif posy lt mv10 | |
*herein lies the tricky part-- you want it to be lower than the ring | |
*being pushed, but higher than the rest. | |
*so NOW check to see if a previous agent has been found | |
doif $targetring = null | |
*if not, make it the current favorite | |
* so set the ring you just found into $targetring | |
* and the y coord into $targetposy | |
seta $targetring targ | |
setv $targetposy posy | |
*else, you have to check it against the current $targetposy to | |
*make sure it's the highest-lower y coord | |
else | |
doif posy gt $targetposy | |
seta $targetring targ | |
setv $targetposy posy | |
endi | |
endi | |
endi | |
endi | |
next | |
*So $targetring should be the ideal ring to tele to now | |
*assuming there is one. | |
*if there's NOT, stop this whole thing now! | |
doif $targetring eq null | |
*make sure there's a FROM creature | |
doif from ne null | |
*who pushed you? | |
doif from.fmly = 4 | |
*put a bug in it's ear-- stop pushing this! | |
urge writ from 26 -2 -1 2 | |
sndc "buzz" | |
*disappointment | |
stim writ from 0 1 | |
stop | |
else | |
stop | |
endi | |
else | |
stop | |
endi | |
*else there IS a $targetring! | |
else | |
*if it's being carried (like by the hand), stop | |
doif $targetring.movs ne 0 | |
stop | |
endi | |
*now, make sure there's a creature to move | |
doif from ne null | |
doif from.fmly = 4 | |
*Lock it out from creatures for a second! | |
$targetring.tick tick | |
$targetring.attr 214 | |
*now targ the norn | |
*make sure it's not being carried | |
doif from.movs ne 0 | |
stop | |
endi | |
*Make sure it's a VALID place to move it! | |
*and move it! | |
doif from.tmvf $targetring.posx $targetring.posb = 1 | |
from.mvft $targetring.posx $targetring.posb | |
*tell the norn it just travled | |
*and it needs to wait? | |
*tell the norn to STOP now.. | |
*and make some dingysound | |
stim writ from 94 1 | |
stim writ from 75 1 | |
urge writ from 26 -2 -1 2 | |
sndc "snap" | |
else | |
*if it's not a VALID PLACE make a sndc | |
sndc "buzz" | |
stop | |
endi | |
else | |
stop | |
endi | |
endi | |
endi | |
endm | |
*Pull -- Want to go down | |
scrp 3 1 21051 2 | |
inst | |
*first off, is it actually possible to go DOWN? | |
*check where you are | |
setv ov10 posy | |
*set the little serchagent to null | |
seta $targetring null | |
*enum through other circles | |
enum 3 1 21051 | |
*only check ones of your code | |
doif mv00 eq ov00 | |
*see if it's on a higher level-- that is, the y coord is GREATER than mv10 | |
doif posy gt mv10 | |
*herein lies the tricky part-- you want it to be lower than the ring | |
*being pushed, but higher than the rest. | |
*so NOW check to see if a previous agent has been found | |
doif $targetring eq null | |
*if not, make it the current favorite | |
* so set the ring you just found into $targetring | |
* and the y coord into $targetposy | |
seta $targetring targ | |
setv $targetposy posy | |
*else, you have to check it against the current $targetposy to | |
*make sure it's the lowest-higher y coord | |
else | |
doif posy lt $targetposy | |
seta $targetring targ | |
setv $targetposy posy | |
endi | |
endi | |
endi | |
endi | |
next | |
*So $targetring should be the ideal ring to tele to now | |
*assuming there is one. | |
*if there's NOT, stop this whole thing now! | |
doif $targetring eq null | |
*make sure there's a FROM creature | |
doif from ne null | |
*who pushed you? | |
seta $fromcreature from | |
targ $fromcreature | |
doif fmly = 4 | |
*put a bug in it's ear-- stop pulling this! | |
*hi | |
sndc "buzz" | |
urge writ targ 26 -2 -1 2 | |
*disappointment | |
stim writ $fromcreature 0 1 | |
stop | |
else | |
stop | |
endi | |
else | |
stop | |
endi | |
*else there IS a $targetring! | |
else | |
*if it's being carried (like by the hand), stop | |
targ $targetring | |
doif movs ne 0 | |
sndc "buzz" | |
stop | |
endi | |
*now, make sure there's a creature to move | |
doif from ne null | |
doif from.fmly = 4 | |
*set the coords of $targetring into $targetposx and $targetposb | |
*Lock it out from creatures for a second! | |
$targetring.tick $targetring.tick | |
$targetring.attr 214 | |
*now targ the norn | |
*make sure it's not being carried | |
doif from.movs ne 0 | |
stop | |
endi | |
*Make sure it's a VALID place to move it! | |
doif from.tmvf $targetring.posx $targetring.posb = 1 | |
*and move it! | |
from.mvft $targetposx $targetposb | |
*tell the norn it just travled | |
stim writ from 94 1 | |
*tell the norn to STOP now.. | |
urge writ from 26 -2 -1 2 | |
*wait? | |
stim writ from 75 1 | |
*and make some dingysound | |
sndc "snap" | |
else | |
*if it's not a VALID PLACE make a sndc | |
sndc "buzz" | |
stop | |
endi | |
else | |
stop | |
endi | |
endi | |
endi | |
endm | |
*you've been CLICKED or clac'd or something | |
scrp 3 1 21051 1000 | |
inst | |
*Here is how it works.... | |
*shift+click creates a copy of the same OV | |
*ctrl+click creates a copy of a new OV | |
*shift+click kills it. | |
sndc "opn1" | |
*shift -- make a copy, save OV, same tint | |
doif keyd 16 eq 1 and keyd 17 eq 0 | |
sndc "opn1" | |
new: comp 3 1 21051 "elevines" 13 4 2000 | |
*move it to the old one, and make it hop a bit | |
mvsf ownr.posl ownr.post | |
velo 15 100 | |
clac 1000 | |
bhvr 3 | |
*activate 1 (1) activate 2 (2) | |
tick 30 | |
attr 198 | |
*mouse pickupable (2) mouseclickable (4) collisions (64) physics (128) | |
accg 30 | |
elas 20 | |
fric 100 | |
perm 100 | |
*ov97, 96, 98 and 99 are going to be COPIED | |
setv ov96 mv96 | |
setv ov97 mv97 | |
setv ov98 mv98 | |
setv ov99 mv99 | |
pose ov96 | |
tint ov97 ov98 ov99 128 128 | |
*We'll base your ID number off your tints, just for fun: | |
sets ov00 vtos ov97 | |
adds ov00 vtos ov98 | |
adds ov00 vtos ov99 | |
*parts-- 1, top button, 2, bottom | |
pat: dull 1 "elevines" 0 6 21 1 | |
pat: dull 2 "elevines" 2 12 72 1 | |
*ctrl | |
elif keyd 16 eq 0 and keyd 17 eq 1 | |
sndc "unlk" | |
*lift teleporting ball things. | |
new: comp 3 1 21051 "elevines" 13 4 2000 | |
*move it to the old one, and make it hop a bit | |
mvsf ownr.posl ownr.post | |
velo 15 100 | |
clac 1000 | |
bhvr 3 | |
*activate 1 (1) activate 2 (2) | |
tick 30 | |
attr 198 | |
*mouse pickupable (2) mouseclickable (4) collisions (64) physics (128) | |
accg 30 | |
elas 20 | |
fric 100 | |
perm 100 | |
*ov98 and 99 are going to be the random tints, ov96 is the random -pose- | |
setv ov96 rand 0 12 | |
setv ov97 rand 50 200 | |
setv ov98 rand 50 200 | |
setv ov99 rand 50 200 | |
pose ov96 | |
tint ov97 ov98 ov99 128 128 | |
*We'll base your ID number off your tints, just for fun: | |
sets ov00 vtos ov97 | |
adds ov00 vtos ov98 | |
adds ov00 vtos ov99 | |
*parts-- 1, top button, 2, bottom | |
pat: dull 1 "elevines" 0 6 21 1 | |
pat: dull 2 "elevines" 2 12 72 1 | |
*both | |
elif keyd 16 eq 1 and keyd 17 eq 1 | |
kill ownr | |
endi | |
endm | |
*Meh. I tried to avoid using a timer for this but it's just | |
*SO MUCH MORE FLUID with it. ]: | |
scrp 3 1 21051 9 | |
inst | |
*reset the attr if it's been changed | |
attr 198 | |
*mouse pickupable (2) mouseclickable (4) collisions (64) physics (128) | |
*the indicator orbs change color. Yay. | |
setv $ishigher 0 | |
setv $islower 0 | |
*check where you are | |
setv ov10 posy | |
*enum through other circles | |
enum 3 1 21051 | |
*only check ones of your code | |
doif mv00 eq ov00 | |
*see if it's on a higher level-- that is, the y coord is less than mv10 | |
doif posy lt mv10 | |
setv $ishigher 1 | |
*lower? | |
elif posy gt mv10 | |
setv $islower 1 | |
endi | |
endi | |
next | |
*pose accordingly! | |
part 1 | |
pose $ishigher | |
part 2 | |
pose $islower | |
endm | |
rscr | |
enum 3 1 21051 | |
dbg: outv $hello | |
kill targ | |
next | |
* extended stuff | |
dbg: outv ownr.posy | |
from.mvsf 5 6 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
import json | |
import re | |
import string | |
import sys | |
with open("build/generated/commandinfo.json", "rb") as f: | |
COMMAND_INFO = json.loads(f.read()) | |
COMMAND_INFO_C3 = COMMAND_INFO["variants"]["c3"] | |
COMMAND_NAMESPACES = { _.get("namespace") for _ in COMMAND_INFO_C3.values() if _.get("namespace") } | |
def peek(s, index): | |
if index < len(s): | |
return s[index] | |
return None | |
class TokenType: | |
__slots__ = ["name"] | |
def __init__(self, name): | |
self.name = name | |
def __repr__(self): | |
return self.name | |
TOK_COMMENT = TokenType("TOK_COMMENT") | |
TOK_DOLLARWORD = TokenType("TOK_DOLLARWORD") | |
TOK_INTEGER = TokenType("TOK_INTEGER") | |
TOK_STRING = TokenType("TOK_STRING") | |
TOK_WHITESPACE = TokenType("TOK_WHITESPACE") | |
TOK_WORD = TokenType("TOK_WORD") | |
TOK_DOT = TokenType("TOK_DOT") | |
TOK_EOI = TokenType("TOK_EOI") | |
def lexcaos(s): | |
p = 0 | |
while True: | |
basep = p | |
if p >= len(s): | |
yield (TOK_EOI, "") | |
return | |
if s[p] in (" ", "\t", "\r", "\n"): | |
while peek(s, p) in (" ", "\t", "\r", "\n"): | |
p += 1 | |
yield (TOK_WHITESPACE, s[basep:p]) | |
elif s[p] == ".": | |
p += 1 | |
yield (TOK_DOT, ".") | |
elif s[p] in string.ascii_letters + "_": | |
while peek(s, p) and peek(s, p) in string.ascii_letters + string.digits + "*:_": | |
p += 1 | |
yield (TOK_WORD, s[basep:p]) | |
elif s[p] == "$": | |
# nonstandard | |
p += 1 | |
if peek(s, p) is None: | |
raise Exception("While parsing dollar var, got unexpected EOI") | |
if peek(s, p) not in string.ascii_letters + string.digits + "*:_": | |
raise Exception("Expected variable name after '$', got '%s' (%02x)" % (peek(s, p), ord(peek(s, p)))) | |
while peek(s, p) and peek(s, p) in string.ascii_letters + string.digits + "*:_": | |
p += 1 | |
yield (TOK_DOLLARWORD, s[basep:p]) | |
elif s[p] == "-": | |
p += 1 | |
if peek(s, p) is None: | |
raise Exception("While parsing negative number, got unexpected EOI") | |
if peek(s, p) not in string.digits: | |
raise Exception("Expected digit after '-', got '%s' (%02x)" % (peek(s, p), ord(peek(s, p)))) | |
while peek(s, p) and peek(s, p) in string.digits: | |
p += 1 | |
yield (TOK_INTEGER, int(s[basep:p])) | |
elif s[p] in string.digits: | |
while peek(s, p) and peek(s, p) in string.digits: | |
p += 1 | |
yield (TOK_INTEGER, int(s[basep:p])) | |
# if peek(s, p) and peek(s, p) not in (" ", "\t", "\r", "\n"): | |
# raise Exception("Expected whitespace after integer, got '%s' (%02x)" % (s[p], ord(s[p]))) | |
elif s[p] == "\"": | |
p += 1 | |
while True: | |
if p >= len(s): | |
raise Exception("While parsing string, got unexpected EOI") | |
if s[p] == "\"": | |
p += 1 | |
yield (TOK_STRING, s[basep:p]) | |
break | |
elif s[p] == "\\": | |
p += 2 | |
else: | |
p += 1 | |
elif s[p] == "=": | |
p += 1 | |
yield (TOK_WORD, "=") | |
elif s[p] == "*": | |
p += 1 | |
while peek(s, p) != "\n": | |
p += 1 | |
yield (TOK_COMMENT, s[basep:p]) | |
else: | |
raise Exception("Unexpected character '%s' (%02x)" % (s[p], ord(s[p]))) | |
class script: | |
def __init__(self, start, end, vaxx_vars, dollar_vars): | |
self.start = start | |
self.end = end | |
self.vaxx_vars = vaxx_vars | |
self.dollar_vars = dollar_vars | |
class ParserState: | |
__slots__ = ['p', 'tokens'] | |
def __init__(self, tokens): | |
self.tokens = tokens | |
self.p = 0 | |
def peekmatch(self, newp, toktypes): | |
if not isinstance(toktypes, (tuple, list, set)): | |
toktypes = (toktypes,) | |
if self.tokens[newp][0] not in toktypes: | |
raise Exception("Expected %r, got %s\n" % (toktypes, self.tokens[newp][0])) | |
def caosliteral(value, token): | |
return collections.OrderedDict([("type", "Literal"), ("value", value), ("token", token)]) | |
def caosvariable(value, token): | |
return collections.OrderedDict([("type", "Variable"), ("value", value), ("token", token)]) | |
def caoscondition(children, start_token): | |
end_token = children[-1].get("end_token") or children[-1].get("token") | |
return collections.OrderedDict([("type", "Condition"), ("children", children), ("start_token", start_token), ("end_token", end_token)]) | |
def caosconditionkeyword(value): | |
return collections.OrderedDict([("type", "ConditionKeyword"), ("value", value)]) | |
def maybe_eat_whitespace(state): | |
ate_whitespace = False | |
while state.tokens[state.p][0] in (TOK_COMMENT, TOK_WHITESPACE): | |
ate_whitespace = True | |
state.p += 1 | |
return ate_whitespace | |
def eat_whitespace(state): | |
if not maybe_eat_whitespace(state): | |
raise Exception("Expected whitespace or comment, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
def parse_condition(state): | |
left = parse_value(state) | |
eat_whitespace(state) | |
if state.tokens[state.p][0] != TOK_WORD: | |
raise Exception("Expected comparison, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
startp = state.p | |
comparison = state.tokens[state.p][1] | |
state.p += 1 | |
if comparison not in ('eq', 'lt', 'gt', 'ne', '='): | |
raise Exception("Unknown comparison operator '%s'" % comparison) | |
eat_whitespace(state) | |
right = parse_value(state) | |
ate_whitespace = maybe_eat_whitespace(state) | |
if ate_whitespace and state.tokens[state.p][0] == TOK_WORD and state.tokens[state.p][1] in ("and", "or"): | |
combiner = state.tokens[state.p][1] | |
state.p += 1 | |
remainder = parse_condition(state) | |
return caoscondition([left, caosconditionkeyword(comparison), right, caosconditionkeyword(combiner)] + remainder["children"], startp) | |
else: | |
return caoscondition([left, caosconditionkeyword(comparison), right], startp) | |
def parse_directive(state): | |
startp = state.p | |
if state.tokens[state.p][0] != TOK_WORD: | |
raise Exception("Expected directive name, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
directive_name = state.tokens[state.p][1].lower() | |
if directive_name == "object_variable": | |
state.p += 1 | |
eat_whitespace(state) | |
if state.tokens[state.p][0] != TOK_DOLLARWORD: | |
raise Exception("Expected variable name, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
args = [state.tokens[state.p][1]] | |
state.p += 1 | |
eat_whitespace(state) | |
if state.tokens[state.p][0] != TOK_WORD: | |
raise Exception("Expected variable command, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
args.append(state.tokens[state.p][1]) | |
state.p += 1 | |
return {"type": "Directive", "name": "object_variable", "args": args, "start_token": startp, "end_token": state.p - 1} | |
else: | |
raise Exception("Expected directive name, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
def parse_command(state, is_toplevel): | |
startp = state.p | |
dotcommand = False | |
if state.tokens[state.p][0] == TOK_WORD: | |
if is_toplevel and state.tokens[state.p][1].lower() in ('object_variable',): | |
return parse_directive(state) | |
if state.tokens[state.p][1].lower() in COMMAND_NAMESPACES: | |
namespace = state.tokens[state.p][1].lower() | |
state.p += 1 | |
eat_whitespace(state) | |
command = state.tokens[state.p][1].lower() | |
elif state.tokens[state.p + 1][0] == TOK_DOT: | |
dotcommand = True | |
namespace = "" | |
targ = state.tokens[state.p][1].lower() | |
# TODO: check it's a valid command | |
state.p += 2 | |
command = state.tokens[state.p][1].lower() | |
else: | |
namespace = "" | |
command = state.tokens[state.p][1].lower() | |
elif state.tokens[state.p][0] == TOK_DOLLARWORD: | |
if state.tokens[state.p + 1][0] != TOK_DOT: | |
value = state.tokens[state.p][1] | |
state.p += 1 | |
state.peekmatch(state.p, (TOK_WHITESPACE, TOK_COMMENT, TOK_EOI)) | |
return caosvariable(value, startp) | |
dotcommand = True | |
namespace = "" | |
targ = state.tokens[state.p][1].lower() | |
state.p += 2 | |
command = state.tokens[state.p][1].lower() | |
else: | |
raise Exception("Expected command name, got %s %s" % (state.tokens[state.p][0], state.tokens[state.p][1])) | |
commandnormalized = command | |
if re.match(r"(?i)^va\d\d$", command): | |
commandnormalized = "vaxx" | |
if re.match(r"(?i)^ov\d\d$", command): | |
commandnormalized = "ovxx" | |
if re.match(r"(?i)^mv\d\d$", command): | |
commandnormalized = "mvxx" | |
commandinfos = [ | |
_ for _ in COMMAND_INFO_C3.values() | |
if | |
_.get("namespace", "").lower() == namespace | |
and _.get("match", "").lower() == commandnormalized | |
and ((is_toplevel and _.get("type") == "command") or (not is_toplevel and _.get("type") != "command")) | |
] | |
if not commandinfos: | |
raise Exception("Unknown command '%s'" % ((namespace + " " if namespace else "") + command)) | |
assert len(commandinfos) == 1 | |
state.p += 1 | |
if commandinfos[0]["arguments"]: | |
eat_whitespace(state) | |
args = [] | |
for _ in commandinfos[0]["arguments"]: | |
if _["type"] == "condition": | |
args.append(parse_condition(state)) | |
else: | |
args.append(parse_value(state)) | |
if args: | |
end_token = args[-1].get("end_token") or args[-1].get("token") | |
else: | |
end_token = startp | |
if dotcommand: | |
return collections.OrderedDict([ | |
("type", "DotCommand"), | |
("targ", targ), | |
("command", command), | |
("commandtype", ("statement" if is_toplevel else "expression")), | |
("commandret", commandinfos[0]["type"]), | |
("args", args), | |
("start_token", startp), | |
("end_token", end_token) | |
]) | |
else: | |
return collections.OrderedDict([ | |
("type", "Command"), | |
("name", (namespace + " " if namespace else "") + command), | |
("commandtype", ("statement" if is_toplevel else "expression")), | |
("args", args), | |
("start_token", startp), | |
("end_token", end_token) | |
]) | |
def parse_toplevel(state): | |
maybe_eat_whitespace(state) | |
return parse_command(state, True) | |
def parse_value(state): | |
maybe_eat_whitespace(state) | |
startp = state.p | |
if state.tokens[state.p][0] in (TOK_WORD, TOK_DOLLARWORD): | |
return parse_command(state, False) | |
elif state.tokens[state.p][0] == TOK_INTEGER: | |
value = state.tokens[state.p][1] | |
state.p += 1 | |
state.peekmatch(state.p, (TOK_WHITESPACE, TOK_COMMENT, TOK_EOI)) | |
return caosliteral(value, startp) | |
elif state.tokens[state.p][0] == TOK_STRING: | |
value = state.tokens[state.p][1] | |
state.p += 1 | |
state.peekmatch(state.p, (TOK_WHITESPACE, TOK_COMMENT, TOK_EOI)) | |
return caosliteral(value, startp) | |
else: | |
raise Exception("Unimplemented token type %s" % state.tokens[state.p][0]) | |
def parse(tokens): | |
state = ParserState(tokens) | |
fst = [] | |
while True: | |
maybe_eat_whitespace(state) | |
if state.tokens[state.p][0] == TOK_EOI: | |
break | |
fst.append(parse_toplevel(state)) | |
return fst | |
def visit_worddotcommands(t): | |
if t["type"] in ("Command",): | |
prefix = [] | |
newargs = [] | |
for a in t["args"]: | |
more_prefix, arg = visit_worddotcommands(a) | |
prefix += more_prefix | |
newargs.append(arg) | |
t = dict(t) | |
t["args"] = newargs | |
# if prefix: | |
# prefix[0]["preceding_tokens"] = t.get("preceding_tokens", []) + prefix[0].get("preceding_tokens", []) | |
if prefix and t["commandtype"] == "statement": | |
ws = "" | |
for pt in reversed(t.get("preceding_tokens", [])): | |
if pt[0] == TOK_WHITESPACE: | |
ws = pt[1] + ws | |
else: | |
break | |
ws = ws.split("\n")[-1] | |
ws = ws.replace("\r", "") | |
# print("indent '%s'" % ws) | |
for p in prefix: | |
p["preceding_tokens"] = p.get("preceding_tokens", []) + [(TOK_WHITESPACE, ws)] | |
return (prefix, t) | |
elif t["type"] in ("Condition",): | |
prefix = [] | |
newchildren = [] | |
for a in t["children"]: | |
more_prefix, child = visit_worddotcommands(a) | |
prefix += more_prefix | |
newchildren.append(child) | |
t = dict(t) | |
t["children"] = newchildren | |
return (prefix, t) | |
elif t["type"] in ("DotCommand",): | |
if t["commandtype"] == "expression": | |
if t["targ"][0] == "$": | |
varname = t["targ"] + "_" + t["command"] | |
else: | |
varname = "$" + t["targ"] + "_" + t["command"] | |
prefix = [ | |
{"type": "Command", "name": "seta", "args": [ | |
{"type": "Variable", "value": "$__saved_targ"}, | |
{"type": "Command", "name": "targ", "args": []} | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
{"type": "Command", "name": "targ", "args": [ | |
{"type": "Command", "name": t["targ"], "args": []} | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
{"type": "Command", "name": "setv", "args": [ | |
{"type": "Variable", "value": varname}, | |
{"type": "Command", "name": t["command"], "args": t["args"]}, | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
{"type": "Command", "name": "targ", "args": [ | |
{"type": "Variable", "value": "$__saved_targ"} | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
] | |
t = {"type": "Variable", "value": varname} | |
elif t["commandtype"] == "statement": | |
prefix = [ | |
{"type": "Command", "name": "seta", "args": [ | |
{"type": "Variable", "value": "$__saved_targ"}, | |
{"type": "Command", "name": "targ", "args": []} | |
], "preceding_tokens": t.get("preceding_tokens", [])}, | |
{"type": "Command", "name": "targ", "args": [ | |
{"type": "Command", "name": t["targ"], "args": []} | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
{"type": "Command", "name": t["command"], "args": t["args"], | |
"preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
{"type": "Command", "name": "targ", "args": [ | |
{"type": "Variable", "value": "$__saved_targ"} | |
], "preceding_tokens": [("TOK_WHITESPACE", "\n")]}, | |
] | |
t = {} | |
return (prefix, t) | |
else: | |
return ([], t) | |
def print_node(t): | |
if not t: | |
return | |
if t.get("preceding_tokens"): | |
for pt in t["preceding_tokens"]: | |
sys.stdout.write(str(pt[1])) | |
if t["type"] == "Command": | |
sys.stdout.write(t["name"]) | |
for a in t["args"]: | |
sys.stdout.write(" ") | |
print_node(a) | |
elif t["type"] == "Literal": | |
sys.stdout.write(str(t["value"])) | |
elif t["type"] == "ConditionKeyword": | |
sys.stdout.write(str(t["value"])) | |
elif t["type"] == "Variable": | |
sys.stdout.write(t["value"]) | |
elif t["type"] == "Condition": | |
for a in t["children"]: | |
print_node(a) | |
sys.stdout.write(" ") | |
elif t["type"] == "DotCommand": | |
sys.stdout.write(t["targ"] + "." + t["command"]) | |
for a in t["args"]: | |
sys.stdout.write(" ") | |
print_node(a) | |
elif t["type"] == "Directive": | |
sys.stdout.write(t["name"]) | |
for a in t["args"]: | |
sys.stdout.write(" " + a) | |
else: | |
raise Exception("unhandled node type %s" % t["type"]) | |
def main(): | |
if len(sys.argv) == 2: | |
with open(sys.argv[1], 'rb') as f: | |
text = f.read() | |
elif len(sys.argv) == 1: | |
sys.stderr.write("Reading from stdin...") | |
text = sys.stdin.read() | |
else: | |
sys.stderr.write("USAGE: %s [FILE]" % sys.argv[0]) | |
exit(1) | |
tokens = list(lexcaos(text)) | |
fst = parse(tokens) | |
print(json.dumps(fst, indent=2)) | |
tokenp = 0 | |
for toplevel in fst: | |
toplevel["preceding_tokens"] = [] | |
while tokenp < toplevel["start_token"]: | |
toplevel["preceding_tokens"].append(tokens[tokenp]) | |
tokenp += 1 | |
tokenp = toplevel["end_token"] + 1 | |
object_variables = {} | |
i = 0 | |
while i < len(fst): | |
t = fst[i] | |
if t["type"] == "Directive" and t["name"] == "object_variable": | |
object_variables[t["args"][0]] = t["args"][1] | |
del fst[i] | |
else: | |
i += 1 | |
newfst = [] | |
for toplevel in fst: | |
prefix, t = visit_worddotcommands(toplevel) | |
newfst += prefix | |
newfst.append(t) | |
# i = 0 | |
# while i < len(newfst): | |
# t0 = newfst[i] | |
# a0 = peek(t0.get("args", []), 0) | |
# t1 = peek(newfst, i + 1) | |
# if ( | |
# t0 | |
# and t0["type"] == "Command" | |
# and t0["name"] == "targ" | |
# and a0["type"] == "Variable" | |
# and a0["value"] == "$__saved_targ" | |
# and t1 | |
# and t1["type"] == "Command" | |
# and t1["name"] == "seta" | |
# and t1["args"][0]["type"] == "Variable" | |
# and t1["args"][0]["value"] == "$__saved_targ" | |
# and t1["args"][1]["type"] == "Command" | |
# and t1["args"][1]["name"] == "targ" | |
# ): | |
# del newfst[i] | |
# else: | |
# i += 1 | |
for toplevel in newfst: | |
print_node(toplevel) | |
exit() | |
scripts = [script(0, 0, set(), set())] | |
for i, t in enumerate(tokens): | |
if t[0] == TOK_WORD and t[1].lower() in ("scrp", "rscr"): | |
scripts.append(script(i, i, set(), set())) | |
continue | |
if t[0] == TOK_WORD and re.match(r"(?i)^va\d\d$", t[1]): | |
scripts[-1].vaxx_vars.add(t[1].lower()) | |
if t[0] == TOK_DOLLARWORD: | |
scripts[-1].dollar_vars.add(t[1]) | |
scripts[-1].end = i | |
for s in scripts: | |
var_mapping = {} | |
for d in s.dollar_vars: | |
possibles = ["va{:02}".format(i) for i in range(100) if "va{:02}".format(i) not in (list(s.vaxx_vars) + var_mapping.values())] | |
if not possibles: | |
raise Exception("Couldn't allocate variable for '%s'" % d) | |
var_mapping[d] = possibles[0] | |
print_mapped_line = False | |
line = [] | |
for t in tokens[s.start:s.end]: | |
if (t[0] == TOK_WHITESPACE and "\n" in t[1]) or (t[0] == TOK_COMMENT): | |
if print_mapped_line: | |
sys.stdout.write(" * ") | |
for lt in line: | |
sys.stdout.write(str(lt[1])) | |
print_mapped_line = False | |
line = [] | |
else: | |
line.append(t) | |
if t[0] == TOK_DOLLARWORD: | |
print_mapped_line = True | |
sys.stdout.write(var_mapping[t[1]]) | |
else: | |
sys.stdout.write(str(t[1])) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment