Thanks Long, this was a great meta-II to build on.
I had to fix a bug in support.h (see diff at bottom) but then used your
code to bootstrap the following, self-contained (i.e. contains its own
support code (a bit hackish but good for learning)) Ruby version in 28
non-empty lines:
.syntax RMetaII
arg = '$' <'@o.print @t'>
| .string <'@o.print ' $>;
output = '<' *arg '>' <'@o.print "\n"'>;
exp3 = .id <'compile_' $>
| .string <'@i.scan /\s*/; s=' $>
<'@f = (@i.peek(s.length) == s) ? (@t=s; @i.pos += s.length) : nil'>
| '.id' <'@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
| '.string' <'@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'>
| '(' exp1 ')'
| '.e' <'@f = true'>
| '*' <'begin'> exp3 <'end while @f'> <'@f = true'>;
exp2 = ( exp3 <'if @f'> | output <'if true'> )
*( exp3 <'raise("error at: " + @i.rest.split("\n")[0]) if !@f'>
| output ) <'end'>;
exp1 = <'begin'> exp2
*( '|' <'break if @f'> exp2 )
<'end while false'>;
stat = .id <'def compile_' $> '=' exp1 ';' <'end'>;
program = '.syntax' .id
<'#!/usr/bin/env ruby'> <'require "strscan"'>
<'class ' $> <'def compile(str, out)'>
<'@i, @o = StringScanner.new(str), out'>
<'compile_program'> <'end'>
*stat '.end' <'end'>
<'puts "Usage: meta_compiler <input> <output>" unless ARGV.length == 2'>
<'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]),
f)}'>;
.end
Very little error handling and I'm sure there are bugs but it's a start...
:)
The reverse order of the rules are really just an artefact of basing it on
Long's version. Ruby does not require a certain order so can be reformatted
to be top-down.
Found at: https://github.com/robertfeldt/meta_compile
Cheers,
Robert Feldt
Diff to Long's support.h :
103c103
< if (('A' <= source[pos] && source[pos] <= 'A') ||
---
> if (('A' <= source[pos] && source[pos] <= 'Z') ||
112c112
< while (('A' <= source[pos] && source[pos] <= 'A') ||
---
> while (('A' <= source[pos] && source[pos] <= 'Z') ||
_______________________________________________
fonc mailing list
[email protected]
http://vpri.org/mailman/listinfo/fonc