first commit

main
sandyx 1 week ago
commit 609dbf39d2

@ -0,0 +1,35 @@
class PrintyBoy
def initialize(stream)
@stream = stream
end
def print_em
@stream.each {|y| puts y}
end
end
class CharStream
include Enumerable
def initialize(str)
puts "str.chars: #{str.chars.class} of #{str.chars.length} chars"
@str = str.chars
end
def each(&block)
@str.each &block
end
def empty?
@str.empty?
end
def length
@str.length
end
end
cs = CharStream.new "cockshitbitchcuntaahhhh"
pb = PrintyBoy.new cs
pb.print_em

@ -0,0 +1,17 @@
@interface NSRuby : NSObject {
int x, y;
}
-(void) sayHello;
+(NSString *) scientificName;
@end
@implementation
-(void) sayHello {
NSLog(@"Hello, World!");
}
+(NSString *) scientificName {
int x = 2 + 5 * 5 / 8;
return @"Homo Sapien!";
}
@end

@ -0,0 +1,329 @@
#!/usr/bin/ruby
def error(msg)
puts "ERROR: #{msg}"
exit 0
end
TokenTypes = {
:blackspace => /\S+/,
:whitespace => /\s+/
}
BasicTokens = {
:open_brace => /{/,
:closed_brace => /}/,
:open_paren => /\(/,
:closed_paren => /\)/,
:open_bracket => /\[/,
:closed_bracket => /\]/,
:comma => /,/,
:dot => /\./,
:double_quote => /\"/,
:single_quote => /\'/,
:plus => /\+/,
:minus => /\-/,
:mult => /\*/,
:div => /\//,
:number => /[0-9]+/,
:colon => /:/,
:semicolon => /;/,
:text => /\S/,
:whitespace => /\s+/,
:doubleq => /\"/,
}
KeywordTokens = {
:intf_decl => /@interface/,
:impl_decl => /@implementation/,
:end => /@end/,
:property => /@property/,
:synthezize => /@synthesize/,
}
class Token
attr_reader :str
attr_accessor :type
attr_accessor :matcher
def initialize(str, hash)
@matcher = Matcher.new(hash)
@str, @type = str, @matcher.match(str)
end
def to_s
"#{@type}: #{@str}"
end
def combine(token)
@str << token.str
end
def match_with(hash)
return self unless Token.new(str, hash).matcher.match(@str)
Token.new(str, hash)
end
end
class Matcher
def initialize(hash)
@hash = hash
end
def match(val)
@hash.each {|k,v|
return k if val =~ v
}
return nil
end
end
class ModeMatcher
def initialize(hash)
@hash = hash
end
def match(val)
@hash.each {|k,v|
return k if val == v
}
return nil
end
end
Modes = {
:intf_decl => :intf_decl,
:impl_decl => :impl_decl,
:end => :end,
}
class VarDecl
def initialize(type, name)
@type = type
@name = name
end
def to_s
"#{@type} #{@name};"
end
end
class VariableDecl
def initialize(stream)
@stream = stream
@modes = [:type, :var, :semicolon]
@mode = :type
end
def new_from(type, vars)
vars.map { |v|
VarDecl.new(type, v)
}
end
def parse
vars = []
until @stream.empty?
token = @stream.shift
@mode = token.type if token.type == :semicolon
case @mode
when :type
type = token
@mode = var
when :var
vars << token
when :semicolon
return [VariableDecl.new_from(type, vars), @stream]
end
end
end
end
class InterfaceDeclHeader
def initialize(name, superclass)
@name, @superclass = name, superclass
@type = :intf_decl_header
@expect = [:intf_struct_member, :intf_property, :intf_method]
@microexpect = {
:open_brace => :intf_struct_member,
:kw_property => :intf_property,
:minus => :intf_method,
:plus => :class_method,
:end => :any,
}
end
def self.new_from(par)
first = par.shift
name = par.shift
par.shift
superclass = par.shift
InterfaceDeclHeader.new(name, superclass)
end
def parse(stream)
token = stream.shift
expected = @microexpect[token]
end
end
class InterfaceStructMember
def initialize(type, name)
@vartype, @name = vartype, name
@type = :intf_struct_member
@expect = [:intf_struct_member, :intf_property, :intf_method]
end
end
class InterfaceMethod
def initialize(return_type, name, args)
@return_type, @name, @args = return_type, name, args
@type = :intf_method
@expect [:intf_method, :end]
end
end
class InterfaceDecl
def initialize(name, superclass)
@name, @superclass = name, superclass
end
def self.new_from(args)
first = args.shift
puts first if first != "@interface"
name = args.shift
args.shift
superclass = args.shift
InterfaceDecl.new(name, superclass)
end
def to_s
"@interface #{@name.str} : #{@superclass.str}"
end
end
class ModeSwitch
def initialize(state)
@state = state
end
def switch(mode)
@state.mode = mode if @state.modes.include? mode
end
end
class SyntaxTape
attr_accessor :processed
attr_accessor :remainder
def initialize(processed, remainder)
@processed, @remainder = processed, remainder
end
def process(parser)
#this should return yet another syntaxtape
parser.parse(@remainder)
end
end
class StateMachineA
attr_accessor :mode
attr_reader :modes
def initialize(stream)
@stream = stream
@modes = [:intf_decl, :impl_decl, :end]
@mode = nil
end
def parse
matcher = ModeSwitch.new(self)
parameters = []
class_type = nil
until @stream.empty?
token = @stream.shift
matcher.switch(token.type)
case @mode
when :intf_decl
class_type = InterfaceDeclHeader
parameters << token unless token.type == :whitespace
when :impl_decl
class_type = ImplDeclHeader
parameters << token unless token.type == :whitespace
when :end
parameters << token
return SyntaxTape.new(class_type.new_from(parameters), @stream)
else
puts "unknown state: #{@mode}"
end
end
end
end
class Lexer
include Enumerable
def keywords
[/@interface/]
end
def initialize(file)
error("expected input file") if file.nil?
@source = File.read(file)
end
def each(&block)
@source.each_char(&block)
end
def blackmap
self.map {|c|
Token.new(c, c=~/\s/ ? :whitespace : :blackspace)
}
end
def matchmap
tokens = self.map {|c|
Token.new(c, BasicTokens)
}
bleed = 0
tokens.filter_map.with_index {|token, idx|
#skips iterations that would result in repeated segments of string
if bleed != 0
bleed -= 1
next
end
next token unless token.type == :text
#combine text into single token
while tokens[idx += 1].type == :text
token.combine(tokens[idx])
bleed += 1
next
end
next token
}.map { |token|
token.match_with(KeywordTokens)
}
end
def each_token
token = ""
end
end
source = Lexer.new(ARGV[0])
a = StateMachineA.new source.matchmap
tape = a.parse
puts tape.processed

@ -0,0 +1,125 @@
intf_decl: @interface
whitespace:
text: NSRuby
whitespace:
colon: :
whitespace:
text: NSObject
whitespace:
open_brace: {
whitespace:
whitespace:
whitespace:
whitespace:
text: int
whitespace:
text: x
comma: ,
whitespace:
text: y
semicolon: ;
whitespace:
closed_brace: }
whitespace:
minus: -
open_paren: (
text: void
closed_paren: )
whitespace:
text: sayHello
semicolon: ;
whitespace:
plus: +
open_paren: (
text: NSString
whitespace:
mult: *
closed_paren: )
whitespace:
text: scientificName
semicolon: ;
whitespace:
end: @end
whitespace:
whitespace:
impl_decl: @implementation
whitespace:
minus: -
open_paren: (
text: void
closed_paren: )
whitespace:
text: sayHello
whitespace:
open_brace: {
whitespace:
whitespace:
whitespace:
whitespace:
text: NSLog
open_paren: (
text: @
double_quote: "
text: Hello
comma: ,
whitespace:
text: World!
double_quote: "
closed_paren: )
semicolon: ;
whitespace:
closed_brace: }
whitespace:
whitespace:
plus: +
open_paren: (
text: NSString
whitespace:
mult: *
closed_paren: )
whitespace:
text: scientificName
whitespace:
open_brace: {
whitespace:
whitespace:
whitespace:
whitespace:
text: int
whitespace:
text: x
whitespace:
text: =
whitespace:
number: 2
whitespace:
plus: +
whitespace:
number: 5
whitespace:
mult: *
whitespace:
number: 5
whitespace:
div: /
whitespace:
number: 8
semicolon: ;
whitespace:
whitespace:
whitespace:
whitespace:
text: return
whitespace:
text: @
double_quote: "
text: Homo
whitespace:
text: Sapien!
double_quote: "
semicolon: ;
whitespace:
closed_brace: }
whitespace:
end: @end
whitespace:

@ -0,0 +1,19 @@
class Parser
def initialize(pattern)
@pattern = pattern
end
def parse(stream)
a = stream.chars
b = a.shift
if b =~ @pattern
return [b, parse(a.join)]
end
end
end
parser = ->(str) {
parser.call [str[1].flatten.chars.first, str[1].flatten.chars.drop(1)]
}
p parser.call ["", "Hello, World"]
Loading…
Cancel
Save