unify grammar file
This commit is contained in:
parent
114817602e
commit
d0980265fd
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
grammar BasicTypes
|
grammar Bosl
|
||||||
|
|
||||||
# unicode generalized categories , according to regex ruby page
|
# unicode generalized categories , according to regex ruby page
|
||||||
rule lower /[[:lower:]]/ end # Lowercase alphabetical character
|
rule lower /[[:lower:]]/ end # Lowercase alphabetical character
|
||||||
@ -135,4 +135,107 @@ grammar BasicTypes
|
|||||||
'!' space*
|
'!' space*
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rule more_args
|
||||||
|
(comma basic_expression )* {
|
||||||
|
captures(:basic_expression).collect{|u| u.value }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule argument_list
|
||||||
|
(left_parenthesis basic_expression? more_args right_parenthesis){
|
||||||
|
args = [ ]
|
||||||
|
args << capture(:basic_expression).value if capture(:basic_expression)
|
||||||
|
args += capture(:more_args).value if capture(:more_args)
|
||||||
|
args
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule call_site
|
||||||
|
(basic_expression "." name_expression argument_list space?) {
|
||||||
|
Ast::CallSiteExpression.new(capture(:name_expression).to_str ,
|
||||||
|
capture(:argument_list).value ,
|
||||||
|
capture(:basic_expression).value )
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule value_expression
|
||||||
|
call_site | basic_expression
|
||||||
|
end
|
||||||
|
|
||||||
|
rule function_definition
|
||||||
|
keyword_def name:function_name parameter_list newline expressions_end newline
|
||||||
|
end
|
||||||
|
|
||||||
|
rule parameter_list
|
||||||
|
left_parenthesis parameter_list:( name:parameter? (comma name:parameter)* ) right_parenthesis
|
||||||
|
end
|
||||||
|
|
||||||
|
rule more_typed_args
|
||||||
|
(comma typed_arg )* {
|
||||||
|
captures(:typed_arg).collect{|u| u.value }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule typed_argument_list
|
||||||
|
(left_parenthesis typed_arg? more_typed_args right_parenthesis){
|
||||||
|
args = [ ]
|
||||||
|
args << capture(:typed_arg).value if capture(:typed_arg)
|
||||||
|
args += capture(:more_typed_args).value if capture(:more_typed_args)
|
||||||
|
args
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule type
|
||||||
|
(typ:("int" | "ref") space*) { capture(:typ).to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
rule typed_arg
|
||||||
|
(type name_expression) {
|
||||||
|
Ast::TypedName.new(capture(:type).value , capture(:name_expression).value.name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule variable_definition
|
||||||
|
(typed_arg ("=" space* value_expression)?) {
|
||||||
|
type = capture(:typed_arg).value
|
||||||
|
value = capture(:value_expression) ? capture(:value_expression).value : nil
|
||||||
|
var = Ast::VariableDefinition.new(type.type , type.name , value)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule assignment
|
||||||
|
(name_expression "=" space* value_expression){
|
||||||
|
Ast::AssignmentExpression.new( capture(:name_expression).value.name , capture(:value_expression).value)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule conditional
|
||||||
|
(keyword_if left_parenthesis value_expression right_parenthesis
|
||||||
|
body
|
||||||
|
keyword_end) {
|
||||||
|
Ast::IfExpression.new( capture(:value_expression).value , capture(:body).value , nil)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule while
|
||||||
|
keyword_while left_parenthesis value_expression right_parenthesis keyword_do
|
||||||
|
body
|
||||||
|
keyword_end
|
||||||
|
end
|
||||||
|
|
||||||
|
rule return
|
||||||
|
keyword_return value_expression newline
|
||||||
|
end
|
||||||
|
|
||||||
|
rule body
|
||||||
|
(statement+){
|
||||||
|
captures(:statement).collect{|u| u.value }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rule statement
|
||||||
|
conditional | while | return | variable_definition | assignment
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
@ -1,40 +0,0 @@
|
|||||||
grammar Expression
|
|
||||||
include BasicTypes
|
|
||||||
|
|
||||||
rule more_args
|
|
||||||
(comma basic_expression )* {
|
|
||||||
captures(:basic_expression).collect{|u| u.value }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule argument_list
|
|
||||||
(left_parenthesis basic_expression? more_args right_parenthesis){
|
|
||||||
args = [ ]
|
|
||||||
args << capture(:basic_expression).value if capture(:basic_expression)
|
|
||||||
args += capture(:more_args).value if capture(:more_args)
|
|
||||||
args
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule call_site
|
|
||||||
(basic_expression "." name_expression argument_list space?) {
|
|
||||||
Ast::CallSiteExpression.new(capture(:name_expression).to_str ,
|
|
||||||
capture(:argument_list).value ,
|
|
||||||
capture(:basic_expression).value )
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule value_expression
|
|
||||||
call_site | basic_expression
|
|
||||||
end
|
|
||||||
|
|
||||||
rule function_definition
|
|
||||||
keyword_def name:function_name parameter_list newline expressions_end newline
|
|
||||||
end
|
|
||||||
|
|
||||||
rule parameter_list
|
|
||||||
left_parenthesis parameter_list:( name:parameter? (comma name:parameter)* ) right_parenthesis
|
|
||||||
end
|
|
||||||
|
|
||||||
root call_site
|
|
||||||
end
|
|
@ -1,37 +0,0 @@
|
|||||||
grammar Function
|
|
||||||
include Statement
|
|
||||||
|
|
||||||
|
|
||||||
rule more_typed_args
|
|
||||||
(comma typed_arg )* {
|
|
||||||
captures(:typed_arg).collect{|u| u.value }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule typed_argument_list
|
|
||||||
(left_parenthesis typed_arg? more_typed_args right_parenthesis){
|
|
||||||
args = [ ]
|
|
||||||
args << capture(:typed_arg).value if capture(:typed_arg)
|
|
||||||
args += capture(:more_typed_args).value if capture(:more_typed_args)
|
|
||||||
args
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule call_site
|
|
||||||
(basic_expression "." name_expression argument_list space?) {
|
|
||||||
Ast::CallSiteExpression.new(capture(:name_expression).to_str ,
|
|
||||||
capture(:argument_list).value ,
|
|
||||||
capture(:basic_expression).value )
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule function_definition
|
|
||||||
keyword_def name:function_name parameter_list newline expressions_end newline
|
|
||||||
end
|
|
||||||
|
|
||||||
rule parameter_list
|
|
||||||
left_parenthesis parameter_list:( name:parameter? (comma name:parameter)* ) right_parenthesis
|
|
||||||
end
|
|
||||||
|
|
||||||
root call_site
|
|
||||||
end
|
|
@ -5,8 +5,6 @@ module Parser
|
|||||||
|
|
||||||
# obviously a work in progress !!
|
# obviously a work in progress !!
|
||||||
|
|
||||||
Citrus.require "parser/basic"
|
Citrus.require "parser/bosl"
|
||||||
Citrus.require "parser/expression"
|
|
||||||
Citrus.require "parser/statement"
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
grammar Statement
|
|
||||||
include Expression
|
|
||||||
|
|
||||||
rule type
|
|
||||||
(typ:("int" | "ref") space*) { capture(:typ).to_s }
|
|
||||||
end
|
|
||||||
|
|
||||||
rule typed_arg
|
|
||||||
(type name_expression) {
|
|
||||||
Ast::TypedName.new(capture(:type).value , capture(:name_expression).value.name)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule variable_definition
|
|
||||||
(typed_arg ("=" space* value_expression)?) {
|
|
||||||
type = capture(:typed_arg).value
|
|
||||||
value = capture(:value_expression) ? capture(:value_expression).value : nil
|
|
||||||
var = Ast::VariableDefinition.new(type.type , type.name , value)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule assignment
|
|
||||||
(name_expression "=" space* value_expression){
|
|
||||||
Ast::AssignmentExpression.new( capture(:name_expression).value.name , capture(:value_expression).value)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule conditional
|
|
||||||
(keyword_if left_parenthesis value_expression right_parenthesis
|
|
||||||
body
|
|
||||||
keyword_end) {
|
|
||||||
Ast::IfExpression.new( capture(:value_expression).value , capture(:body).value , nil)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule while
|
|
||||||
keyword_while left_parenthesis value_expression right_parenthesis keyword_do
|
|
||||||
body
|
|
||||||
keyword_end
|
|
||||||
end
|
|
||||||
|
|
||||||
rule return
|
|
||||||
keyword_return value_expression newline
|
|
||||||
end
|
|
||||||
|
|
||||||
rule body
|
|
||||||
(statement+){
|
|
||||||
captures(:statement).collect{|u| u.value }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
rule statement
|
|
||||||
conditional | while | return | variable_definition | assignment
|
|
||||||
end
|
|
||||||
|
|
||||||
root statement
|
|
||||||
|
|
||||||
end
|
|
@ -4,46 +4,16 @@ require_relative "setup"
|
|||||||
module ParserHelper
|
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 :extend, ClassMethods #gets the method creation going
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
def setup
|
def setup
|
||||||
@parser = Keywords
|
@parser = Bosl
|
||||||
end
|
end
|
||||||
|
|
||||||
# check that @input parses correctly to @input
|
def check rule = :root
|
||||||
def check_parse
|
parse = @parser.parse(@input , :root => rule)
|
||||||
is = @parser.parse(@input , :root => @root)
|
assert_equal @input , parse
|
||||||
assert_equal @input , is
|
assert_equal @output , parse.value
|
||||||
end
|
|
||||||
|
|
||||||
# check that @input parses and transforms to @output
|
|
||||||
def check_ast
|
|
||||||
syntax = @parser.parse(@input , :root => @root)
|
|
||||||
#puts is.inspect
|
|
||||||
assert_equal @output , syntax.value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module ClassMethods
|
|
||||||
# this creates test methods dynamically. For each test_* method we create
|
|
||||||
# three test_*[ast/parse/transf] methods that in turn check the three phases.
|
|
||||||
# runnable_methods is called by minitest to determine which tests to run
|
|
||||||
def runnable_methods
|
|
||||||
tests = []
|
|
||||||
public_instance_methods(true).grep(/^test_/).map(&:to_s).each do |test|
|
|
||||||
["ast" , "parse"].each do |what|
|
|
||||||
name = "#{test}_#{what}"
|
|
||||||
tests << name
|
|
||||||
self.send(:define_method, name ) do
|
|
||||||
send(test)
|
|
||||||
send("check_#{what}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tests
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
require_relative "../setup"
|
require_relative "../parser_helper"
|
||||||
|
|
||||||
class TestBasic < MiniTest::Test
|
class TestBasic < MiniTest::Test
|
||||||
#test basics and keyword expressions. Keywords includes BasicTypes
|
#test basics and keyword expressions. Keywords includes BasicTypes
|
||||||
def setup
|
include ParserHelper
|
||||||
@parser = BasicTypes
|
|
||||||
end
|
|
||||||
|
|
||||||
def check rule = :root
|
|
||||||
parse = @parser.parse(@input , :root => rule)
|
|
||||||
assert_equal @input , parse
|
|
||||||
assert_equal @output , parse.value
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_true
|
def test_true
|
||||||
@input = 'true '
|
@input = 'true '
|
||||||
|
@ -1,39 +1,31 @@
|
|||||||
require_relative "../parser_helper"
|
require_relative "../parser_helper"
|
||||||
|
|
||||||
class TestCallSite < MiniTest::Test
|
class TestCallSite < MiniTest::Test
|
||||||
|
include ParserHelper
|
||||||
def setup
|
|
||||||
@parser = Expression
|
|
||||||
end
|
|
||||||
def check
|
|
||||||
parse = @parser.parse(@input)
|
|
||||||
assert_equal @input , parse
|
|
||||||
assert_equal @output , parse.value
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_single_self
|
def test_single_self
|
||||||
@input = 'self.foo(42)'
|
@input = 'self.foo(42)'
|
||||||
@output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)]
|
@output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)]
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_single_name
|
def test_single_name
|
||||||
@input = 'my_my.foo(42)'
|
@input = 'my_my.foo(42)'
|
||||||
@parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
|
@parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
|
||||||
@output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my"))
|
@output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my"))
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_int_receiver
|
def test_int_receiver
|
||||||
@input = '42.put()'
|
@input = '42.put()'
|
||||||
@output = Ast::CallSiteExpression.new(:put, [] ,Ast::IntegerExpression.new(42))
|
@output = Ast::CallSiteExpression.new(:put, [] ,Ast::IntegerExpression.new(42))
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_string_receiver
|
def test_string_receiver
|
||||||
@input = '"hello".puts()'
|
@input = '"hello".puts()'
|
||||||
@output = Ast::CallSiteExpression.new(:puts, [] ,Ast::StringExpression.new("hello"))
|
@output = Ast::CallSiteExpression.new(:puts, [] ,Ast::StringExpression.new("hello"))
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_call_site_2
|
def test_call_site_2
|
||||||
@ -41,7 +33,7 @@ class TestCallSite < MiniTest::Test
|
|||||||
@output = Ast::CallSiteExpression.new :baz,
|
@output = Ast::CallSiteExpression.new :baz,
|
||||||
[Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo") ] ,
|
[Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo") ] ,
|
||||||
Ast::NameExpression.new(:self)
|
Ast::NameExpression.new(:self)
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_call_site_3
|
def test_call_site_3
|
||||||
@ -51,7 +43,7 @@ class TestCallSite < MiniTest::Test
|
|||||||
Ast::NameExpression.new("foo") ,
|
Ast::NameExpression.new("foo") ,
|
||||||
Ast::NameExpression.new("bar")] ,
|
Ast::NameExpression.new("bar")] ,
|
||||||
Ast::NameExpression.new(:self)
|
Ast::NameExpression.new(:self)
|
||||||
check
|
check :call_site
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,33 +1,24 @@
|
|||||||
require_relative "../parser_helper"
|
require_relative "../parser_helper"
|
||||||
|
|
||||||
class TestConditional < MiniTest::Test
|
class TestConditional < MiniTest::Test
|
||||||
|
include ParserHelper
|
||||||
def setup
|
|
||||||
@parser = Statement
|
|
||||||
end
|
|
||||||
|
|
||||||
def check
|
|
||||||
parse = @parser.parse(@input)
|
|
||||||
assert_equal @input , parse
|
|
||||||
assert_equal @output , parse.value
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_assignment
|
def test_assignment
|
||||||
@input = "myvar = 42"
|
@input = "myvar = 42"
|
||||||
@output = Ast::AssignmentExpression.new(:myvar,Ast::IntegerExpression.new(42))
|
@output = Ast::AssignmentExpression.new(:myvar,Ast::IntegerExpression.new(42))
|
||||||
check
|
check :assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_variable_declaration
|
def test_variable_declaration
|
||||||
@input = "int myvar"
|
@input = "int myvar"
|
||||||
@output = Ast::VariableDefinition.new(:int,:myvar,nil)
|
@output = Ast::VariableDefinition.new(:int,:myvar,nil)
|
||||||
check
|
check :variable_definition
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_variable_declaration_value
|
def test_variable_declaration_value
|
||||||
@input = "int myvar = 42"
|
@input = "int myvar = 42"
|
||||||
@output = Ast::VariableDefinition.new(:int,:myvar,Ast::IntegerExpression.new(42))
|
@output = Ast::VariableDefinition.new(:int,:myvar,Ast::IntegerExpression.new(42))
|
||||||
check
|
check :variable_definition
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_if
|
def test_if
|
||||||
@ -37,7 +28,7 @@ if( 1 )
|
|||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = Ast::IfExpression.new(Ast::IntegerExpression.new(1), [Ast::VariableDefinition.new(:int,:num,Ast::IntegerExpression.new(42))],nil )
|
@output = Ast::IfExpression.new(Ast::IntegerExpression.new(1), [Ast::VariableDefinition.new(:int,:num,Ast::IntegerExpression.new(42))],nil )
|
||||||
check
|
check :conditional
|
||||||
end
|
end
|
||||||
|
|
||||||
def ttest_conditional_with_calls
|
def ttest_conditional_with_calls
|
||||||
|
Loading…
x
Reference in New Issue
Block a user