Commits

catseye  committed fdc66f0

Add `-x` option for expanding symbolic constants.

  • Participants
  • Parent commits a2f2d8d

Comments (0)

Files changed (2)

File README.markdown

 
 `yucca` has been successfully used on:
 
-* The editor for [Apple Befunge][] -- this is a 'session transcript';
-* The original version of [Bubble Escape][] -- this is the textual
-  conversion of the tokenized program.
+* The editor for [Apple Befunge][] -- `APPLE BEFUNGE EDITOR.bas` is a
+  'session transcript' intended to be pasted into an emulator;
+* The original version of [Bubble Escape][] -- `bubble escape.bas` is a
+  text file detokenized from the original tokenized program;
+* [Dungeons of Ekileugor][] -- an original text file, intended to be
+  passed through a C pre-processor and `yucca`, then passed to `petcat`,
+  to create a tokenized VIC-20 BASIC program.
 
 [Apple Befunge]: http://catseye.tc/projects/apple-befunge/
 [Bubble Escape]: http://catseye.tc/projects/bubble-escape/
+[Dungeons of Ekileugor]: https://github.com/catseye/Dungeons-of-Ekileugor
 
 Usage
 -----
 lines, not on immediate mode lines.  Thus, in combination with `-R`, `REM`s
 on immediate mode lines are not removed.  It does not affect `-I` at all.
 
+The `-x` option allows symbol constants to be defined in, and expanded in,
+a yucca source.  A symbolic constant is any alphanumeric token inside
+square bracket.  A symbolic constant is defined by placing it as the first
+thing on a line, followed immediately by an equals sign, followed immediately
+by the value it represents.  Such lines will be stripped, and the values for
+those constants expanded in other lines, when `-x` is given.
+
 The `-t` option runs `yucca` through its internal test suite and exits
 immediately.
 
             self.command = None
             return
         text = text.rstrip('\r\n')
+        self.text = text
         match = re.match(r'^(\s*\d+\s*)(.*?)$', text)
         if match:
             self.line_number = LineNumber(match.group(1))
     >>> len([e for e in b.check_computed_jumps()])
     0
 
+    Symbolic constants defined within the program can be collected
+    and expanded.
+
+    >>> b = BasicProgram('[value]=10\n'
+    ...                  '[xyz]=PRINT\n'
+    ...                  '10 FORI=1TO[value]:[xyz]I:NEXT\n')
+    >>> b.dump()
+    [value]=10
+    [xyz]=PRINT
+    10 FORI=1TO[value]:[xyz]I:NEXT
+    >>> d = b.collect_symbols()
+    >>> sorted(d.keys())
+    ['value', 'xyz']
+    >>> d['value']
+    '10'
+    >>> d['xyz']
+    'PRINT'
+    >>> b.dump()
+    10 FORI=1TO[value]:[xyz]I:NEXT
+    >>> b.expand_symbols(d)
+    >>> b.dump()
+    10 FORI=1TO10:PRINTI:NEXT
+
     """
     def __init__(self, text=None):
         self.lines = []
                 new_lines.append(new_line)
         self.lines = new_lines
 
+    def collect_symbols(self):
+        symbols = {}
+        new_lines = []
+        for line in self.lines:
+            match = re.match(r'^\[(.*?)\]=(.*?)$', line.text)
+            if match:
+                symbols[match.group(1)] = match.group(2)
+            else:
+                new_lines.append(line)
+        self.lines = new_lines
+        return symbols
+
+    def expand_symbols(self, symbols):
+        new_lines = []
+        for line in self.lines:
+            text = line.text
+            text_file_line = line.text_file_line
+            for symbol in symbols:
+                pattern = re.escape('[%s]' % symbol)
+                text = re.sub(pattern, symbols[symbol], text)
+            new_line = BasicLine(text, text_file_line)
+            new_lines.append(new_line)
+        self.lines = new_lines
+
     def dump(self):
         for line in self.lines:
             print line
     parser.add_option("-t", "--test",
                       action="store_true", dest="test", default=False,
                       help="run internal test cases and exit")
+    parser.add_option("-x", "--expand-symbols",
+                      dest="expand_symbols",
+                      action="store_true",
+                      help="expand symbolic names defined in the source file "
+                           "(implies -o)")
 
     (options, args) = parser.parse_args()
 
         p.add_line(line, text_file_line)
         text_file_line += 1
 
+    if options.expand_symbols:
+        options.dump_output = True
+        symbols = p.collect_symbols()
+        p.expand_symbols(symbols)
+
     if options.strip_immediate_mode:
         options.dump_output = True
         p.strip_immediate_mode_commands()