Advertisement
Guest User

Untitled

a guest
Apr 3rd, 2020
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * GScript was mostly created to be a very simple way to write continuation-
  3.  * based scripts.
  4.  */
  5.  
  6. var fs = require('fs');
  7.  
  8. function split(f) {
  9.     return f.replace(/\r\n/g, '\n').split('\n');
  10. }
  11.  
  12. function until(str, terminal) {
  13.     return str.substring(0, str.indexOf(terminal));
  14. }
  15.  
  16. function clean(l) {
  17.     return l.map( (e) => {
  18.         if (e.indexOf('//') >= 0) {
  19.             return until(e, '//');
  20.         }
  21.         return e;
  22.     }).map( e => e.trim() ).filter( e => e.length != 0);
  23. }
  24.  
  25. function lex(l) {
  26.     let root;
  27.     let instructions = [];
  28.  
  29.     let name = "root";
  30.     let id = 1;
  31.    
  32.     while (l.length > 0) {
  33.         let i = l.shift();
  34.         // label
  35.         if (i.endsWith(':')) {
  36.             name = until(i, ':');
  37.             id = 1;
  38.             continue;
  39.         }
  40.  
  41.         let instruction = {
  42.             key: id == 1 ? name : name + "-" + id
  43.         }
  44.         id++;
  45.  
  46.         if (!root) root = instruction.key;
  47.  
  48.         let space = i.indexOf(' ') > 0 ? i.indexOf(' ') : i.length;
  49.         instruction.command = i.substring(0, space);
  50.         instruction.args = i.substring(space + 1);
  51.  
  52.         // multiline
  53.         if (i.startsWith('switch') ||
  54.             i.startsWith('userchoice') ||
  55.             i.startsWith('hasitem') ||
  56.             i.startsWith('megaswitch') ||
  57.             i.startsWith('questcomplete')
  58.         ) {
  59.             let ml = [];
  60.             while (true) {
  61.                 i = l.shift();
  62.                 if (i != 'end')
  63.                     ml.push(i);
  64.                 else
  65.                     break;
  66.             }
  67.             instruction.children = ml;
  68.         }
  69.         instructions.push(instruction);
  70.     }
  71.     return { root: root, instructions: instructions };
  72. }
  73.  
  74. function desugar(l) {
  75.     let desugared = [];
  76.     for (let i in l.instructions) {
  77.         let ii = l.instructions[i];
  78.  
  79.         if (ii.command == 'megaswitch') {
  80.             let base = ii.key;
  81.             for (let j in ii.children) {
  82.                 let s = ii.children[j].split('->');
  83.                 let condition = s[0].trim();
  84.                 let label = s[1].trim();
  85.                
  86.                 let cParsed = condition.split(' ');
  87.                 let cCommand = cParsed[0].trim();
  88.                 if (cCommand == 'var') {
  89.                     let v = cParsed[1].trim();
  90.                     let vv = cParsed[2].trim();
  91.                     desugared.push({
  92.                         key: base + ((j == 0) ? "" : j),
  93.                         command: "switch",
  94.                         args: v,
  95.                         children: [
  96.                             vv + "->" + label,
  97.                             "false" + "->" + base + (Number(j) + 1)
  98.                         ]
  99.                     })
  100.                 } else if (cCommand == 'hasitem') {
  101.                     let v = cParsed[1].trim();
  102.                     desugared.push({
  103.                         key: base + ((j == 0) ? "" : j),
  104.                         command: "hasitem",
  105.                         args: v,
  106.                         children: [
  107.                             "true" + "->" + label,
  108.                             "false" + "->" + base + (Number(j) + 1)
  109.                         ]
  110.                     })
  111.                 } else if (cCommand == 'default') {
  112.                     desugared.push({
  113.                         key: base + j,
  114.                         command: "noop",
  115.                         args: label
  116.                     });
  117.                 }
  118.             }
  119.         } else {
  120.             desugared.push(ii);
  121.         }
  122.     }
  123.     return { root: l.root, instructions: desugared };
  124. }
  125.  
  126. function convert(i) {
  127.     let program = { root: i.root }
  128.  
  129.     let conversation = {};
  130.    
  131.     for (let j in i.instructions) {
  132.         let ii = i.instructions[j];
  133.  
  134.         let compiled = {
  135.            
  136.         }
  137.  
  138.         let key = ii.key;
  139.        
  140.         let n = i.instructions[Number(j) + 1];
  141.         if (!n || n.command == 'end') {
  142.             compiled.next = false;
  143.         } else if (n.command == 'goto') {
  144.             compiled.next = n.args.trim();
  145.         } else if (n.key) {
  146.             compiled.next = n.key;
  147.         } else {
  148.             console.log("Next instruction is unknown " + JSON.stringify(n));
  149.         }
  150.  
  151.         //console.log(JSON.stringify(ii));
  152.  
  153.         switch (ii.command) {
  154.             case 'end':
  155.                 continue;
  156.             case 'goto':
  157.                 continue;
  158.             case 'noop':
  159.                 compiled.type = 'noop';
  160.                 break;
  161.             case 'npcmessage':
  162.                 compiled.type = 'message'
  163.                 compiled.speaker = '$npc'
  164.                 compiled.message = ii.args
  165.                 break;
  166.             case 'playermessage':
  167.                 compiled.type = 'message'
  168.                 compiled.speaker = '$player'
  169.                 compiled.message = ii.args
  170.                 break;
  171.             case 'narration':
  172.                 compiled.type = 'message'
  173.                 compiled.message = ii.args
  174.                 break;
  175.             case 'simplemessage':
  176.                 compiled.type = 'simplemessage'
  177.                 compiled.speaker = ''
  178.                 compiled.message = ii.args
  179.                 break;
  180.             case 'passdoor':
  181.                 compiled.type = 'passdoor'
  182.                 compiled.args = ii.args
  183.                 break;
  184.             case 'questcomplete':
  185.                 compiled.type = 'questcomplete';
  186.                 compiled.xp = {};
  187.                 for (let m in ii.children) {
  188.                     let mm = ii.children[m];
  189.                     let s = mm.split(' ');
  190.                     if (s[0].trim() == 'quest') {
  191.                         compiled.quest = s[1].trim();
  192.                     } else if (s[0].trim() == 'xp') {
  193.                         compiled.xp[s[1].trim()] = Number(s[2].trim());
  194.                     } else if (s[0].trim() == 'icon') {
  195.                         compiled.icon = s[1].trim();
  196.                     }
  197.                 }
  198.                 break;
  199.             case 'switch':
  200.                 compiled.type = 'switch'
  201.                 compiled.var = ii.args.trim();
  202.                 for (let m in ii.children) {
  203.                     let mm = ii.children[m];
  204.                     let s = mm.split('->');
  205.                     let message = s[0].trim();
  206.                     let label = s[1].trim();
  207.                     compiled[message] = label;
  208.                 }
  209.                 break;
  210.             case 'hasitem':
  211.                 compiled.type = 'hasitem'
  212.                 compiled.item = ii.args.trim();
  213.                 for (let m in ii.children) {
  214.                     let mm = ii.children[m];
  215.                     let s = mm.split('->');
  216.                     let message = s[0].trim();
  217.                     let label = s[1].trim();
  218.                     compiled[message] = label;
  219.                 }
  220.                 break;
  221.             case 'userchoice':
  222.                 compiled.type = 'choice'
  223.                 compiled.message = ii.args.trim();
  224.                 compiled.options = {};
  225.                 for (let m in ii.children) {
  226.                     let mm = ii.children[m];
  227.                     let s = mm.split('->');
  228.                     let message = s[0].trim();
  229.                     let label = s[1].trim();
  230.                     compiled.options[label] = message;
  231.                 }
  232.                 break;
  233.             case 'openstore':
  234.                 compiled.type = 'openstore';
  235.                 compiled.store = ii.args.trim();
  236.                 break;
  237.             case 'teleport':
  238.                 compiled.type = 'teleport';
  239.                 let t = ii.args.split(' ');
  240.                 compiled.layer = t[0].trim();
  241.                 compiled.x = t[1].trim();
  242.                 compiled.y = t[2].trim();
  243.                 break;
  244.             case 'setvar':
  245.                 compiled.type = 'setvar';
  246.                 let s = ii.args.split(' ');
  247.                 compiled.var = s[0].trim();
  248.                 compiled.value = s[1].trim();
  249.                 break;
  250.             case 'givexp':
  251.                 compiled.type = 'givexp';
  252.                 let k = ii.args.split(' ');
  253.                 compiled.skill = k[0].trim();
  254.                 compiled.xp = Number(k[1].trim());
  255.                 break;
  256.             case 'giveitem':
  257.                 compiled.type = 'giveitem';
  258.                 let i = ii.args.split(' ');
  259.                 compiled.item = i[0].trim();
  260.                 if (i[1])
  261.                     compiled.quantity = i[1].trim();
  262.                 break;
  263.             case 'takeitem':
  264.                 compiled.type = 'takeitem';
  265.                 let j = ii.args.split(' ');
  266.                 compiled.item = j[0].trim();
  267.                 if (j[1])
  268.                     compiled.quantity = j[1].trim();
  269.  
  270.                 compiled.success = compiled.next;
  271.                 compiled.failure = false;
  272.                 break;
  273.             case 'nothing-interesting-happens':
  274.                 compiled.type == 'nothing-interesting-happens';
  275.                 break;
  276.             default:
  277.                 console.log("Unknown command: " + ii.command);
  278.         }
  279.  
  280.         conversation[key] = compiled;
  281.     }
  282.     program.conversation = conversation;
  283.  
  284.     return program;
  285. }
  286.  
  287. function compile(file) {
  288.     let f = split(file);
  289.     let c = clean(f);
  290.     let l = lex(c);
  291.     let r = desugar(l)
  292.     let x = convert(r);
  293.     return x;
  294. }
  295.  
  296. function load(path) {
  297.     let file = fs.readFileSync("game-scripts/" + string + ".gs").toString();
  298.     let compiled = compile(file);
  299.     fs.writeFileSync('output/' + string + ".json",
  300.         JSON.stringify(compiled, null, 2));
  301. }
  302.  
  303. exports.compile = compile;
  304.  
  305. //compile(process.argv[2])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement