This commit is contained in:
Torsten Ruger 2015-05-01 16:26:26 +03:00
parent 6afd692255
commit 4ee470ff93
3 changed files with 21 additions and 21 deletions

View File

@ -2,7 +2,7 @@
The parser part of salama is now a standalone gem. It parses ruby using Parslet and no other dependencies.
This is interesing if you want to generate executable code, like salama, but also for other things, like code analysis.
This is interesting if you want to generate executable code, like salama, but also for other things, like code analysis.
Also it is very educational, as it is very readable code, and not too much of it.
@ -11,9 +11,10 @@ It looks into it's salama ball and all it sees is red. A red salama . . . ruby,
### Parser
The main parser per se is in parser/salama , but it just pulls in all the parts.
The main parser per se is in parser/salama , but it just pulls in all the parts.
All the other files are ruby modules representing aspects of the parser. Most names are quite self explanitory, but here is a list:
All the other files are ruby modules representing aspects of the parser.
Most names are quite self explanatory, but here is a list:
- basic_type defines just that. Strings, symbols, integers, floats , also comments and space
- call_site is a function call. May be qualified, but currently must still have braches
@ -42,19 +43,19 @@ The functionality that is in there is mainly to do with testing. Equality is def
Parslet is really great in that it:
- does not generate code but instead gives a clean dsl to define a grammar
- uses ruby modules so one can split the grammars up
- has support for binary operators with presedence and binding
- has a seperate tranform stage to generate an ast layer
- has support for binary operators with precedence and binding
- has a separate transform stage to generate an ast layer
Especially the last point is great. Since it is seperate it does not clutter up the actual grammar.
Especially the last point is great. Since it is separate it does not clutter up the actual grammar.
And it can generate a layer that has no links to the actual parser anymore, thus saving/automating
a complete tranformation process.
a complete transformation process.
### Todo
A random list of things left for the future
- extract commonality of function call/definition,array, hash and multi assignment comma lists
- break and next
- break and next
- blocks
- more loops, i'm not even sure what ruby supports
- ifs without else, also elsif
@ -104,4 +105,4 @@ N A M Operator(s) Description
1 N N defined? test variable definition and type
1 R N not boolean NOT (low precedence)
2 L N and or boolean AND, boolean OR (low precedence)
2 N N if unless while until conditional and loop modifiers
2 N N if unless while until conditional and loop modifiers

View File

@ -1,7 +1,7 @@
module Parser
# Tokens are single or double character combinations with "meaning"
# braces, comman, point, questionmark , quotes, that kind of thing
# operator symbols are seperate in Opreators
# operator symbols are separate in Opreators
module Tokens
include Parslet
rule(:left_parenthesis) { str('(') >> space? }

View File

@ -4,21 +4,21 @@ To run all tests, type
ruby test/test_all.rb
to run just a single, replace all with what you want to test. Minitest accept a -n option to run just a single test. So while developing i often write things like
to run just a single, replace all with what you want to test. Minitest accept a -n option to run just a single test. So while developing i often write things like
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
functions per case. Your options are _parse , _transform , or if it's really bad, _ast (this should really work when the previous two work)
Notice tough the "_parse" at the end, while you will find no such function. The Magic (explained below) renerates 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
Currently we have two directories for test.
Currently we have two directories for test.
- unit tests map to parser modules and specify the parser rule they test
- root test test much of the same functionality, but as root (rule) tests.
- root test test much of the same functionality, but as root (rule) tests.
The root tests need to be seperate to check if seperate rules interfere with each other.
The root tests need to be separate to check if separate rules interfere with each other.
Apart from just plain more tests, two additional directories are planned. One is larger tests and the other is failing tests.
@ -28,7 +28,7 @@ Parsing is a two step process with parslet:
- 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)
A test tests both phases seperately and again together.
A test tests both phases separately and again together.
Each test must thus specify (as instance variables):
- the string input
- the parse output
@ -37,7 +37,7 @@ Each test must thus specify (as instance variables):
### Magic
Test are grouped by functionality into cases (classes) and define methods test_*
Test cases must include ParserHelper, which includes the magic to write the 3 test methods for each
Test cases must include ParserHelper, which includes the magic to write the 3 test methods for each
test method. See test_basic for easy example.
Example:
@ -53,6 +53,5 @@ The first three lines define the data as described above.
The last line tells the parser what to parse. This is off couse only needed when a non-root rule is tested
and should be left out if possible.
As can be seen, there are no asserts. All asserting is done by the created methods, which call
As can be seen, there are no asserts. All asserting is done by the created methods, which call
the check_* methods in helper.