meta_compile 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'meta_compile'
3
- s.version = '0.1.2'
3
+ s.version = '0.1.3'
4
4
  s.summary = "Meta compiler framework for Ruby"
5
5
  s.description = "A meta compilation framework à la Meta-II by Val Schorre, now for Ruby. Bootstrapped from a pure-C implementation of Meta-II but then self-hosting. A main attraction is that the core specification file is very short (~26 lines), and fully self-contained (both syntax and semantics in s single file) which makes it easy for Rubyists to get into the wonderful world of meta compilation. See github homepage for details and examples: https://github.com/robertfeldt/meta_compile"
6
6
  s.author = "Robert Feldt"
@@ -1,59 +1,82 @@
1
1
  .syntax program
2
2
 
3
- outarg = '$' <'@out.print @token'>
4
- | .string <'@out.print ' $>;
3
+ outarg = '$' <'@out.print @match # Print last matched token on output stream'>
4
+ | .string <'@out.print ' $ ' # Print literal string on output stream'>;
5
5
 
6
- out = '<' *outarg '>' <'@out.print "\n"'>;
7
-
8
- exp3 = .id <'compile_' $>
9
-
10
- | .string <'@in.scan /\s*/'>
11
- <'s=' $>
12
- <'l=s.length'>
13
- <'@flag = (@in.peek(l) == s) ? (@token=s; @in.pos += l) : nil'>
14
-
15
- | '.id' <'@in.scan /\s*/; @flag = @token = @in.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
16
-
17
- | '.string' <'@in.scan /\s*/; @flag = @token = @in.scan /\047[^\047]*\047/'>
6
+ out = '<' *outarg '>' <'@out.print "\n" # Print newline on output stream'>;
18
7
 
8
+ exp3 = .id <'compile_' $ ' # Call the method for a rule'>
9
+ | .string <'scan ' $>
10
+ | '.id' <'scan /[A-Za-z]+[A-Za-z0-9_]+/'>
11
+ | '.string' <'scan /\047[^\047]*\047/'>
19
12
  | '(' exp1 ')'
13
+ | '.e' <'@match = true # .e means empty so always matches => set flag.'>
14
+ | '*' <'begin'>
15
+ exp3
16
+ <'end while @match # Loop while there is a match'>
17
+ <'@match = true # Since also zero matches is ok set flag here.'>;
20
18
 
21
- | '.e' <'@flag = true'>
22
-
23
- | '*' <'begin'> exp3 <'end while @flag'> <'@flag = true'>;
24
-
25
- exp2 = ( exp3 <'if @flag'> | out <'if true'> )
26
- *( exp3 <'raise("error at: " + @in.rest.split("\n")[0]) if !@flag'>
27
- | out ) <'end'>;
19
+ exp2 = ( exp3 <'if @match'> | out <'if true'> )
20
+ *( exp3 <'report_error() unless @match'>
21
+ | out )
22
+ <'end'>;
28
23
 
29
24
  exp1 = <'begin'> exp2
30
- *( '|' <'break if @flag'> exp2 )
31
- <'end while false'>;
25
+ *( '|' <'break if @match'> exp2 )
26
+ <'end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise'>;
32
27
 
33
- rule = .id <'def compile_' $> '=' exp1 ';' <'end'>;
28
+ rule = .id <'def compile_' $>
29
+ '=' exp1 ';' <'end'>;
34
30
 
35
31
  program = '.syntax' .id
36
- <'#!/usr/bin/env ruby'>
37
- <'require "strscan"'>
38
-
39
- <'class C_' $>
40
- <' $c = self # so we can access it below if this is run from command line'>
41
- <' def compile(str, out)'>
42
- <' @in, @out = StringScanner.new(str), out'>
43
- <' compile_' $>
32
+ <'#!/usr/bin/env ruby'>
33
+ <'require "strscan"'>
34
+ <'class StringScanner'>
35
+ <' # Add scan for string since base StringScanner lack that...'>
36
+ <' def scan_str(string)'>
37
+ <' return nil unless self.peek(string.length) == string'>
38
+ <' self.pos += string.length # Advance the position in the input string'>
39
+ <' return string'>
44
40
  <' end'>
45
-
46
- *rule '.end'
47
-
48
- <'end # end of class'>
49
-
50
- <'if __FILE__ == $0'>
51
- <' if ARGV.length != 1'>
52
- <' puts("usage: " + $0 + " <input>")'>
53
- <' exit -1'>
54
- <' else'>
55
- <' $c.new.compile(File.read(ARGV[0]), STDOUT)'>
41
+ <' alias :old_scan :scan'>
42
+ <' def scan(strOrRegexp)'>
43
+ <' String === strOrRegexp ? scan_str(strOrRegexp) : old_scan(strOrRegexp)'>
44
+ <' end'>
45
+ <'end'>
46
+ <'class MetaCompiler_' $>
47
+ <' $compiler_class = self # Save class in global var for later reference below'>
48
+ <' def compile_string(string, outFile)'>
49
+ <' @in, @out = StringScanner.new(string), outFile'>
50
+ <' compile_' $ ' # call the main compile method to start compiling'>
51
+ <' end'>
52
+ <' # Scan for a string or regexp and update state based on match. Skips leading whitespace.'>
53
+ <' def scan strOrRegexp'>
54
+ <' @in.scan /\s*/ # Skip whitespace'>
55
+ <' @match = @in.scan strOrRegexp'>
56
+ <' # Since nil is same as false in Ruby we can set the flag to the matched token'>
57
+ <' @last_matched_token = @match if @match # Update last matched only if a token was matched'>
58
+ <' end'>
59
+ <' def report_error'>
60
+ <' pre_lines = @in.string[0, @in.pos].split("\n") # lines of input up to current position'>
61
+ <' post_lines = @in.rest.split("\n") # lines of input after current position'>
62
+ <' message = "PARSE ERROR at line #{pre_lines.length}:\n " + pre_lines.last.inspect + " @ "'>
63
+ <' message += post_lines.first.inspect'>
64
+ <' message += "\n Last matched token: #{@last_matched_token}"'>
65
+ <' raise message'>
66
+ <' end'>
67
+ <' def self.compile_file(inFile, out = nil)'>
68
+ <' outfh = (out == nil ? STDOUT : File.open(out, "w"))'>
69
+ <' self.new.compile_string(File.read(inFile), outfh)'>
70
+ <' outfh.close if out == nil'>
56
71
  <' end'>
72
+ *rule '.end'
73
+ <'end'>
74
+ <'if ARGV.length < 1 || ARGV.length > 2'>
75
+ <' puts "ERROR: wrong number of parameters\n\n"'>
76
+ <' puts "Usage: #{File.basename($0)} <input_file> [output_file]"'>
77
+ <' exit(-1)'>
78
+ <'else'>
79
+ <' $compiler_class.compile_file(ARGV[0], ARGV[1])'>
57
80
  <'end'>;
58
81
 
59
82
  .end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_compile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-26 00:00:00.000000000 Z
12
+ date: 2012-11-29 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'A meta compilation framework à la Meta-II by Val Schorre, now for
15
15
  Ruby. Bootstrapped from a pure-C implementation of Meta-II but then self-hosting.
@@ -27,7 +27,9 @@ files:
27
27
  - README.md
28
28
  - meta_compile.gemspec
29
29
  - bin/meta_compile
30
- - bin/metacomp_re
30
+ - bin/metac_minimal
31
+ - bin/metac_readable
32
+ - bin/metac_regexp
31
33
  - bootstrap/bootstrap.c
32
34
  - bootstrap/meta_ruby_compiler.rb
33
35
  - bootstrap/meta_to_c.meta