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.
- data/README.md +4 -4
- data/Rakefile +98 -50
- data/bin/meta_compile +295 -195
- data/bin/metac_minimal +231 -0
- data/bin/metac_readable +331 -0
- data/bin/{metacomp_re → metac_regexp} +0 -0
- data/meta_compile.gemspec +1 -1
- data/syntaxes/meta_to_ruby.meta +66 -43
- metadata +5 -3
File without changes
|
data/meta_compile.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'meta_compile'
|
3
|
-
s.version = '0.1.
|
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"
|
data/syntaxes/meta_to_ruby.meta
CHANGED
@@ -1,59 +1,82 @@
|
|
1
1
|
.syntax program
|
2
2
|
|
3
|
-
outarg = '$'
|
4
|
-
| .string
|
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 '>'
|
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
|
-
|
22
|
-
|
23
|
-
|
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 @
|
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
|
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
|
-
<'
|
40
|
-
<'
|
41
|
-
<'
|
42
|
-
<'
|
43
|
-
<'
|
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
|
-
|
47
|
-
|
48
|
-
<'end
|
49
|
-
|
50
|
-
<'
|
51
|
-
<'
|
52
|
-
<'
|
53
|
-
<'
|
54
|
-
<'
|
55
|
-
<'
|
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.
|
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-
|
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/
|
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
|