35 Commits

Author SHA1 Message Date
56a02bd6ea use ast that produces ruby output 2016-12-08 19:34:59 +02:00
f5b54c5fca add cli for soml->s-exp 2016-12-08 18:54:27 +02:00
5c03db709f fix if false logic 2016-03-07 11:51:58 +02:00
324c9c2eae better handling of statement lists 2016-03-07 11:32:28 +02:00
c9d25fcf81 easier constructor 2016-03-07 11:32:09 +02:00
f51ed376c4 add missing as types 2016-03-06 14:07:25 +02:00
4a9b492dd9 move to typed structure
on the way to removing the language, the at needs to be replaced with a
typed structure.
2016-03-06 09:40:41 +02:00
9ca03ef115 hopefully fix travis issue 2015-11-30 20:07:11 +02:00
d38a9c626f renamed to soml-parser 2015-11-30 19:55:48 +02:00
6ae4b624b0 leaving the name for field defs
so we can reuse that expression
so we can highlight it in the debugger
2015-11-02 20:10:05 +02:00
335a6b1e37 update parsley 2015-11-02 20:09:13 +02:00
6710567af9 fix test after syntax changes 2015-10-19 15:21:23 +03:00
3061ddfed9 same syntax change for while_xxx
xxx can be any string for the parser
the language will restrict if somewhat later
2015-10-19 15:21:11 +03:00
7cc7ab5c18 adding condition to if statement
new syntax is if_true( . .. . )
where any string is allowed in case of true
2015-10-19 15:10:38 +03:00
72ed05254e move control into statements 2015-10-19 14:57:03 +03:00
ab0a94bd51 change type to class name
although int is still allowed for integers (gets replaced though)
2015-10-14 15:48:53 +03:00
1b2802ecf4 use bundlers rake tasks 2015-10-10 21:52:14 +03:00
6bd5e9b5ee version bump for lots of incompatible changes 2015-10-09 17:34:10 +03:00
be07cd615a transform changes for what was basically a rewrite 2015-10-09 17:32:55 +03:00
e9a7b1f6da fix root, much tighter now 2015-10-09 17:32:34 +03:00
3651856fc5 fix class defs 2015-10-09 17:32:05 +03:00
60746383ee expressions are now statements 2015-10-09 17:31:08 +03:00
b424306156 fix array and hash constants, now seperated out 2015-10-09 17:29:24 +03:00
dff0e8fab4 fix function definition 2015-10-09 17:28:47 +03:00
48a6dfabff fix while and if statements 2015-10-09 17:28:13 +03:00
7f2f64c713 fix call site and now seperated assignment (was bunged as operator) 2015-10-09 17:27:22 +03:00
c9942ec516 test field access seperately (was mixed in) 2015-10-09 17:25:43 +03:00
af8febe456 fix operators, only binary 2015-10-09 17:25:09 +03:00
ba7ecbfa7b fix basic types 2015-10-09 17:24:23 +03:00
97cf5e5bea retrying with the root of the directory
comes from finally tightning the root and not allowing random
expression code ala ruby
2015-10-09 17:23:43 +03:00
f7dcf2a2ff renameing to match expressions 2015-10-09 17:21:15 +03:00
85adfa7107 may call with r_value 2015-10-09 12:47:03 +03:00
308c0efc05 rename value_expression to r_value 2015-10-09 12:42:50 +03:00
77cb8ce90a restrict the root, but expand for testing 2015-10-09 12:39:31 +03:00
486e24514b there goes the module
it was ruby after all
should be reborn as twins: namespace and aspect
2015-10-08 22:57:39 +03:00
157 changed files with 1212 additions and 1142 deletions

View File

@ -2,16 +2,14 @@ source "http://rubygems.org"
gem "rake" gem "rake"
gem "salama-reader" , :path => "." gem "soml-parser" , :path => "."
# use this for debugging, the printout is better (cut/paste) # use this for debugging, the printout is better (cut/paste)
gem "ast" , :github => "dancinglightning/ast" , :branch => :new_inspect gem "ast" , :github => "dancinglightning/ast"
#gem "ast"
# Add dependencies to develop your gem here. # Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc. # Include everything needed to run rake, tests, features, etc.
group :development do group :development do
gem "codeclimate-test-reporter", require: nil gem "codeclimate-test-reporter", require: nil
gem "minitest" gem "minitest"
gem "rubygems-tasks"
end end

View File

@ -1,16 +1,15 @@
GIT GIT
remote: git://github.com/dancinglightning/ast.git remote: git://github.com/dancinglightning/ast.git
revision: a9bc29377a94d2194e92596aceb9be7c7db4c8f8 revision: 3814fb102af82a30bf334005ebe17332744f9dad
branch: new_inspect
specs: specs:
ast (2.1.0) ast (2.1.0)
PATH PATH
remote: . remote: .
specs: specs:
salama-reader (0.3.0) soml-parser (0.5.0)
ast (~> 2.1.0) ast (~> 2.1.0)
parslet (~> 1.7.0) parslet (~> 1.7.1)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
@ -24,7 +23,6 @@ GEM
parslet (1.7.1) parslet (1.7.1)
blankslate (>= 2.0, <= 4.0) blankslate (>= 2.0, <= 4.0)
rake (10.4.2) rake (10.4.2)
rubygems-tasks (0.2.4)
simplecov (0.9.2) simplecov (0.9.2)
docile (~> 1.1.0) docile (~> 1.1.0)
multi_json (~> 1.0) multi_json (~> 1.0)
@ -39,8 +37,7 @@ DEPENDENCIES
codeclimate-test-reporter codeclimate-test-reporter
minitest minitest
rake rake
rubygems-tasks soml-parser!
salama-reader!
BUNDLED WITH BUNDLED WITH
1.10.6 1.13.5

View File

@ -1,17 +1,17 @@
[![Build Status](https://travis-ci.org/salama/salama-reader.svg?branch=master)](https://travis-ci.org/salama/salama-reader) [![Build Status](https://travis-ci.org/salama/soml-parser.svg?branch=master)](https://travis-ci.org/salama/soml-parser)
[![Gem Version](https://badge.fury.io/rb/salama-reader.svg)](http://badge.fury.io/rb/salama-reader) [![Gem Version](https://badge.fury.io/rb/soml-parser.svg)](http://badge.fury.io/rb/soml-parser)
[![Test Coverage](https://codeclimate.com/github/salama/salama-reader/badges/coverage.svg)](https://codeclimate.com/github/salama/salama-reader) [![Test Coverage](https://codeclimate.com/github/salama/soml-parser/badges/coverage.svg)](https://codeclimate.com/github/salama/soml-parser)
## Salama Reader ## Soml Parser
The parser part of salama is now a standalone gem. It parses Phisol using Parslet and no other dependencies. The parser part of soml is a standalone gem to allow independent development.
It parses Soml using Parslet and no other dependencies.
Also it is very educational, as it is very readable code, and not too much of it. Also it is very educational, as it is very readable code, and not too much of it.
## Phisol Phi System Object Language ## Soml: Salama Object Machine Language
Phisol is just forming after realizing the (unfortunate) need for an oo system language. Soml is Still forming after realizing the need for an oo system language.
(I really didn't want to do yet another language)
The need comes from these three things: The need comes from these three things:
@ -20,26 +20,18 @@ Phisol is just forming after realizing the (unfortunate) need for an oo system l
- Upward compatible memory and calling conventions are needed - Upward compatible memory and calling conventions are needed
- Multiple return addresses are needed - Multiple return addresses are needed
From these comes the name: A phi node is the opposite of what you may think of as an if. Actually an In Soml a function call is not necessarily a part of linear code. A call may return to several
if statement is always a branch (the if part) and a rejoining of the two branches (the phi part).
In Phisol a function call is not necessarily a part of linear code. A call may return to several
addresses, making the call more like an if statement. addresses, making the call more like an if statement.
### Syntax ### Syntax
Syntax (and semantics) of Phisol are just forming, but some things are clear: Syntax and semantics of Soml are described on the [salama site](http://salama-vm.org/soml/soml.html)
- statically typed (in the beginning with just two types) meaning all variable declarations, - statically typed so all variable declarations, functions and arguments are typed.
functions and arguments shall be typed.
- objects but without data hiding - objects but without data hiding
- probably nil objects
- static blocks (a bit ala crystal) - static blocks (a bit ala crystal)
- call syntax as already discussed, ie message based - call syntax as already discussed, ie message based
- no semicolns and stuff, but not ruby either
Some things we shall leave behind from the ruby approach are a lot of sugar, like missing brackets,
random code everywhere, expressions galore . . .
### Parser ### Parser
@ -52,10 +44,10 @@ Most names are quite self explanatory, but here is a list:
- call_site is a function call. May be qualified, but currently must still have braches - call_site is a function call. May be qualified, but currently must still have braches
- compound types are hash and array definitions. Hashes still need curlies - compound types are hash and array definitions. Hashes still need curlies
- control is if statement which still must have an else - control is if statement which still must have an else
- expression is a helper for all code allowed in a function - statement is a helper for all code allowed in a function
- function definition must have braces too - function definition must have braces too
- keywords is just a list of them - keywords is just a list of them
- operator expression are binary operators (see also below). There's a surprising amount - operator statement are binary operators (see also below). There's a surprising amount
- return statement are straightforward - return statement are straightforward
- while still needs a do, though i think in ruby a newline is sufficient - while still needs a do, though i think in ruby a newline is sufficient

View File

@ -11,9 +11,7 @@ rescue Bundler::BundlerError => e
end end
require 'rake' require 'rake'
require "bundler/gem_tasks"
require 'rubygems/tasks'
Gem::Tasks.new
require 'rake/testtask' require 'rake/testtask'
Rake::TestTask.new(:test) do |test| Rake::TestTask.new(:test) do |test|
@ -29,7 +27,7 @@ Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : "" version = File.exist?('VERSION') ? File.read('VERSION') : ""
rdoc.rdoc_dir = 'rdoc' rdoc.rdoc_dir = 'rdoc'
rdoc.title = "salama-reader #{version}" rdoc.title = "soml-parser #{version}"
rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb') rdoc.rdoc_files.include('lib/**/*.rb')
end end

View File

@ -36,27 +36,29 @@ module Parser
rule(:digit) { match('[0-9]') } rule(:digit) { match('[0-9]') }
rule(:exponent) { (str('e')| str('E')) } rule(:exponent) { (str('e')| str('E')) }
rule(:type) { (str("int") | str("ref")).as(:type) >> space } rule(:type) { (str("int") | class_name).as(:type) >> space }
# identifier must start with lower case # identifier must start with lower case
# TODO rule forbit names like if_true, because it starts with a keyword. a little looser please! # TODO rule forbit names like true_statements, because it starts with a keyword. a little looser please!
rule(:name) { (keyword|type).absent? >> (match['a-z_'] >> match['a-zA-Z0-9_'].repeat).as(:name) >> space? } rule(:name) { (keyword|type).absent? >> (match['a-z_'] >> match['a-zA-Z0-9_'].repeat).as(:name) >> space? }
# fields have type # fields have type
rule(:field) { type >> name >> (assign >> value_expression.as(:value) ).maybe}
rule(:class_field) { keyword_field >> field }
# and class/module names must start with capital # and class/module names must start with capital
rule(:module_name) { keyword.absent? >> (match['A-Z'] >> match['a-zA-Z0-9_'].repeat).as(:module_name) >> space? } rule(:class_name) { keyword.absent? >> (match['A-Z'] >> match['a-zA-Z0-9_'].repeat).as(:class_name) >> space? }
rule(:escape) { str('\\') >> any.as(:esc) } rule(:escape) { str('\\') >> any.as(:esc) }
rule(:string) { quote >> ( rule(:string) { quote >> (
escape | escape |
nonquote.as(:char) nonquote.as(:char)
).repeat(1).as(:string) >> quote } ).repeat(1).as(:string) >> quote >> space? }
rule(:integer) { sign.maybe >> digit.repeat(1).as(:integer) >> space? } rule(:integer) { sign.maybe >> digit.repeat(1).as(:integer) >> space? }
rule(:float) { integer >> dot >> integer >> rule(:float) { integer >> dot >> integer >>
(exponent >> sign.maybe >> digit.repeat(1,3)).maybe >> space?} (exponent >> sign.maybe >> digit.repeat(1,3)).maybe >> space?}
rule(:basic_type){ integer | name | string | float | field | module_name |
keyword_true | keyword_false | keyword_nil } rule(:field_access) { name.as(:receiver) >> str(".") >> name.as(:field) }
rule(:basic_type){ integer | name | string | float | class_name |
((keyword_true | keyword_false | keyword_nil) >> space? ) }
end end
end end

View File

@ -2,17 +2,22 @@ module Parser
module CallSite module CallSite
include Parslet include Parslet
rule(:r_value) { operator_value | call_site | field_access | basic_type }
rule(:assign) { str('=') >> space?}
rule(:assignment){ (field_access|name).as(:l_value) >> assign.as(:assign) >> r_value.as(:r_value) }
rule(:field_def) { type >> name >> (assign >> r_value.as(:value) ).maybe}
rule(:argument_list) { rule(:argument_list) {
left_parenthesis >> left_parenthesis >>
( (basic_type.as(:argument) >> ( (basic_type.as(:argument) >>
(comma >> basic_type.as(:argument)).repeat(0)).repeat(0,1)).as(:argument_list) >> (comma >> r_value.as(:argument)).repeat(0)).repeat(0,1)).as(:argument_list) >>
right_parenthesis right_parenthesis
} }
rule(:call_site) { (basic_type.as(:receiver) >> str(".")).maybe >> #possibly qualified rule(:call_site) { (basic_type.as(:receiver) >> str(".")).maybe >> #possibly qualified
name.as(:call_site) >> argument_list >> comment.maybe} name.as(:call_site) >> argument_list >> comment.maybe}
rule(:field_access) { name.as(:receiver) >> str(".") >> name.as(:field) }
end end
end end

View File

@ -0,0 +1,16 @@
module Parser
module ModuleDef
include Parslet
rule(:class_field) { keyword_field >> field_def }
rule(:class_body) {
function_definition | class_field
}
rule(:class_definition) do
keyword_class >> class_name >> (str("<") >> space >> class_name).maybe.as(:derived_name) >>
( (keyword_end.absent? >> class_body).repeat()).as(:class_statements) >> keyword_end
end
end
end

View File

@ -5,12 +5,12 @@ module Parser
rule(:array_constant) do rule(:array_constant) do
left_bracket >> left_bracket >>
( ((operator_expression|value_expression).as(:array_element) >> space? >> ( (r_value.as(:array_element) >> space? >>
(comma >> space? >> (operator_expression|value_expression).as(:array_element)).repeat(0)).repeat(0,1)).as(:array_constant) >> (comma >> space? >> r_value.as(:array_element)).repeat(0)).repeat(0,1)).as(:array_constant) >>
space? >> right_bracket space? >> right_bracket
end end
rule(:hash_pair) { basic_type.as(:hash_key) >> association >> (operator_expression|value_expression).as(:hash_value) } rule(:hash_pair) { basic_type.as(:hash_key) >> association >> r_value.as(:hash_value) }
rule(:hash_constant) { left_brace >> ((hash_pair.as(:hash_pair) >> rule(:hash_constant) { left_brace >> ((hash_pair.as(:hash_pair) >>
(comma >> space? >> hash_pair.as(:hash_pair)).repeat(0)).repeat(0,1)).as(:hash_constant)>> (comma >> space? >> hash_pair.as(:hash_pair)).repeat(0)).repeat(0,1)).as(:hash_constant)>>
space? >> right_brace } space? >> right_brace }

View File

@ -1,24 +0,0 @@
module Parser
module Control
include Parslet
rule(:conditional) do
keyword_if >>
left_parenthesis >> (operator_expression|value_expression).as(:conditional) >> right_parenthesis >>
expressions_else.as(:if_true) >> expressions_end.as(:if_false)
end
rule(:small_conditional) do
keyword_if >>
left_parenthesis >> (operator_expression|value_expression).as(:conditional) >> right_parenthesis >>
expressions_end.as(:if_true)
end
rule(:while_do) do
keyword_while >> left_parenthesis >> (operator_expression|value_expression).as(:while_cond) >>
right_parenthesis >> expressions_end.as(:body)
end
rule(:simple_return) do
keyword_return >> (operator_expression|value_expression).as(:return_expression)
end
end
end

View File

@ -1,20 +0,0 @@
module Parser
module Expression
include Parslet
rule(:value_expression) { call_site | field_access |basic_type }
rule(:expression) { (simple_return | while_do | small_conditional | conditional |
operator_expression | call_site | class_field | field |
hash_constant | array_constant) }
def delimited_expressions( delimit )
( (delimit.absent? >> expression).repeat(1)).as(:expressions) >> delimit
end
rule(:expressions_do) { delimited_expressions(keyword_do) }
rule(:expressions_else) { delimited_expressions(keyword_else) }
rule(:expressions_end) { delimited_expressions(keyword_end) }
end
end

View File

@ -3,13 +3,13 @@ module Parser
include Parslet include Parslet
rule(:function_definition) { rule(:function_definition) {
type >> ((module_name|name).as(:receiver) >> str(".")).maybe >> #possibly qualified type >> ((class_name|name).as(:receiver) >> str(".")).maybe >> #possibly qualified
name.as(:function_name) >> left_parenthesis >> name.as(:function_name) >> left_parenthesis >>
parameter_list.maybe >> right_parenthesis >> expressions_end >> space? parameter_list.maybe >> right_parenthesis >> statements_end >> space?
} }
rule(:parameter_list) { rule(:parameter_list) {
((field.as(:parameter) >> (comma >> field.as(:parameter)).repeat(0)).repeat(0,1)).as(:parameter_list) ((field_def.as(:parameter) >> (comma >> field_def.as(:parameter)).repeat(0)).repeat(0,1)).as(:parameter_list)
} }
end end

View File

@ -4,25 +4,18 @@ module Parser
rule(:keyword_begin) { str('begin').as(:begin) >> space?} rule(:keyword_begin) { str('begin').as(:begin) >> space?}
rule(:keyword_class) { str('class') >> space? } rule(:keyword_class) { str('class') >> space? }
rule(:keyword_do) { str('do').as(:do) >> space?}
rule(:keyword_else) { str('else').as(:else) >> space? } rule(:keyword_else) { str('else').as(:else) >> space? }
rule(:keyword_end) { str('end').as(:end) >> space? } rule(:keyword_end) { str('end').as(:end) >> space? }
rule(:keyword_false) { str('false').as(:false) } rule(:keyword_false) { str('false').as(:false) }
rule(:keyword_field) { str('field').as(:field) >> space? } rule(:keyword_field) { str('field').as(:field) >> space? }
rule(:keyword_if) { str('if').as(:if) }
rule(:keyword_rescue) { str('rescue').as(:rescue) >> space?}
rule(:keyword_return) { str('return').as(:return) >> space?} rule(:keyword_return) { str('return').as(:return) >> space?}
rule(:keyword_true) { str('true').as(:true) } rule(:keyword_true) { str('true').as(:true) }
rule(:keyword_module) { str('module') >> space? }
rule(:keyword_nil) { str('nil').as(:nil) } rule(:keyword_nil) { str('nil').as(:nil) }
rule(:keyword_unless) { str('unless').as(:unless) >> space?}
rule(:keyword_until) { str('until').as(:until) >> space?}
rule(:keyword_while) { str('while').as(:while) }
# this rule is just to make sure identifiers can't be keywords. Kind of duplication here, but we need the # this rule is just to make sure identifiers can't be keywords. Kind of duplication here, but we need the
# space in above rules, so just make sure to add any here too. # space in above rules, so just make sure to add any here too.
rule(:keyword){ str('begin') | str('def') | str('do') | str('else') | str('end') | rule(:keyword){ str('if_') | str('else') | str('end') | str('while_') |
str('false')| str('if')| str('rescue')| str('true')| str('nil') | str('false') | str('true')| str('nil') | str("class") |
str('unless')| str('until')| str('while') | str('field')} str('return')| str('int')| str('field')}
end end
end end

View File

@ -1,15 +0,0 @@
module Parser
module ModuleDef
include Parslet
rule(:module_definition) do
keyword_module >> module_name >>
( (keyword_end.absent? >> root_body).repeat()).as(:module_expressions) >> keyword_end
end
rule(:class_definition) do
keyword_class >> module_name >> (smaller >> module_name).maybe.as(:derived_name) >>
( (keyword_end.absent? >> root_body).repeat()).as(:class_expressions) >> keyword_end
end
end
end

View File

@ -1,48 +1,15 @@
module Parser module Parser
module Operators module Operators
include Parslet include Parslet
rule(:exponent) { str('**') >> space?}
rule(:multiply) { match['*/%'] >> space? }
rule(:plus) { match['+-'] >> space? }
rule(:shift) { str(">>") | str("<<") >> space?}
rule(:bit_and) { str('&') >> space?}
rule(:bit_or) { str('|') >> space?}
rule(:greater_equal) { str('>=') >> space?}
rule(:less_or_equal) { str('<=') >> space?}
rule(:larger) { str('>') >> space?}
rule(:smaller) { str('<') >> space?}
rule(:identity) { str('===') >> space?}
rule(:equal) { str('==') >> space?}
rule(:not_equal) { str('!=') >> space?}
rule(:boolean_and) { str('&&') | str("and") >> space?}
rule(:boolean_or) { str('||') | str("or") >> space?}
rule(:assign) { str('=') >> space?}
rule(:op_assign) { str('+=')|str('-=')|str('*=')|str('/=')|str('%=') >> space?}
rule(:eclipse) { str('..') |str("...") >> space?}
rule(:assign) { str('=') >> space?}
#infix doing the heavy lifting here, rule(:operator_sym) {
# is defined as an expressions and array of [atoms,priority,binding] triples str('**') | str('*') | str('/') | str('/') | str('%') |
rule(:operator_expression) do infix_expression(value_expression, str('+') | str('-') | str('<<')| str('>>') |
[exponent, 120, :left] , str('|') | str('&') |
[multiply, 120, :left] , str('>=') | str('<=') | str('>') | str('<') |
[plus, 110, :left], str('==') | str('!=') }
[shift, 100, :left],
[bit_and, 90, :left], rule(:operator_value) { (field_access|basic_type).as(:left) >>
[bit_or, 90, :right], operator_sym.as(:operator) >> space? >> (field_access|basic_type).as(:right) }
[greater_equal, 80, :left],
[less_or_equal, 80, :left],
[larger, 80, :left],
[smaller, 80, :left],
[identity, 70, :right],
[equal, 70, :right],
[not_equal, 70, :right],
[boolean_and, 60, :left],
[boolean_or, 50, :right],
[eclipse, 40, :right],
[keyword_rescue, 30, :right],
[assign, 20, :right],
[op_assign, 20, :right] ) >> space?
end
end end
end end

View File

@ -2,11 +2,10 @@ require_relative "basic_types"
require_relative "compound_types" require_relative "compound_types"
require_relative "tokens" require_relative "tokens"
require_relative "keywords" require_relative "keywords"
require_relative "control" require_relative "statement"
require_relative "expression"
require_relative "call_site" require_relative "call_site"
require_relative "function_definition" require_relative "function_definition"
require_relative "module_definition" require_relative "class_definition"
require_relative "operators" require_relative "operators"
module Parser module Parser
@ -24,15 +23,13 @@ module Parser
include CompoundTypes include CompoundTypes
include Tokens include Tokens
include Keywords include Keywords
include Control include Statement
include Expression
include CallSite include CallSite
include FunctionDefinition include FunctionDefinition
include Operators include Operators
include ModuleDef include ModuleDef
rule(:root_body) {(module_definition | class_definition | function_definition | rule(:root_body) {( class_definition | function_definition )}
expression | operator_expression | call_site )} rule(:root) { root_body.repeat.as(:statement_list) }
rule(:root) { root_body.repeat.as(:expression_list) }
end end
end end

46
lib/parser/statement.rb Normal file
View File

@ -0,0 +1,46 @@
module Parser
module Statement
include Parslet
rule( :keyword_while) do
str("while_") >> alpha.repeat.as(:condition) >> space
end
rule(:while_statement) do
keyword_while >> left_parenthesis >> r_value.as(:conditional) >>
right_parenthesis >> statements_end.as(:body)
end
rule( :keyword_if) do
str("if_") >> alpha.repeat.as(:condition) >> space
end
rule(:if_statement) do
keyword_if >>
left_parenthesis >> r_value.as(:conditional) >> right_parenthesis >>
statements_else.as(:true_statements) >> statements_end.as(:false_statements)
end
rule(:small_conditional) do
keyword_if >>
left_parenthesis >> r_value.as(:conditional) >> right_parenthesis >>
statements_end.as(:true_statements)
end
rule(:return_statement) do
keyword_return >> r_value.as(:return_statement)
end
rule(:statement) { (return_statement | while_statement | small_conditional | if_statement |
assignment | class_field | field_def | call_site |
hash_constant | array_constant) }
def delimited_statements( delimit )
( (delimit.absent? >> statement).repeat(1)).as(:statements) >> delimit
end
rule(:statements_do) { delimited_statements(keyword_do) }
rule(:statements_else) { delimited_statements(keyword_else) }
rule(:statements_end) { delimited_statements(keyword_end) }
end
end

View File

@ -1,7 +1,17 @@
#include is private in 1.9, who'd have known without travis #include is private in 1.9, who'd have known without travis
Parslet::Context.send :include , AST::Sexp Parslet::Context.send :include , AST::Sexp
Parslet::Context.class_eval do
def type_sym t
if( t.is_a? AST::Node )
t = t.children.first
else
t = t.to_sym
t = :Integer if t == :int
end
t
end
end
module Parser module Parser
class Transform < Parslet::Transform class Transform < Parslet::Transform
@ -15,16 +25,22 @@ module Parser
rule(:integer => simple(:value)) { s(:int ,value.to_i) } rule(:integer => simple(:value)) { s(:int ,value.to_i) }
rule(:name => simple(:name)) { s(:name , name.to_sym) } rule(:name => simple(:name)) { s(:name , name.to_sym) }
# local variables # local variables
rule(:type => simple(:type), :name => simple(:name)) { s(:field_def , type.to_sym , name.to_sym) } rule(:type => simple(:type), :name => simple(:name)) {
s(:field_def , type_sym(type) , s(:name , name.to_sym)) }
rule(:type => simple(:type), :name => simple(:name) , :value => simple(:value)) { rule(:type => simple(:type), :name => simple(:name) , :value => simple(:value)) {
s(:field_def , type.to_sym , name.to_sym , value ) } s(:field_def , type_sym(type) , s(:name , name.to_sym) , value ) }
# class field # class field
rule(:field => simple(:field) , :type => simple(:type), :name => simple(:name)) { rule(:field => simple(:field) , :type => simple(:type), :name => simple(:name)) {
s(:class_field , type.to_sym , name.to_sym) } s(:class_field , type_sym(type) , name.to_sym) }
rule(:field => simple(:field) , :type => simple(:type), :name => simple(:name) , :value => simple(:value)) { rule(:field => simple(:field) , :type => simple(:type), :name => simple(:name) , :value => simple(:value)) {
s(:class_field , type.to_sym , name.to_sym , value ) } s(:class_field , type_sym(type) , name.to_sym , value ) }
rule(:module_name => simple(:module_name)) { s(:module,module_name.to_s) } rule(:l_value => simple(:l_value) , :assign => simple(:assign) , :r_value => simple(:r_value)) {
s(:assignment , l_value , r_value)
}
rule( :left => simple(:left) , :operator => simple(:operator) ,
:right => simple(:right)) { s(:operator_value , operator.to_sym , left , right )}
rule(:class_name => simple(:class_name)) { s(:class_name,class_name.to_s.to_sym) }
rule(:array_constant => sequence(:array_constant) ) { s(:array , *array_constant) } rule(:array_constant => sequence(:array_constant) ) { s(:array , *array_constant) }
rule(:array_element => simple(:array_element)) { array_element } rule(:array_element => simple(:array_element)) { array_element }
@ -48,68 +64,59 @@ module Parser
s(:field_access , s(:receiver , receiver) , s(:field , field) ) s(:field_access , s(:receiver , receiver) , s(:field , field) )
end end
rule(:if => simple(:if), :conditional => simple(:conditional), rule(:condition => simple(:condition) ,
:if_true => {:expressions => sequence(:if_true) , :else => simple(:else) }, :conditional => simple(:conditional),
:if_false => {:expressions => sequence(:if_false) , :end => simple(:e) }) do :body => {:statements => sequence(:body) , :end => simple(:e) }) do
s(:if , s(:condition, conditional), s(:if_true, *if_true), s(:if_false , *if_false)) s(:while_statement,condition.to_s.to_sym, s(:conditional , conditional), s(:statements , *body))
end end
rule(:if => simple(:if), :conditional => simple(:conditional), rule(:condition => simple(:condition), :conditional => simple(:conditional),
:if_true => {:expressions => sequence(:if_true) , :end => simple(:e) }) do :true_statements => {:statements => sequence(:true_statements) , :else => simple(:else) },
s(:if , s(:condition, conditional), s(:if_true, *if_true), s(:if_false , nil) ) :false_statements => {:statements => sequence(:false_statements) , :end => simple(:e) }) do
s(:if_statement, condition.to_s.to_sym,
s(:condition, conditional),
s(:true_statements, *true_statements),
s(:false_statements , *false_statements))
end end
rule(:while => simple(:while), rule(:condition => simple(:condition), :conditional => simple(:conditional),
:while_cond => simple(:while_cond) , :true_statements => {:statements => sequence(:true_statements) , :end => simple(:e) }) do
:body => {:expressions => sequence(:body) , :end => simple(:e) }) do s(:if_statement, condition.to_s.to_sym, s(:condition, conditional),
s(:while , s(:condition , while_cond), s(:expressions , *body)) s(:true_statements, *true_statements), s(:false_statements , nil) )
end end
rule(:return => simple(:return) , :return_expression => simple(:return_expression))do rule(:return => simple(:return) , :return_statement => simple(:return_statement))do
s(:return , return_expression) s(:return , return_statement)
end end
rule(:parameter => simple(:parameter)) { s(:parameter , *parameter) } rule(:parameter => simple(:parameter)) { s(:parameter , parameter.children[0] , parameter.children[1].children[0]) }
# Also two rules for function definitions, unqualified and qualified # Also two rules for function definitions, unqualified and qualified
rule(:type => simple(:type) , rule(:type => simple(:type) ,
:function_name => simple(:function_name), :function_name => simple(:function_name),
:parameter_list => sequence(:parameter_list), :parameter_list => sequence(:parameter_list),
:expressions => sequence(:expressions) , :end => simple(:e)) do :statements => sequence(:statements) , :end => simple(:e)) do
s(:function, type.to_sym , function_name, s(:parameters , *parameter_list ), s(:function, type_sym(type) , function_name, s(:parameters , *parameter_list ),
s(:expressions , *expressions)) s(:statements , *statements))
end end
rule(:type => simple(:type) , rule(:type => simple(:type) ,
:receiver=> simple(:receiver), :receiver=> simple(:receiver),
:function_name => simple(:function_name), :function_name => simple(:function_name),
:parameter_list => sequence(:parameter_list), :parameter_list => sequence(:parameter_list),
:expressions => sequence(:expressions) , :end => simple(:e)) do :statements => sequence(:statements) , :end => simple(:e)) do
s(:function, type.to_sym , function_name, s(:parameters , *parameter_list ), s(:function, type_sym(type) , function_name, s(:parameters , *parameter_list ),
s(:expressions , *expressions) , s(:receiver , *receiver)) s(:statements , *statements) , s(:receiver , *receiver))
end end
rule(l: simple(:l), o: simple(:o) , r: simple(:r)) do rule( :class_name => simple(:class_name) , :derived_name => simple(:derived_name) , :class_statements => sequence(:class_statements) , :end=>"end") do
op = o.to_s.strip s(:class , class_name.to_s.to_sym ,
if op == "="
s(:assign , l ,r)
else
s(:operator, op , l ,r)
end
end
#modules and classes are understandibly quite similar Class < Module
rule( :module_name => simple(:module_name) , :derived_name => simple(:derived_name) , :class_expressions => sequence(:class_expressions) , :end=>"end") do
s(:class , module_name.to_s.to_sym ,
s(:derives, derived_name ? derived_name.to_a.first.to_sym : nil) , s(:derives, derived_name ? derived_name.to_a.first.to_sym : nil) ,
s(:expressions, *class_expressions) ) s(:statements, *class_statements) )
end
rule( :module_name => simple(:module_name) , :module_expressions => sequence(:module_expressions) , :end=>"end") do
s(:module , module_name.to_s.to_sym , s(:expressions, *module_expressions))
end end
rule(:expression_list => sequence(:expression_list)) { rule(:statement_list => sequence(:statement_list)) {
s(:expressions , *expression_list) s(:statements , *statement_list)
} }
#shortcut to get the ast tree for a given string #shortcut to get the ast tree for a given string

View File

@ -1,4 +1,5 @@
require 'parslet' require 'parslet'
require 'parser/salama' require 'parser/soml'
require "ast" require "ast"
require 'parser/transform' require 'parser/transform'
require "soml/code/code"

View File

@ -0,0 +1,13 @@
module Soml
class Assignment < Statement
attr_accessor :name , :value
def initialize(n = nil , v = nil )
@name , @value = n , v
end
end
class FieldDef < Statement
attr_accessor :name , :type , :value
end
end

View File

@ -0,0 +1,39 @@
module Soml
class IntegerExpression < Expression
attr_accessor :value
def initialize(value)
@value = value
end
end
class FloatExpression < Expression
attr_accessor :value
def initialize(value)
@value = value
end
end
class TrueExpression < Expression
end
class FalseExpression < Expression
end
class NilExpression < Expression
end
class StringExpression < Expression
attr_accessor :value
def initialize(value)
@value = value
end
end
class NameExpression < Expression
attr_accessor :value
alias :name :value
def initialize(value)
@value = value
end
end
class ClassExpression < Expression
attr_accessor :value
def initialize(value)
@value = value
end
end
end

View File

@ -0,0 +1,5 @@
module Soml
class CallSite < Expression
attr_accessor :name , :receiver , :arguments
end
end

View File

@ -0,0 +1,9 @@
module Soml
class ClassStatement < Statement
attr_accessor :name , :derives , :statements
end
class ClassField < Statement
attr_accessor :name , :type
end
end

27
lib/soml/code/code.rb Normal file
View File

@ -0,0 +1,27 @@
# Base class for Expresssion and Statement
module Soml
class Code
end
class Statement < Code
end
class Expression < Code
end
end
require_relative "while_statement"
require_relative "if_statement"
require_relative "return_statement"
require_relative "statements"
require_relative "operator_expression"
require_relative "field_access"
require_relative "call_site"
require_relative "basic_values"
require_relative "assignment"
require_relative "class_statement"
require_relative "function_statement"
require_relative "to_code"

View File

@ -0,0 +1,5 @@
module Soml
class FieldAccess < Expression
attr_accessor :receiver , :field
end
end

View File

@ -0,0 +1,5 @@
module Soml
class FunctionStatement < Statement
attr_accessor :return_type , :name , :parameters, :statements , :receiver
end
end

View File

@ -0,0 +1,5 @@
module Soml
class IfStatement < Statement
attr_accessor :branch_type , :condition , :if_true , :if_false
end
end

View File

@ -0,0 +1,5 @@
module Soml
class OperatorExpression < Expression
attr_accessor :operator , :left_expression , :right_expression
end
end

View File

@ -0,0 +1,5 @@
module Soml
class ReturnStatement < Statement
attr_accessor :return_value
end
end

View File

@ -0,0 +1,5 @@
module Soml
class Statements < Statement
attr_accessor :statements
end
end

163
lib/soml/code/to_code.rb Normal file
View File

@ -0,0 +1,163 @@
module Soml
def self.ast_to_code statement
compiler = ToCode.new
compiler.process statement
end
class ToCode < AST::Processor
def handler_missing node
raise "No handler on_#{node.type}(node)"
end
def on_class statement
name , derives , statements = *statement
w = ClassStatement.new()
w.name = name
w.derives = derives.children.first
w.statements = process(statements)
w
end
def on_function statement
return_type , name , parameters, statements , receiver = *statement
w = FunctionStatement.new()
w.return_type = return_type
w.name = name.children.first
w.parameters = parameters.to_a.collect do |p|
raise "error, argument must be a identifier, not #{p}" unless p.type == :parameter
p.children
end
w.statements = process(statements)
w.receiver = receiver
w
end
def on_field_def statement
type , name , value = *statement
w = FieldDef.new()
w.type = type
w.name = process(name)
w.value = process(value) if value
w
end
def on_class_field statement
type , name = *statement
w = ClassField.new()
w.type = type
w.name = name
w
end
def on_while_statement statement
branch_type , condition , statements = *statement
w = WhileStatement.new()
w.branch_type = branch_type
w.condition = process(condition)
w.statements = process(statements)
w
end
def on_if_statement statement
branch_type , condition , if_true , if_false = *statement
w = IfStatement.new()
w.branch_type = branch_type
w.condition = process(condition)
w.if_true = process(if_true)
w.if_false = process(if_false)
w
end
def process_first code
raise "Too many children #{code.inspect}" if code.children.length != 1
process code.children.first
end
alias :on_conditional :process_first
alias :on_condition :process_first
alias :on_field :process_first
def on_statements statement
w = Statements.new()
return w unless statement.children
return w unless statement.children.first
w.statements = process_all(statement.children)
w
end
alias :on_true_statements :on_statements
alias :on_false_statements :on_statements
def on_return statement
w = ReturnStatement.new()
w.return_value = process(statement.children.first)
w
end
def on_operator_value statement
operator , left_e , right_e = *statement
w = OperatorExpression.new()
w.operator = operator
w.left_expression = process(left_e)
w.right_expression = process(right_e)
w
end
def on_field_access statement
receiver_ast , field_ast = *statement
w = FieldAccess.new()
w.receiver = process(receiver_ast)
w.field = process(field_ast)
w
end
def on_receiver expression
process expression.children.first
end
def on_call statement
name_s , arguments , receiver = *statement
w = CallSite.new()
w.name = name_s.children.first
w.arguments = process_all(arguments)
w.receiver = process(receiver)
w
end
def on_int expression
IntegerExpression.new(expression.children.first)
end
def on_true expression
TrueExpression.new
end
def on_false expression
FalseExpression.new
end
def on_nil expression
NilExpression.new
end
def on_name statement
NameExpression.new(statement.children.first)
end
def on_string expression
StringExpression.new(expression.children.first)
end
def on_class_name expression
ClassExpression.new(expression.children.first)
end
def on_assignment statement
name , value = *statement
w = Assignment.new()
w.name = process name
w.value = process(value)
w
end
end
end

View File

@ -0,0 +1,5 @@
module Soml
class WhileStatement < Statement
attr_accessor :branch_type , :condition , :statements
end
end

View File

@ -1,19 +1,19 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = 'salama-reader' s.name = 'soml-parser'
s.version = '0.3.0' s.version = '0.5.0'
s.authors = ['Torsten Ruger'] s.authors = ['Torsten Ruger']
s.email = 'torsten@villataika.fi' s.email = 'torsten@villataika.fi'
s.extra_rdoc_files = ['README.md'] s.extra_rdoc_files = ['README.md']
s.files = %w(README.md LICENSE) + Dir.glob("lib/**/*") s.files = %w(README.md LICENSE) + Dir.glob("lib/**/*")
s.homepage = 'https://github.com/salama/salama-reader' s.homepage = 'https://github.com/salama/soml-parser'
s.license = 'GNU v3' s.license = 'GNU v3'
s.require_paths = ['lib'] s.require_paths = ['lib']
s.summary = 'Ruby parser for the salama machine' s.summary = 'Ruby parser for the salama object system language'
s.add_dependency 'parslet', '~> 1.7.0' s.add_dependency 'parslet', '~> 1.7.1'
s.add_dependency 'ast', '~> 2.1.0' s.add_dependency 'ast', '~> 2.1.0'
end end

View File

@ -8,8 +8,10 @@ to run just a single, replace all with what you want to test. Minitest accept a
ruby test/test_class.rb -n test_class_ops_parse ruby test/test_class.rb -n test_class_ops_parse
Notice tough the "_parse" at the end, while you will find no such function. The Magic (explained below) renerates three Notice tough the "_parse" at the end, while you will find no such function.
functions per case. Your options are "_parse" , "_transform" , or if it's really bad, "_ast" (this should really work when the previous two work) The Magic (explained below) generates three functions per case.
Your options are "_parse" , "_transform" , or if it's really bad, "_ast"
(this should really work when the previous two work)
### Directories ### Directories
@ -26,7 +28,7 @@ Apart from just plain more tests, two additional directories are planned. One is
Parsing is a two step process with parslet: Parsing is a two step process with parslet:
- parse takes an input and outputs hashes/arrays with basic types - parse takes an input and outputs hashes/arrays with basic types
- tramsform takes the output of parse and generates an ast (as specified by the transformation) - transform takes the output of parse and generates an ast (as specified by the transformation)
A test tests both phases separately and again together. A test tests both phases separately and again together.
Each test must thus specify (as instance variables): Each test must thus specify (as instance variables):

View File

@ -0,0 +1,9 @@
self.a = 5
-- -- --
s(:assignment,
s(:field_access,
s(:receiver,
s(:name, :self)),
s(:field,
s(:name, :a))),
s(:int, 5))

View File

@ -0,0 +1,5 @@
name = 10
-- -- --
s(:assignment,
s(:name, :name),
s(:int, 10))

View File

@ -1,4 +0,0 @@
FooBar
-- -- --
s(:expressions,
s(:module, "FooBar"))

View File

@ -1,4 +0,0 @@
foo
-- -- --
s(:expressions,
s(:name, :foo))

View File

@ -1,4 +0,0 @@
foo_bar
-- -- --
s(:expressions,
s(:name, :foo_bar))

View File

@ -1,4 +0,0 @@
_bar
-- -- --
s(:expressions,
s(:name, :_bar))

View File

@ -1,4 +0,0 @@
42
-- -- --
s(:expressions,
s(:int, 42))

View File

@ -1,4 +0,0 @@
"hello"
-- -- --
s(:expressions,
s(:string, "hello"))

View File

@ -1,4 +0,0 @@
"hello \nyou"
-- -- --
s(:expressions,
s(:string, "hello \\nyou"))

View File

@ -0,0 +1,3 @@
FooBar
-- -- --
s(:class_name, :FooBar)

View File

@ -0,0 +1,3 @@
foo
-- -- --
s(:name, :foo)

View File

@ -0,0 +1,3 @@
foo_bar
-- -- --
s(:name, :foo_bar)

View File

@ -0,0 +1,3 @@
_bar
-- -- --
s(:name, :_bar)

View File

@ -0,0 +1,3 @@
42
-- -- --
s(:int, 42)

View File

@ -0,0 +1,2 @@
"hello"-- -- --
s(:string, "hello")

View File

@ -0,0 +1,2 @@
"hello \nyou"-- -- --
s(:string, "hello \\nyou")

View File

@ -1,8 +1,7 @@
puts(3 , a ) puts(3 , a )
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :puts),
s(:name, :puts), s(:arguments,
s(:arguments, s(:int, 3),
s(:int, 3), s(:name, :a)))
s(:name, :a))))

View File

@ -1,8 +1,7 @@
baz(42, foo) baz(42, foo)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :baz),
s(:name, :baz), s(:arguments,
s(:arguments, s(:int, 42),
s(:int, 42), s(:name, :foo)))
s(:name, :foo))))

View File

@ -1,7 +1,6 @@
puts( "hello") puts( "hello")
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :puts),
s(:name, :puts), s(:arguments,
s(:arguments, s(:string, "hello")))
s(:string, "hello"))))

View File

@ -1,8 +0,0 @@
message.self
-- -- --
s(:expressions,
s(:field_access,
s(:receiver,
s(:name, :message)),
s(:field,
s(:name, :self))))

View File

@ -1,8 +1,7 @@
42.put() 42.put()
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :put),
s(:name, :put), s(:arguments),
s(:arguments), s(:receiver,
s(:receiver, s(:int, 42)))
s(:int, 42))))

View File

@ -1,7 +1,6 @@
puts( 5) puts( 5)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :puts),
s(:name, :puts), s(:arguments,
s(:arguments, s(:int, 5)))
s(:int, 5))))

View File

@ -1,7 +1,6 @@
foo(42) foo(42)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :foo),
s(:name, :foo), s(:arguments,
s(:arguments, s(:int, 42)))
s(:int, 42))))

View File

@ -1,9 +1,8 @@
Object.foo(42) Object.foo(42)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :foo),
s(:name, :foo), s(:arguments,
s(:arguments, s(:int, 42)),
s(:int, 42)), s(:receiver,
s(:receiver, s(:class_name, :Object)))
s(:module, "Object"))))

View File

@ -1,9 +1,8 @@
my_my.foo(42) my_my.foo(42)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :foo),
s(:name, :foo), s(:arguments,
s(:arguments, s(:int, 42)),
s(:int, 42)), s(:receiver,
s(:receiver, s(:name, :my_my)))
s(:name, :my_my))))

View File

@ -1,9 +1,8 @@
self.foo(42) self.foo(42)
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :foo),
s(:name, :foo), s(:arguments,
s(:arguments, s(:int, 42)),
s(:int, 42)), s(:receiver,
s(:receiver, s(:name, :self)))
s(:name, :self))))

View File

@ -1,8 +1,7 @@
"hello".puts() "hello".puts()
-- -- -- -- -- --
s(:expressions, s(:call,
s(:call, s(:name, :puts),
s(:name, :puts), s(:arguments),
s(:arguments), s(:receiver,
s(:receiver, s(:string, "hello")))
s(:string, "hello"))))

View File

@ -1,15 +0,0 @@
class Foo < Object
int test()
43
end
end
-- -- --
s(:expressions,
s(:class, :Foo,
s(:derives, :Object),
s(:expressions,
s(:function, :int,
s(:name, :test),
s(:parameters),
s(:expressions,
s(:int, 43))))))

View File

@ -1,17 +0,0 @@
class Foo
module Boo
funcall(3 , var)
end
end
-- -- --
s(:expressions,
s(:class, :Foo,
s(:derives, nil),
s(:expressions,
s(:module, :Boo,
s(:expressions,
s(:call,
s(:name, :funcall),
s(:arguments,
s(:int, 3),
s(:name, :var))))))))

View File

@ -1,21 +0,0 @@
class Opers
int foo(int x)
int abba = 5
abba + 5
end
end
-- -- --
s(:expressions,
s(:class, :Opers,
s(:derives, nil),
s(:expressions,
s(:function, :int,
s(:name, :foo),
s(:parameters,
s(:parameter, :int, :x)),
s(:expressions,
s(:field_def, :int, :abba,
s(:int, 5)),
s(:operator, "+",
s(:name, :abba),
s(:int, 5)))))))

View File

@ -1,9 +0,0 @@
class Foo
5
end
-- -- --
s(:expressions,
s(:class, :Foo,
s(:derives, nil),
s(:expressions,
s(:int, 5))))

View File

@ -1,6 +1,6 @@
class String class String
ref self.new_string(int len ) String self.new_string(int len )
len = len << 2 len = len << 2
return super.new_object( len) return super.new_object( len)
end end
@ -9,19 +9,19 @@ class String
return self.length return self.length
end end
int plus(ref str) int plus(String str)
my_length = self.length my_length = self.length
str_len = str.length() str_len = str.length()
my_length = str_len + my_length my_length = str_len + my_length
new_string = self.new_string(my_length ) new_string = self.new_string(my_length )
i = 0 i = 0
while( i < my_length) while_plus( i - my_length)
char = get(i) char = get(i)
new_string.set(i , char) new_string.set(i , char)
i = i + 1 i = i + 1
end end
i = 0 i = 0
while( i < str_len) while_plus( i - str_len)
char = str.get(i) char = str.get(i)
len = i + my_length len = i + my_length
new_string.set( len , char) new_string.set( len , char)
@ -32,18 +32,18 @@ class String
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:class, :String, s(:class, :String,
s(:derives, nil), s(:derives, nil),
s(:expressions, s(:statements,
s(:function, :ref, s(:function, :String,
s(:name, :new_string), s(:name, :new_string),
s(:parameters, s(:parameters,
s(:parameter, :int, :len)), s(:parameter, :Integer, :len)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :len), s(:name, :len),
s(:operator, "<<", s(:operator_value, :<<,
s(:name, :len), s(:name, :len),
s(:int, 2))), s(:int, 2))),
s(:return, s(:return,
@ -54,41 +54,41 @@ s(:expressions,
s(:receiver, s(:receiver,
s(:name, :super))))), s(:name, :super))))),
s(:receiver, :self)), s(:receiver, :self)),
s(:function, :int, s(:function, :Integer,
s(:name, :length), s(:name, :length),
s(:parameters), s(:parameters),
s(:expressions, s(:statements,
s(:return, s(:return,
s(:field_access, s(:field_access,
s(:receiver, s(:receiver,
s(:name, :self)), s(:name, :self)),
s(:field, s(:field,
s(:name, :length)))))), s(:name, :length)))))),
s(:function, :int, s(:function, :Integer,
s(:name, :plus), s(:name, :plus),
s(:parameters, s(:parameters,
s(:parameter, :ref, :str)), s(:parameter, :String, :str)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :my_length), s(:name, :my_length),
s(:field_access, s(:field_access,
s(:receiver, s(:receiver,
s(:name, :self)), s(:name, :self)),
s(:field, s(:field,
s(:name, :length)))), s(:name, :length)))),
s(:assign, s(:assignment,
s(:name, :str_len), s(:name, :str_len),
s(:call, s(:call,
s(:name, :length), s(:name, :length),
s(:arguments), s(:arguments),
s(:receiver, s(:receiver,
s(:name, :str)))), s(:name, :str)))),
s(:assign, s(:assignment,
s(:name, :my_length), s(:name, :my_length),
s(:operator, "+", s(:operator_value, :+,
s(:name, :str_len), s(:name, :str_len),
s(:name, :my_length))), s(:name, :my_length))),
s(:assign, s(:assignment,
s(:name, :new_string), s(:name, :new_string),
s(:call, s(:call,
s(:name, :new_string), s(:name, :new_string),
@ -96,16 +96,16 @@ s(:expressions,
s(:name, :my_length)), s(:name, :my_length)),
s(:receiver, s(:receiver,
s(:name, :self)))), s(:name, :self)))),
s(:assign, s(:assignment,
s(:name, :i), s(:name, :i),
s(:int, 0)), s(:int, 0)),
s(:while, s(:while_statement, :plus,
s(:condition, s(:conditional,
s(:operator, "<", s(:operator_value, :-,
s(:name, :i), s(:name, :i),
s(:name, :my_length))), s(:name, :my_length))),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :char), s(:name, :char),
s(:call, s(:call,
s(:name, :get), s(:name, :get),
@ -118,21 +118,21 @@ s(:expressions,
s(:name, :char)), s(:name, :char)),
s(:receiver, s(:receiver,
s(:name, :new_string))), s(:name, :new_string))),
s(:assign, s(:assignment,
s(:name, :i), s(:name, :i),
s(:operator, "+", s(:operator_value, :+,
s(:name, :i), s(:name, :i),
s(:int, 1))))), s(:int, 1))))),
s(:assign, s(:assignment,
s(:name, :i), s(:name, :i),
s(:int, 0)), s(:int, 0)),
s(:while, s(:while_statement, :plus,
s(:condition, s(:conditional,
s(:operator, "<", s(:operator_value, :-,
s(:name, :i), s(:name, :i),
s(:name, :str_len))), s(:name, :str_len))),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :char), s(:name, :char),
s(:call, s(:call,
s(:name, :get), s(:name, :get),
@ -140,9 +140,9 @@ s(:expressions,
s(:name, :i)), s(:name, :i)),
s(:receiver, s(:receiver,
s(:name, :str)))), s(:name, :str)))),
s(:assign, s(:assignment,
s(:name, :len), s(:name, :len),
s(:operator, "+", s(:operator_value, :+,
s(:name, :i), s(:name, :i),
s(:name, :my_length))), s(:name, :my_length))),
s(:call, s(:call,
@ -152,9 +152,9 @@ s(:expressions,
s(:name, :char)), s(:name, :char)),
s(:receiver, s(:receiver,
s(:name, :new_string))), s(:name, :new_string))),
s(:assign, s(:assignment,
s(:name, :i), s(:name, :i),
s(:operator, "+", s(:operator_value, :+,
s(:name, :i), s(:name, :i),
s(:int, 1))))), s(:int, 1))))),
s(:return, s(:return,

View File

@ -3,27 +3,21 @@ class Foo < Object
int func() int func()
return self.fff return self.fff
end end
ofthen(3 , var)
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:class, :Foo, s(:class, :Foo,
s(:derives, :Object), s(:derives, :Object),
s(:expressions, s(:statements,
s(:class_field, :int, :fff, s(:class_field, :Integer, :fff,
s(:int, 3)), s(:int, 3)),
s(:function, :int, s(:function, :Integer,
s(:name, :func), s(:name, :func),
s(:parameters), s(:parameters),
s(:expressions, s(:statements,
s(:return, s(:return,
s(:field_access, s(:field_access,
s(:receiver, s(:receiver,
s(:name, :self)), s(:name, :self)),
s(:field, s(:field,
s(:name, :fff)))))), s(:name, :fff)))))))))
s(:call,
s(:name, :ofthen),
s(:arguments,
s(:int, 3),
s(:name, :var))))))

View File

@ -1,30 +1,24 @@
class Pifi class Pifi
ofthen(3 , var)
int self.ofthen(int n , ref m) int self.ofthen(int n , Object m)
n = n + m.index n = n + m.index
return n return n
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:class, :Pifi, s(:class, :Pifi,
s(:derives, nil), s(:derives, nil),
s(:expressions, s(:statements,
s(:call, s(:function, :Integer,
s(:name, :ofthen),
s(:arguments,
s(:int, 3),
s(:name, :var))),
s(:function, :int,
s(:name, :ofthen), s(:name, :ofthen),
s(:parameters, s(:parameters,
s(:parameter, :int, :n), s(:parameter, :Integer, :n),
s(:parameter, :ref, :m)), s(:parameter, :Object, :m)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :n), s(:name, :n),
s(:operator, "+", s(:operator_value, :+,
s(:name, :n), s(:name, :n),
s(:field_access, s(:field_access,
s(:receiver, s(:receiver,

View File

@ -1,6 +1,6 @@
class Ifi class Ifi
int ofthen(int n) int ofthen(int n)
if(0) if_zero(0)
isit = 42 isit = 42
else else
maybenot = 667 maybenot = 667
@ -8,23 +8,23 @@ class Ifi
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:class, :Ifi, s(:class, :Ifi,
s(:derives, nil), s(:derives, nil),
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :ofthen), s(:name, :ofthen),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:if, s(:if_statement, :zero,
s(:condition, s(:condition,
s(:int, 0)), s(:int, 0)),
s(:if_true, s(:true_statements,
s(:assign, s(:assignment,
s(:name, :isit), s(:name, :isit),
s(:int, 42))), s(:int, 42))),
s(:if_false, s(:false_statements,
s(:assign, s(:assignment,
s(:name, :maybenot), s(:name, :maybenot),
s(:int, 667))))))))) s(:int, 667)))))))))

View File

@ -0,0 +1,16 @@
class Foo < Object
int test()
return 43
end
end
-- -- --
s(:statements,
s(:class, :Foo,
s(:derives, :Object),
s(:statements,
s(:function, :Integer,
s(:name, :test),
s(:parameters),
s(:statements,
s(:return,
s(:int, 43)))))))

View File

@ -0,0 +1,23 @@
class Opers
int foo(int x)
int abba = 5
return abba + 5
end
end
-- -- --
s(:statements,
s(:class, :Opers,
s(:derives, nil),
s(:statements,
s(:function, :Integer,
s(:name, :foo),
s(:parameters,
s(:parameter, :Integer, :x)),
s(:statements,
s(:field_def, :Integer,
s(:name, :abba),
s(:int, 5)),
s(:return,
s(:operator_value, :+,
s(:name, :abba),
s(:int, 5))))))))

View File

@ -0,0 +1,9 @@
class Foo
field int x
end
-- -- --
s(:statements,
s(:class, :Foo,
s(:derives, nil),
s(:statements,
s(:class_field, :Integer, :x))))

View File

@ -1,6 +0,0 @@
[42, foo]
-- -- --
s(:expressions,
s(:array,
s(:int, 42),
s(:name, :foo)))

View File

@ -1,11 +0,0 @@
[ 3 + 4 , foo(22) ]
-- -- --
s(:expressions,
s(:array,
s(:operator, "+",
s(:int, 3),
s(:int, 4)),
s(:call,
s(:name, :foo),
s(:arguments,
s(:int, 22)))))

View File

@ -1,7 +0,0 @@
{ foo => 33 }
-- -- --
s(:expressions,
s(:hash,
s(:assoc,
s(:name, :foo),
s(:int, 33))))

View File

@ -1,7 +0,0 @@
{ foo => true }
-- -- --
s(:expressions,
s(:hash,
s(:assoc,
s(:name, :foo),
s(:true))))

View File

@ -1,10 +0,0 @@
{foo => 33 , bar => 42}
-- -- --
s(:expressions,
s(:hash,
s(:assoc,
s(:name, :foo),
s(:int, 33)),
s(:assoc,
s(:name, :bar),
s(:int, 42))))

View File

@ -1,5 +0,0 @@
[42]
-- -- --
s(:expressions,
s(:array,
s(:int, 42)))

View File

@ -1,14 +0,0 @@
if(0)
42
else
667
end
-- -- --
s(:expressions,
s(:if,
s(:condition,
s(:int, 0)),
s(:if_true,
s(:int, 42)),
s(:if_false,
s(:int, 667))))

View File

@ -1,25 +0,0 @@
if(3 > var)
Object.initialize(3)
else
var.new(33)
end
-- -- --
s(:expressions,
s(:if,
s(:condition,
s(:operator, ">",
s(:int, 3),
s(:name, :var))),
s(:if_true,
s(:call,
s(:name, :initialize),
s(:arguments,
s(:int, 3)),
s(:receiver,
s(:module, "Object")))),
s(:if_false, s(:call,
s(:name, :new),
s(:arguments,
s(:int, 33)),
s(:receiver,
s(:name, :var))))))

View File

@ -1,11 +0,0 @@
if(0)
42
end
-- -- --
s(:expressions,
s(:if,
s(:condition,
s(:int, 0)),
s(:if_true,
s(:int, 42)),
s(:if_false, nil)))

View File

@ -1,18 +0,0 @@
if(3 > var)
Object.initialize(3)
end
-- -- --
s(:expressions,
s(:if,
s(:condition,
s(:operator, ">",
s(:int, 3),
s(:name, :var))),
s(:if_true,
s(:call,
s(:name, :initialize),
s(:arguments,
s(:int, 3)),
s(:receiver,
s(:module, "Object")))),
s(:if_false, nil)))

View File

@ -1,6 +0,0 @@
a = 5
-- -- --
s(:expressions,
s(:assign,
s(:name, :a),
s(:int, 5)))

View File

@ -1,6 +0,0 @@
a = 5
-- -- --
s(:expressions,
s(:assign,
s(:name, :a),
s(:int, 5)))

View File

@ -1,6 +0,0 @@
a - b
-- -- --
s(:expressions,
s(:operator, "-",
s(:name, :a),
s(:name, :b)))

View File

@ -1,6 +0,0 @@
a - 5
-- -- --
s(:expressions,
s(:operator, "-",
s(:name, :a),
s(:int, 5)))

View File

@ -1,6 +0,0 @@
a - "st"
-- -- --
s(:expressions,
s(:operator, "-",
s(:name, :a),
s(:string, "st")))

View File

@ -1,6 +0,0 @@
a == true
-- -- --
s(:expressions,
s(:operator, "==",
s(:name, :a),
s(:true)))

View File

@ -1,6 +0,0 @@
5 / 3
-- -- --
s(:expressions,
s(:operator, "/",
s(:int, 5),
s(:int, 3)))

View File

@ -1,6 +0,0 @@
5 > 3
-- -- --
s(:expressions,
s(:operator, ">",
s(:int, 5),
s(:int, 3)))

View File

@ -1,6 +0,0 @@
5 - 3
-- -- --
s(:expressions,
s(:operator, "-",
s(:int, 5),
s(:int, 3)))

View File

@ -1,6 +0,0 @@
5 * 3
-- -- --
s(:expressions,
s(:operator, "*",
s(:int, 5),
s(:int, 3)))

View File

@ -1,6 +0,0 @@
5 + 3
-- -- --
s(:expressions,
s(:operator, "+",
s(:int, 5),
s(:int, 3)))

View File

@ -1,6 +0,0 @@
5 < 3
-- -- --
s(:expressions,
s(:operator, "<",
s(:int, 5),
s(:int, 3)))

View File

@ -1,8 +0,0 @@
2 + 3 * 4
-- -- --
s(:expressions,
s(:operator, "+",
s(:int, 2),
s(:operator, "*",
s(:int, 3),
s(:int, 4))))

View File

@ -1,8 +0,0 @@
2 * 3 + 4
-- -- --
s(:expressions,
s(:operator, "+",
s(:operator, "*",
s(:int, 2),
s(:int, 3)),
s(:int, 4)))

View File

@ -1,8 +0,0 @@
2 + 3 + 4
-- -- --
s(:expressions,
s(:operator, "+",
s(:operator, "+",
s(:int, 2),
s(:int, 3)),
s(:int, 4)))

View File

@ -0,0 +1,7 @@
foo.bar
-- -- --
s(:field_access,
s(:receiver,
s(:name, :foo)),
s(:field,
s(:name, :bar)))

View File

@ -1,12 +1,13 @@
int self.length( ref x ) int self.length( Object x )
length return 5
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :length), s(:name, :length),
s(:parameters, s(:parameters,
s(:parameter, :ref, :x)), s(:parameter, :Object, :x)),
s(:expressions, s(:statements,
s(:name, :length)), s(:return,
s(:int, 5))),
s(:receiver, :self))) s(:receiver, :self)))

View File

@ -1,7 +1,7 @@
int fibonaccit(int n) int fibonaccit(int n)
a = 0 a = 0
b = 1 b = 1
while( n > 1 ) while_positive( n )
tmp = a tmp = a
a = b a = b
b = tmp + b b = tmp + b
@ -10,41 +10,39 @@ int fibonaccit(int n)
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :fibonaccit), s(:name, :fibonaccit),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :a), s(:name, :a),
s(:int, 0)), s(:int, 0)),
s(:assign, s(:assignment,
s(:name, :b), s(:name, :b),
s(:int, 1)), s(:int, 1)),
s(:while, s(:while_statement, :positive,
s(:condition, s(:conditional,
s(:operator, ">", s(:name, :n)),
s(:name, :n), s(:statements,
s(:int, 1))), s(:assignment,
s(:expressions,
s(:assign,
s(:name, :tmp), s(:name, :tmp),
s(:name, :a)), s(:name, :a)),
s(:assign, s(:assignment,
s(:name, :a), s(:name, :a),
s(:name, :b)), s(:name, :b)),
s(:assign, s(:assignment,
s(:name, :b), s(:name, :b),
s(:operator, "+", s(:operator_value, :+,
s(:name, :tmp), s(:name, :tmp),
s(:name, :b))), s(:name, :b))),
s(:call, s(:call,
s(:name, :puts), s(:name, :puts),
s(:arguments, s(:arguments,
s(:name, :b))), s(:name, :b))),
s(:assign, s(:assignment,
s(:name, :n), s(:name, :n),
s(:operator, "-", s(:operator_value, :-,
s(:name, :n), s(:name, :n),
s(:int, 1)))))))) s(:int, 1))))))))

View File

@ -2,21 +2,15 @@ int foo(int x)
int a = 5 int a = 5
return a return a
end end
3.foo( 4 )
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :foo), s(:name, :foo),
s(:parameters, s(:parameters,
s(:parameter, :int, :x)), s(:parameter, :Integer, :x)),
s(:expressions, s(:statements,
s(:field_def, :int, :a, s(:field_def, :Integer,
s(:name, :a),
s(:int, 5)), s(:int, 5)),
s(:return, s(:return,
s(:name, :a)))), s(:name, :a)))))
s(:call,
s(:name, :foo),
s(:arguments,
s(:int, 4)),
s(:receiver,
s(:int, 3))))

View File

@ -1,25 +1,25 @@
ref ofthen(int n) int ofthen(int n)
if(0) if_plus(0)
isit = 42 isit = 42
else else
maybenot = 667 maybenot = 667
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :ref, s(:function, :Integer,
s(:name, :ofthen), s(:name, :ofthen),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:if, s(:if_statement, :plus,
s(:condition, s(:condition,
s(:int, 0)), s(:int, 0)),
s(:if_true, s(:true_statements,
s(:assign, s(:assignment,
s(:name, :isit), s(:name, :isit),
s(:int, 42))), s(:int, 42))),
s(:if_false, s(:false_statements,
s(:assign, s(:assignment,
s(:name, :maybenot), s(:name, :maybenot),
s(:int, 667))))))) s(:int, 667)))))))

View File

@ -1,10 +1,11 @@
int foo() int foo()
5 return 5
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :foo), s(:name, :foo),
s(:parameters), s(:parameters),
s(:expressions, s(:statements,
s(:int, 5)))) s(:return,
s(:int, 5)))))

View File

@ -1,16 +1,19 @@
int foo(int x) int foo(int x)
int abba = 5 int abba = 5
abba + 5 abba = abba + 5
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :foo), s(:name, :foo),
s(:parameters, s(:parameters,
s(:parameter, :int, :x)), s(:parameter, :Integer, :x)),
s(:expressions, s(:statements,
s(:field_def, :int, :abba, s(:field_def, :Integer,
s(:int, 5)),
s(:operator, "+",
s(:name, :abba), s(:name, :abba),
s(:int, 5))))) s(:int, 5)),
s(:assignment,
s(:name, :abba),
s(:operator_value, :+,
s(:name, :abba),
s(:int, 5))))))

View File

@ -1,15 +1,16 @@
int retvar(ref n) int retvar(Object n)
int i = n.layout int i = n.layout
return i return i
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :retvar), s(:name, :retvar),
s(:parameters, s(:parameters,
s(:parameter, :ref, :n)), s(:parameter, :Object, :n)),
s(:expressions, s(:statements,
s(:field_def, :int, :i, s(:field_def, :Integer,
s(:name, :i),
s(:field_access, s(:field_access,
s(:receiver, s(:receiver,
s(:name, :n)), s(:name, :n)),

View File

@ -1,25 +1,25 @@
int retvar(int n) int retvar(int n)
if( n > 5) if_positive( n - 5)
return 10 return 10
else else
return 20 return 20
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :retvar), s(:name, :retvar),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:if, s(:if_statement, :positive,
s(:condition, s(:condition,
s(:operator, ">", s(:operator_value, :-,
s(:name, :n), s(:name, :n),
s(:int, 5))), s(:int, 5))),
s(:if_true, s(:true_statements,
s(:return, s(:return,
s(:int, 10))), s(:int, 10))),
s(:if_false, s(:false_statements,
s(:return, s(:return,
s(:int, 20))))))) s(:int, 20)))))))

View File

@ -1,25 +1,25 @@
int retvar(int n ) int retvar(int n )
while( n > 5) while_positive( n - 5)
n = n + 1 n = n + 1
return n return n
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :retvar), s(:name, :retvar),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:while, s(:while_statement, :positive,
s(:condition, s(:conditional,
s(:operator, ">", s(:operator_value, :-,
s(:name, :n), s(:name, :n),
s(:int, 5))), s(:int, 5))),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :n), s(:name, :n),
s(:operator, "+", s(:operator_value, :+,
s(:name, :n), s(:name, :n),
s(:int, 1))), s(:int, 1))),
s(:return, s(:return,

View File

@ -1,12 +1,13 @@
int foo( int n ,ref m) int foo( int n ,String m)
n return n
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :foo), s(:name, :foo),
s(:parameters, s(:parameters,
s(:parameter, :int, :n), s(:parameter, :Integer, :n),
s(:parameter, :ref, :m)), s(:parameter, :String, :m)),
s(:expressions, s(:statements,
s(:name, :n)))) s(:return,
s(:name, :n)))))

View File

@ -1,29 +1,29 @@
ref fibonaccit(int n) Biggie fibonaccit(int n)
a = 0 a = 0
while(n) while_ok(n)
some = 43 some = 43
other = some * 4 other = some * 4
end end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :ref, s(:function, :Biggie,
s(:name, :fibonaccit), s(:name, :fibonaccit),
s(:parameters, s(:parameters,
s(:parameter, :int, :n)), s(:parameter, :Integer, :n)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :a), s(:name, :a),
s(:int, 0)), s(:int, 0)),
s(:while, s(:while_statement, :ok,
s(:condition, s(:conditional,
s(:name, :n)), s(:name, :n)),
s(:expressions, s(:statements,
s(:assign, s(:assignment,
s(:name, :some), s(:name, :some),
s(:int, 43)), s(:int, 43)),
s(:assign, s(:assignment,
s(:name, :other), s(:name, :other),
s(:operator, "*", s(:operator_value, :*,
s(:name, :some), s(:name, :some),
s(:int, 4)))))))) s(:int, 4))))))))

View File

@ -1,11 +1,13 @@
int foo(ref x) int foo(Class x)
5 a = 1
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:function, :Integer,
s(:name, :foo), s(:name, :foo),
s(:parameters, s(:parameters,
s(:parameter, :ref, :x)), s(:parameter, :Class, :x)),
s(:expressions, s(:statements,
s(:int, 5)))) s(:assignment,
s(:name, :a),
s(:int, 1)))))

View File

@ -0,0 +1,17 @@
if_true(0)
fourty = 10
else
twenty = 5
end
-- -- --
s(:if_statement, :true,
s(:condition,
s(:int, 0)),
s(:true_statements,
s(:assignment,
s(:name, :fourty),
s(:int, 10))),
s(:false_statements,
s(:assignment,
s(:name, :twenty),
s(:int, 5))))

View File

@ -0,0 +1,25 @@
if_yes(3 > var)
Object.initialize(3)
else
var.new(33)
end
-- -- --
s(:if_statement, :yes,
s(:condition,
s(:operator_value, :>,
s(:int, 3),
s(:name, :var))),
s(:true_statements,
s(:call,
s(:name, :initialize),
s(:arguments,
s(:int, 3)),
s(:receiver,
s(:class_name, :Object)))),
s(:false_statements,
s(:call,
s(:name, :new),
s(:arguments,
s(:int, 33)),
s(:receiver,
s(:name, :var)))))

View File

@ -1,11 +0,0 @@
module Opers
field int abba = 5
field ref baab
end
-- -- --
s(:expressions,
s(:module, :Opers,
s(:expressions,
s(:class_field, :int, :abba,
s(:int, 5)),
s(:class_field, :ref, :baab))))

View File

@ -1,17 +0,0 @@
module Foo
class Bar
funcall(3 , var)
end
end
-- -- --
s(:expressions,
s(:module, :Foo,
s(:expressions,
s(:class, :Bar,
s(:derives, nil),
s(:expressions,
s(:call,
s(:name, :funcall),
s(:arguments,
s(:int, 3),
s(:name, :var))))))))

View File

@ -1,23 +0,0 @@
module Soho
ofthen(3 , var)
int ofthen(int n,ref m )
return 44
end
end
-- -- --
s(:expressions,
s(:module, :Soho,
s(:expressions,
s(:call,
s(:name, :ofthen),
s(:arguments,
s(:int, 3),
s(:name, :var))),
s(:function, :int,
s(:name, :ofthen),
s(:parameters,
s(:parameter, :int, :n),
s(:parameter, :ref, :m)),
s(:expressions,
s(:return,
s(:int, 44)))))))

View File

@ -1,29 +0,0 @@
module Foo
ref ofthen(int n)
if(0)
isit = 42
else
maybenot = 667
end
end
end
-- -- --
s(:expressions,
s(:module, :Foo,
s(:expressions,
s(:function, :ref,
s(:name, :ofthen),
s(:parameters,
s(:parameter, :int, :n)),
s(:expressions,
s(:if,
s(:condition,
s(:int, 0)),
s(:if_true,
s(:assign,
s(:name, :isit),
s(:int, 42))),
s(:if_false,
s(:assign,
s(:name, :maybenot),
s(:int, 667)))))))))

View File

@ -1,25 +0,0 @@
module Opers
int foo(int x)
int abba = self.index
return abba + 5
end
end
-- -- --
s(:expressions,
s(:module, :Opers,
s(:expressions,
s(:function, :int,
s(:name, :foo),
s(:parameters,
s(:parameter, :int, :x)),
s(:expressions,
s(:field_def, :int, :abba,
s(:field_access,
s(:receiver,
s(:name, :self)),
s(:field,
s(:name, :index)))),
s(:return,
s(:operator, "+",
s(:name, :abba),
s(:int, 5))))))))

View File

@ -1,8 +0,0 @@
module Simple
5
end
-- -- --
s(:expressions,
s(:module, :Simple,
s(:expressions,
s(:int, 5))))

View File

@ -0,0 +1,9 @@
foo.bar - gumbar
-- -- --
s(:operator_value, :-,
s(:field_access,
s(:receiver,
s(:name, :foo)),
s(:field,
s(:name, :bar))),
s(:name, :gumbar))

View File

@ -0,0 +1,9 @@
5 % foo.bar
-- -- --
s(:operator_value, :%,
s(:int, 5),
s(:field_access,
s(:receiver,
s(:name, :foo)),
s(:field,
s(:name, :bar))))

View File

@ -0,0 +1,5 @@
3 > var
-- -- --
s(:operator_value, :>,
s(:int, 3),
s(:name, :var))

View File

@ -0,0 +1,5 @@
5 + 7
-- -- --
s(:operator_value, :+,
s(:int, 5),
s(:int, 7))

View File

@ -0,0 +1,5 @@
a - b
-- -- --
s(:operator_value, :-,
s(:name, :a),
s(:name, :b))

View File

@ -0,0 +1,5 @@
a - 5
-- -- --
s(:operator_value, :-,
s(:name, :a),
s(:int, 5))

View File

@ -0,0 +1,5 @@
a - "st"
-- -- --
s(:operator_value, :-,
s(:name, :a),
s(:string, "st"))

View File

@ -0,0 +1,5 @@
a == true
-- -- --
s(:operator_value, :==,
s(:name, :a),
s(:true))

View File

@ -0,0 +1,5 @@
5 / 3
-- -- --
s(:operator_value, :/,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,5 @@
5 > 3
-- -- --
s(:operator_value, :>,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,5 @@
5 - 3
-- -- --
s(:operator_value, :-,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,5 @@
5 * 3
-- -- --
s(:operator_value, :*,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,5 @@
5 + 3
-- -- --
s(:operator_value, :+,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,5 @@
5 < 3
-- -- --
s(:operator_value, :<,
s(:int, 5),
s(:int, 3))

View File

@ -0,0 +1,9 @@
gumbar & foo.bar
-- -- --
s(:operator_value, :&,
s(:name, :gumbar),
s(:field_access,
s(:receiver,
s(:name, :foo)),
s(:field,
s(:name, :bar))))

View File

@ -0,0 +1,5 @@
bar - gumbar
-- -- --
s(:operator_value, :-,
s(:name, :bar),
s(:name, :gumbar))

View File

@ -1,5 +0,0 @@
return 42
-- -- --
s(:expressions,
s(:return,
s(:int, 42)))

View File

@ -1,5 +0,0 @@
return "hello"
-- -- --
s(:expressions,
s(:return,
s(:string, "hello")))

View File

@ -1,5 +0,0 @@
return foo
-- -- --
s(:expressions,
s(:return,
s(:name, :foo)))

View File

@ -0,0 +1,4 @@
return 42
-- -- --
s(:return,
s(:int, 42))

View File

@ -0,0 +1,4 @@
return "hello"
-- -- --
s(:return,
s(:string, "hello"))

View File

@ -0,0 +1,4 @@
return foo
-- -- --
s(:return,
s(:name, :foo))

View File

@ -1,15 +1,21 @@
class FooBo class FooBo
Bar.call(35) int main()
Bar.call(35)
end
end end
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:class, :FooBo, s(:class, :FooBo,
s(:derives, nil), s(:derives, nil),
s(:expressions, s(:statements,
s(:call, s(:function, :Integer,
s(:name, :call), s(:name, :main),
s(:arguments, s(:parameters),
s(:int, 35)), s(:statements,
s(:receiver, s(:call,
s(:module, "Bar")))))) s(:name, :call),
s(:arguments,
s(:int, 35)),
s(:receiver,
s(:class_name, :Bar))))))))

View File

@ -1,19 +1,34 @@
int foo(ref x) class Object
a = 5 int foo(String x)
a = 5
end
end
class Other < Object
int foo()
foo( 3 )
end
end end
foo( 3 )
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:class, :Object,
s(:name, :foo), s(:derives, nil),
s(:parameters, s(:statements,
s(:parameter, :ref, :x)), s(:function, :Integer,
s(:expressions, s(:name, :foo),
s(:assign, s(:parameters,
s(:name, :a), s(:parameter, :String, :x)),
s(:int, 5)))), s(:statements,
s(:call, s(:assignment,
s(:name, :foo), s(:name, :a),
s(:arguments, s(:int, 5)))))),
s(:int, 3)))) s(:class, :Other,
s(:derives, :Object),
s(:statements,
s(:function, :Integer,
s(:name, :foo),
s(:parameters),
s(:statements,
s(:call,
s(:name, :foo),
s(:arguments,
s(:int, 3))))))))

View File

@ -1,56 +1,65 @@
int fibonaccit(int n) class Object
a = 0 int fibonaccit(int n)
b = 1 a = 0
while( n > 1 ) b = 1
tmp = a while_plus( n )
a = b tmp = a
b = tmp + b a = b
puts(b) b = tmp + b
n = n - 1 puts(b)
n = n - 1
end
end
int main()
fibonaccit( 10 )
end end
end end
fibonaccit( 10 )
-- -- -- -- -- --
s(:expressions, s(:statements,
s(:function, :int, s(:class, :Object,
s(:name, :fibonaccit), s(:derives, nil),
s(:parameters, s(:statements,
s(:parameter, :int, :n)), s(:function, :Integer,
s(:expressions, s(:name, :fibonaccit),
s(:assign, s(:parameters,
s(:name, :a), s(:parameter, :Integer, :n)),
s(:int, 0)), s(:statements,
s(:assign, s(:assignment,
s(:name, :b),
s(:int, 1)),
s(:while,
s(:condition,
s(:operator, ">",
s(:name, :n),
s(:int, 1))),
s(:expressions,
s(:assign,
s(:name, :tmp),
s(:name, :a)),
s(:assign,
s(:name, :a), s(:name, :a),
s(:name, :b)), s(:int, 0)),
s(:assign, s(:assignment,
s(:name, :b), s(:name, :b),
s(:operator, "+", s(:int, 1)),
s(:name, :tmp), s(:while_statement, :plus,
s(:name, :b))), s(:conditional,
s(:name, :n)),
s(:statements,
s(:assignment,
s(:name, :tmp),
s(:name, :a)),
s(:assignment,
s(:name, :a),
s(:name, :b)),
s(:assignment,
s(:name, :b),
s(:operator_value, :+,
s(:name, :tmp),
s(:name, :b))),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :b))),
s(:assignment,
s(:name, :n),
s(:operator_value, :-,
s(:name, :n),
s(:int, 1))))))),
s(:function, :Integer,
s(:name, :main),
s(:parameters),
s(:statements,
s(:call, s(:call,
s(:name, :puts), s(:name, :fibonaccit),
s(:arguments, s(:arguments,
s(:name, :b))), s(:int, 10))))))))
s(:assign,
s(:name, :n),
s(:operator, "-",
s(:name, :n),
s(:int, 1))))))),
s(:call,
s(:name, :fibonaccit),
s(:arguments,
s(:int, 10))))

View File

@ -1,20 +0,0 @@
module Fibo
a = 5 + foo
bar( b , a , r)
end
-- -- --
s(:expressions,
s(:module, :Fibo,
s(:expressions,
s(:assign,
s(:name, :a),
s(:operator, "+",
s(:int, 5),
s(:name, :foo))),
s(:call,
s(:name, :bar),
s(:arguments,
s(:name, :b),
s(:name, :a),
s(:name, :r))))))

View File

@ -1,26 +0,0 @@
module Fibo
int fibonaccit(int n)
int a = 0
return a
end
fibonaccit( 10 )
end
-- -- --
s(:expressions,
s(:module, :Fibo,
s(:expressions,
s(:function, :int,
s(:name, :fibonaccit),
s(:parameters,
s(:parameter, :int, :n)),
s(:expressions,
s(:field_def, :int, :a,
s(:int, 0)),
s(:return,
s(:name, :a)))),
s(:call,
s(:name, :fibonaccit),
s(:arguments,
s(:int, 10))))))

View File

@ -1,18 +0,0 @@
module FooBo
class Bar
a = 5 + foo
end
end
-- -- --
s(:expressions,
s(:module, :FooBo,
s(:expressions,
s(:class, :Bar,
s(:derives, nil),
s(:expressions,
s(:assign,
s(:name, :a),
s(:operator, "+",
s(:int, 5),
s(:name, :foo))))))))

View File

@ -0,0 +1,12 @@
if_zero(0)
four = 42
end
-- -- --
s(:if_statement, :zero,
s(:condition,
s(:int, 0)),
s(:true_statements,
s(:assignment,
s(:name, :four),
s(:int, 42))),
s(:false_statements, nil))

View File

@ -0,0 +1,17 @@
if_overflow(3 + 100000 )
Object.initialize(3)
end
-- -- --
s(:if_statement, :overflow,
s(:condition,
s(:operator_value, :+,
s(:int, 3),
s(:int, 100000))),
s(:true_statements,
s(:call,
s(:name, :initialize),
s(:arguments,
s(:int, 3)),
s(:receiver,
s(:class_name, :Object)))),
s(:false_statements, nil))

View File

@ -1,35 +0,0 @@
while( n > 1)
tmp = a
a = b
b = tmp + b
puts(b)
n = n - 1
end
-- -- --
s(:expressions,
s(:while,
s(:condition,
s(:operator, ">",
s(:name, :n),
s(:int, 1))),
s(:expressions,
s(:assign,
s(:name, :tmp),
s(:name, :a)),
s(:assign,
s(:name, :a),
s(:name, :b)),
s(:assign,
s(:name, :b),
s(:operator, "+",
s(:name, :tmp),
s(:name, :b))),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :b))),
s(:assign,
s(:name, :n),
s(:operator, "-",
s(:name, :n),
s(:int, 1))))))

View File

@ -1,17 +0,0 @@
while(1)
tmp = a
puts(b)
end
-- -- --
s(:expressions,
s(:while,
s(:condition,
s(:int, 1)),
s(:expressions,
s(:assign,
s(:name, :tmp),
s(:name, :a)),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :b))))))

View File

@ -1,23 +0,0 @@
while(1)
tmp = String.new()
tmp.puts(i)
end
-- -- --
s(:expressions,
s(:while,
s(:condition,
s(:int, 1)),
s(:expressions,
s(:assign,
s(:name, :tmp),
s(:call,
s(:name, :new),
s(:arguments),
s(:receiver,
s(:module, "String")))),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :i)),
s(:receiver,
s(:name, :tmp))))))

View File

@ -0,0 +1,34 @@
while_allgood( n > 1)
tmp = a
a = b
b = tmp + b
puts(b)
n = n - 1
end
-- -- --
s(:while_statement, :allgood,
s(:conditional,
s(:operator_value, :>,
s(:name, :n),
s(:int, 1))),
s(:statements,
s(:assignment,
s(:name, :tmp),
s(:name, :a)),
s(:assignment,
s(:name, :a),
s(:name, :b)),
s(:assignment,
s(:name, :b),
s(:operator_value, :+,
s(:name, :tmp),
s(:name, :b))),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :b))),
s(:assignment,
s(:name, :n),
s(:operator_value, :-,
s(:name, :n),
s(:int, 1)))))

View File

@ -0,0 +1,16 @@
while_false(1)
tmp = a
puts(b)
end
-- -- --
s(:while_statement, :false,
s(:conditional,
s(:int, 1)),
s(:statements,
s(:assignment,
s(:name, :tmp),
s(:name, :a)),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :b)))))

View File

@ -0,0 +1,22 @@
while_true(1)
tmp = String.new()
tmp.puts(i)
end
-- -- --
s(:while_statement, :true,
s(:conditional,
s(:int, 1)),
s(:statements,
s(:assignment,
s(:name, :tmp),
s(:call,
s(:name, :new),
s(:arguments),
s(:receiver,
s(:class_name, :String)))),
s(:call,
s(:name, :puts),
s(:arguments,
s(:name, :i)),
s(:receiver,
s(:name, :tmp)))))

View File

@ -8,7 +8,7 @@ module ParserHelper
def self.included(base) def self.included(base)
base.send :include, InstanceMethods #provides helpers and setup base.send :include, InstanceMethods #provides helpers and setup
base.send :include, AST::if_true base.send :include, AST::true_statements
base.send :extend, ClassMethods #gets the method creation going base.send :extend, ClassMethods #gets the method creation going
end end

View File

@ -13,7 +13,7 @@ if ENV['CODECLIMATE_REPO_TOKEN']
CodeClimate::TestReporter.start CodeClimate::TestReporter.start
end end
require 'salama-reader' require 'soml-parser'
require "minitest" require "minitest"
require "minitest/autorun" require "minitest/autorun"

View File

@ -10,7 +10,13 @@ class TestAll < MiniTest::Test
def check_file file def check_file file
inn , out = File.new(file).read.split(SEPERATOR) inn , out = File.new(file).read.split(SEPERATOR)
sexp = eval(out) sexp = eval(out)
syntax = Parser::Salama.new.parse_with_debug(inn) begin
syntax = Parser::Salama.new.parse(inn)
rescue
root = file.split("/")[2]
parser = Parser::Salama.new.send root.to_sym
syntax = parser.parse_with_debug(inn )
end
result = Parser::Transform.new.apply(syntax) result = Parser::Transform.new.apply(syntax)
equal = (sexp == result) equal = (sexp == result)
unless equal unless equal
@ -28,6 +34,12 @@ class TestAll < MiniTest::Test
end end
end end
assert_equal sexp , result assert_equal sexp , result
check_transform sexp
end
def check_transform sexp
code = Soml.ast_to_code sexp
assert code.is_a?(Soml::Code) , "Returned #{code}"
end end
# this creates test methods dynamically. For each test_* method we create # this creates test methods dynamically. For each test_* method we create

36
to_code.rb Normal file
View File

@ -0,0 +1,36 @@
require 'rubygems'
require 'bundler'
Bundler.setup(:default, :development)
require 'soml-parser'
require "parslet/convenience"
require "ast/sexp"
require "pp"
class Converter
include AST::Sexp
SEPERATOR = "-- -- --"
def to_ast
file = ARGV[0]
inn = File.new(file).read.split(SEPERATOR).first
begin
syntax = Parser::Salama.new.parse(inn)
rescue
root = file.split("/").last.split(".").first
parser = Parser::Salama.new.send root.to_sym
syntax = parser.parse_with_debug(inn )
end
result = Parser::Transform.new.apply(syntax)
out_file = File.new(file, "w")
out_file.puts inn
out_file.puts SEPERATOR
out_file.puts result.inspect
out_file.close
end
end
Converter.new.to_ast