mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			128 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| <%
 | |
| 
 | |
| class Env {
 | |
|     def init {
 | |
|         @memory = [];
 | |
|         @ptr = 0;
 | |
|     }
 | |
| 
 | |
|     def ptr       { @ptr }
 | |
|     def ptr=(ptr) { @ptr = ptr }
 | |
| 
 | |
|     def current_value         { @memory[@ptr] || 0 }
 | |
|     def current_value=(value) { @memory[@ptr] = value }
 | |
| }
 | |
| 
 | |
| class AST {
 | |
|     class Next {
 | |
|         def eval(env) {
 | |
|             env.ptr++;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Prev {
 | |
|         def eval(env) {
 | |
|             env.ptr--;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Inc {
 | |
|         def eval(env) {
 | |
|             env.current_value++;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Dec {
 | |
|         def eval(env) {
 | |
|             env.current_value--;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Output {
 | |
|         def eval(env) {
 | |
|             print(env.current_value.char);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Input {
 | |
|         def eval(env) {
 | |
|             ...
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Sequence {
 | |
|         def init(nodes) {
 | |
|             @nodes = nodes;
 | |
|         }
 | |
| 
 | |
|         def eval(env) {
 | |
|             for node in @nodes {
 | |
|                 node.eval(env);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class Loop {
 | |
|         def init(seq) {
 | |
|             @seq = seq;
 | |
|         }
 | |
| 
 | |
|         def eval(env) {
 | |
|             while env.current_value != 0 {
 | |
|                 @seq.eval(env);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| class Parser {
 | |
|     def init(str) {
 | |
|         @chars = str.split("");
 | |
|     }
 | |
| 
 | |
|     def parse {
 | |
|         @stack = [[]];
 | |
|         for char in @chars {
 | |
|             _parse_char(char);
 | |
|         }
 | |
|         if @stack.length != 1 {
 | |
|             throw SyntaxError.new("unexpected end of input");
 | |
|         }
 | |
|         AST::Sequence.new(@stack.last);
 | |
|     }
 | |
| 
 | |
|     def _parse_char(char) {
 | |
|         switch char {
 | |
|             ">" { _add(AST::Next.new); }
 | |
|             "<" { _add(AST::Prev.new); }
 | |
|             "+" { _add(AST::Inc.new); }
 | |
|             "-" { _add(AST::Dec.new); }
 | |
|             "." { _add(AST::Output.new); }
 | |
|             "," { _add(AST::Input.new); }
 | |
|             "[" { _open_loop(); }
 | |
|             "]" { _close_loop(); }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     def _add(node) {
 | |
|         @stack.last.push(node);
 | |
|     }
 | |
| 
 | |
|     def _open_loop {
 | |
|         @stack.push([]);
 | |
|     }
 | |
| 
 | |
|     def _close_loop {
 | |
|         if @stack.length == 1 {
 | |
|             throw SyntaxError.new("unexpected ']'");
 | |
|         }
 | |
| 
 | |
|         nodes = @stack.pop;
 | |
|         _add(AST::Loop.new(AST::Sequence.new(nodes)));
 | |
|     }
 | |
| }
 | |
| 
 | |
| src = File.read(ARGV.first);
 | |
| ast = Parser.new(src).parse;
 | |
| ast.eval(Env.new);
 |