antelope 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CONTRIBUTING.md +4 -4
  4. data/GENERATORS.md +61 -19
  5. data/README.md +84 -9
  6. data/TODO.md +58 -0
  7. data/examples/deterministic.ace +21 -9
  8. data/examples/example.ace +16 -10
  9. data/examples/example.output +213 -146
  10. data/examples/simple.ace +1 -1
  11. data/lib/antelope/ace/compiler.rb +52 -15
  12. data/lib/antelope/ace/errors.rb +7 -0
  13. data/lib/antelope/ace/grammar/generation.rb +3 -3
  14. data/lib/antelope/ace/grammar/precedences.rb +5 -7
  15. data/lib/antelope/ace/grammar/productions.rb +36 -11
  16. data/lib/antelope/ace/grammar/{terminals.rb → symbols.rb} +25 -2
  17. data/lib/antelope/ace/grammar.rb +12 -3
  18. data/lib/antelope/ace/precedence.rb +4 -0
  19. data/lib/antelope/ace/scanner/argument.rb +57 -0
  20. data/lib/antelope/ace/scanner/first.rb +32 -6
  21. data/lib/antelope/ace/scanner/second.rb +23 -8
  22. data/lib/antelope/ace/scanner.rb +32 -26
  23. data/lib/antelope/ace/token.rb +21 -2
  24. data/lib/antelope/cli.rb +22 -2
  25. data/lib/antelope/generation/constructor/first.rb +1 -1
  26. data/lib/antelope/generation/constructor.rb +2 -0
  27. data/lib/antelope/generation/null.rb +13 -0
  28. data/lib/antelope/generation/recognizer/rule.rb +4 -3
  29. data/lib/antelope/generation/recognizer/state.rb +18 -3
  30. data/lib/antelope/generation/recognizer.rb +19 -24
  31. data/lib/antelope/generation/tableizer.rb +30 -2
  32. data/lib/antelope/generation.rb +1 -0
  33. data/lib/antelope/generator/base.rb +150 -13
  34. data/lib/antelope/generator/c.rb +11 -0
  35. data/lib/antelope/generator/c_header.rb +105 -0
  36. data/lib/antelope/generator/c_source.rb +39 -0
  37. data/lib/antelope/generator/null.rb +5 -0
  38. data/lib/antelope/generator/output.rb +3 -3
  39. data/lib/antelope/generator/ruby.rb +23 -5
  40. data/lib/antelope/generator/templates/c_header.ant +36 -0
  41. data/lib/antelope/generator/templates/c_source.ant +202 -0
  42. data/lib/antelope/generator/templates/output.ant +68 -0
  43. data/lib/antelope/generator/templates/ruby.ant +146 -0
  44. data/lib/antelope/generator.rb +15 -3
  45. data/lib/antelope/template/compiler.rb +78 -0
  46. data/lib/antelope/template/errors.rb +9 -0
  47. data/lib/antelope/template/scanner.rb +111 -0
  48. data/lib/antelope/template.rb +60 -0
  49. data/lib/antelope/version.rb +1 -1
  50. data/lib/antelope.rb +1 -0
  51. data/spec/antelope/template_spec.rb +39 -0
  52. data/subl/Ace (Ruby).JSON-tmLanguage +94 -0
  53. data/subl/Ace (Ruby).tmLanguage +153 -0
  54. metadata +21 -8
  55. data/examples/deterministic.output +0 -131
  56. data/examples/simple.output +0 -121
  57. data/lib/antelope/generator/templates/output.erb +0 -56
  58. data/lib/antelope/generator/templates/ruby.erb +0 -63
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a92fce8aab3e6c5107252ea4a33c51f7da399473
4
- data.tar.gz: 6833313957e6ae84009644b24ce78093bf049285
3
+ metadata.gz: 16bfd59509232d2d3ac2ae7a2fd3be25254836da
4
+ data.tar.gz: 28f7a1a19695c03a3f22e0d4b4bcf3ddea518fd4
5
5
  SHA512:
6
- metadata.gz: 0904f4b66bbb6468462420b81bdcd3d711291137f9ca54232bf3856dc8f1fafe6d208186c4db6d2aeb74af7b83e3fd74b2877a159c80767eac55325fdee5333b
7
- data.tar.gz: c75fa1bc293beb80a2e45fe971c2db0330064919954393121a72fae89872c5a8e1d93f99eebfc247e7f879b25c2dcf86d3ad01d4ba92982f9eed9ffdfbb5a411
6
+ metadata.gz: c89393e3efb8f38b932aefd49a5b7800879ca7d9a4bcbdc4a23f075f6bae1f5eb758904b6c602856834bb281ebf910ad0ffeb4af4fc2f6212c9813af121253e0
7
+ data.tar.gz: 62bebf9be801f6408ed4603e401aab55d7e38224dd428073874255ba20e3b1892b9f79e5abb56a4a5bd9de8bbb55501f0c6854a2261ea99526e6b79f420eac67
data/.yardopts CHANGED
@@ -3,3 +3,5 @@
3
3
  -m markdown
4
4
  -
5
5
  LICENSE.txt
6
+ CONTRIBUTING.md
7
+ GENERATORS.md
data/CONTRIBUTING.md CHANGED
@@ -6,11 +6,11 @@ First and foremost, **thank you**! Contributing to _Antelope_ is great! There a
6
6
 
7
7
  1. Fork the repository ([medcat/antelope])
8
8
  2. Create a new branch for your feature (something like `my-feature`)
9
- 3. Make yo' changes
10
- 4. Commit yo' changes
9
+ 3. Make your changes
10
+ 4. Commit your changes
11
11
  5. if(notDone) goto 3;
12
- 6. Push yo' changes
13
- 7. Make yo' pull request
12
+ 6. Push your changes
13
+ 7. Make a pull request
14
14
 
15
15
  Creating a new branch is a _really, really_ good idea; it keeps things neat in the world of git. When you make the pull request, any commits you make to the merging branch are added to the pull request. Also, _please_ make sure you describe the pull request, and what it does, and why it's needed.
16
16
 
data/GENERATORS.md CHANGED
@@ -10,11 +10,11 @@ class MyGenerator < Antelope::Generator::Base
10
10
  end
11
11
  ```
12
12
 
13
- Next, you'll want to define a `generate` method on your generator that takes no arguments. This is used internally by _Antelope_ to actually have your generator perform its generation. In the case of this generator, we'll have it copy over a template (after running ERb over it).
13
+ Next, you'll want to define a `generate` method on your generator that takes no arguments. This is used internally by _Antelope_ to actually have your generator perform its generation. In the case of this generator, we'll have it copy over a template (after running the templating generator over it over it).
14
14
 
15
15
  ```Ruby
16
16
  class MyGenerator < Antelope::Generator::Base
17
-
17
+
18
18
  def generate
19
19
  template "my_template", "#{file}.my_file"
20
20
  end
@@ -25,7 +25,7 @@ end
25
25
 
26
26
  ```Ruby
27
27
  class MyGenerator < Antelope::Generator::Base
28
-
28
+
29
29
  def self.source_root
30
30
  Pathname.new("/path/to/source")
31
31
  end
@@ -39,15 +39,15 @@ end
39
39
  In the template, the code is run in the context of the instance of the class, so you have access to instance variables and methods as if you were defining a method on the class:
40
40
 
41
41
  ```
42
- % table.each_with_index do |hash, i|
43
- state <%= i %>:
44
- % hash.each do |token, action|
45
- for <%= token %>, I'll <%= action[0] %> <%= action[1] %>
46
- % end
47
- % end
42
+ {{ table.each_with_index do |hash, i| }}
43
+ state {{= i }}:
44
+ {{ hash.each do |token, action| }}
45
+ for {{= token }}, I'll {{= action[0] }} {{= action[1] }}
46
+ {{ end }}
47
+ {{ end }}
48
48
  ```
49
49
 
50
- _Note: in templates, the ERb syntax allows lines starting with `%` to be interpreted as ruby; this helps remove unwanted line space._
50
+ _Note: in templates, blocks that start at the beginning of a line and end at the end of a line do not produce any whitespace._
51
51
 
52
52
  `table` here is defined on the base class, and we're iterating over all of the values of it.
53
53
 
@@ -60,23 +60,65 @@ The finialized product:
60
60
  class MyGenerator < Antelope::Generator::Base
61
61
 
62
62
  register_as "my_generator"
63
-
63
+
64
64
  def self.source_root
65
65
  Pathname.new("/path/to/source")
66
66
  end
67
67
 
68
68
  def generate
69
- template "my_template", "#{file}.my_file"
69
+ template "my_template.erb", "#{file}.my_file"
70
70
  end
71
71
  end
72
72
  ```
73
73
 
74
74
  ```
75
- # my_template.erb
76
- % table.each_with_index do |hash, i|
77
- state <%= i %>:
78
- % hash.each do |token, action|
79
- for <%= token %>, I'll <%= action[0] %> <%= action[1] %>
80
- % end
81
- % end
75
+ # my_template.ant
76
+ {{ table.each_with_index do |hash, i| }}
77
+ state {{= i }}:
78
+ {{ hash.each do |token, action| }}
79
+ for {{= token }}, I'll {{= action[0] }} {{= action[1] }}
80
+ {{ end }}
81
+ {{ end }}
82
+ ```
83
+
84
+ ## Bundling
85
+
86
+ If you want to bundle a few generators together such that the bundle is generated together, you can use an `Antelope::Generator::Group`. This would be useful for something like a C language generator, which may need to generate both a header and a source file:
87
+
88
+ ```Ruby
89
+ class CHeader < Antelope::Generator::Base
90
+ # ...
91
+ end
92
+
93
+ class CSource < Antelope::Generator::Base
94
+ # ...
95
+ end
96
+
97
+
98
+ class C < Antelope::Generator::Group
99
+ register_generator CHeader, "c-header"
100
+ register_generator CSource, "c-source"
101
+ end
82
102
  ```
103
+
104
+ The `register_generator` takes a generator class and a name for the generator, and adds the generator to the list of generators on the receiver (in this case, the `C` class). Now, when `C#generate` is run, it will run both `CHeader#generate` and `CSource#generate`.
105
+
106
+ ## Using Compiler Directives
107
+
108
+ Directives are statements that are used in Ace files in order to pass information to _Antelope_. They normally follow the syntax `%<directive name> [directive arguments]*`. See [the Ace file format](http://rubydoc.info/github/medcat/antelope/Antelope/Ace) for more information about directives.
109
+
110
+ In some cases, like in the [Ruby generator][Ruby], options from the Ace file are needed for generation. In the case of the Ruby generator, we need the error class that the developer wants the generator to use; and we reference it through the `ruby.error-class` directive. In order to define directives that can be used in custom generators, you just need to add a few lines:
111
+
112
+ ```Ruby
113
+ class MyGenerator < Antelope::Generator::Base
114
+
115
+ has_directive "my-generator.some-value", Boolean
116
+
117
+ end
118
+ ```
119
+
120
+ In this example, we define a directive named `my-generator.some-value`; this directive is eventually coerced into a `true`/`false` value. In order to actually use the value of the directive, in either the template or a method on the generator, you can reference `directives["my-generator.some-value"]`, which will be `nil` (it wasn't defined), `true` (it was defined, with any arguments), or `false` (it was explicitly defined with one argument, `"false"`). Some other values you can pass in place of `Boolean` would be `:single` (or `:one`), which only gives the first argument passed to the directive; an `Array` of types, which would coerce each argument into its corresponding element of the array; `Array`, which will give an array of the given arguments; `String`, which gives a string representation of the first argument; any `Numeric` subclass, which would coerce the first argument into an integer; `Float`, which would coerce the first argument into a float; any class, which would be instantized with the arguments to the directive. Any other values would yield an error.
121
+
122
+ It is recommended that you namespace directives that only your generator would use, using dashed syntax, like in our example above. However, some directives are not namespaced, or are not namespaced under a generator; these may be used by any generator. It is also recommended that you declare every directive that you use.
123
+
124
+ [Ruby]: http://rubydoc.info/github/medcat/antelope/Antelope/Generator/Ruby
data/README.md CHANGED
@@ -1,24 +1,94 @@
1
1
  # Antelope
2
2
 
3
- TODO: Write a gem description
3
+ _Antelope_ is a parser generator that can generate parsers for any language*. In the sense of actually creating a parser, it works kind of like [_Bison_][bison] - you give it an input file, say, `language.ace`, and it generates a parser for it, in, say, `language.rb`. Only, instead of _Bison_'s support only for C, C++, and Java, _Antelope_ is meant to generate parsers for multiple languages. _Antelope_ is also written in Ruby for understandability.
4
+
5
+ Enough about that, though, let's get into _Antelope_.
4
6
 
5
7
  ## Installation
6
8
 
7
- Add this line to your application's Gemfile:
9
+ Since you'll only typically use _Antelope_ from the command line, I suggest you install it like so:
10
+
11
+ $ gem install antelope
8
12
 
9
- gem 'antelope'
13
+ If, however, you plan on using it in an application, or need it as a part of a library, you can add `gem "antelope"` to your Gemfile.
10
14
 
11
- And then execute:
15
+ ## Usage
12
16
 
13
- $ bundle
17
+ _Antelope_ is fairly simple to use; you define an `.ace` file, compile it, and use the proper API for the generated language.
14
18
 
15
- Or install it yourself as:
19
+ ### How Antelope Works
16
20
 
17
- $ gem install antelope
21
+ Before getting into Ace files, however, you have to understand how _Antelope_ works. _Antelope_ generates a LALR(1) parser, like _Bison_; for your benefit, however, there are some terms here to understand:
18
22
 
19
- ## Usage
23
+ - LL: A type of parser. If followed by parenthesis, the number (or letter) in the parenthesis denotes the number of tokens of lookahead; i.e., LL(0) has 0 tokens of lookahead. Standing for **L** eft to Right, **L** eftmost Derivation, these tend to be handwritten as Recursive Decent parsers. LL parsers can be represented normally by a set of _productions_. LL parsers are _Top-Down parsers_, meaning they start with only the _Starting symbol_ and try to match the input. A look at an LL parser is given [here][ll-parser]; check out [this post][tumblr-ll-parser] for more information about LL parsers. _Antelope_ does not generate LL parsers.
24
+ - Production: In parsing, a production associates a _nonterminal_ with a _string_ of _nonterminals_ and _terminals_. It is said that the string of nonterminals and terminals _reduces to_ the nonterminal. Productions take the form of `A -> y`, with _A_ being the left hand side (and the _nonterminal_), and _y_ being the string.
25
+ - Starting symbol: In parsing, it is the _nonterminal_ that is used to represent any kind of valid input.
26
+ - Symbol: A _nonterminal_ or a _terminal_.
27
+ - Nonterminal: In parsing, a nonterminal is an abstraction used to represent any number of _strings_ of _nonterminals_ and _terminals_.
28
+ - String: In parsing, an ordered set of _symbols_.
29
+ - Terminal: In parsing, it is a concrete value given by the lexer.
30
+ - LR: A family of types of parsers. If followed by parenthesis, the number (or letter) in the parenthesis denotes the number of tokens of lookahead; i.e., LR(0) has 0 tokens of lookahead. Standing for **L** eft to Right, **R** ightmost Derivation, they tend to be more complicated than their LL brethren. LR parsers work by starting with the entire input and finding _Handles_ from that input, eventually ending up at the _Starting symbol_. LR parsers typically do this by splitting the input into two parts: the _stack_, and the _input_. LR(0), LR(1), SLR(1), and LALR(1) are all examples of LR parsers.
31
+ - Handle: In a LR parser, it is the _Leftmost complete cluster of leaf nodes_ (in a representative AST). When a handle is found, a _reduction_ is performed.
32
+ - Stack: Initially empty, it can contain any _symbol_, and is primarily used to represent what the parser has seen. Finding handles will purely occur at the top of the stack.
33
+ - Reduction/Reduce: In a LR parser, this is an action corresponding to replacing the right side of a _production_ with its left side. This purely occurs at the top of the _stack_, and correlates to finding a _Handle_.
34
+ - Input: Initially containing the full input, it can contain only _terminals_; it primarily contains what the parser has yet to see.
35
+ - LR(0): In parsing, it is a type of LR parser that uses no lookahead. It essentially uses a deterministic finite automaton to find _possible_ handles. It does no checking to make sure that the _possible_ handles are legitimate.
36
+ - SLR(1): A part of the LR family of parsers, it upgrades LR(0) by checking to make sure that the reduction that it will make (as a part of finding a handle) is valid in the context; basically, for every reduction that it can make, it defines a set of terminals that can _FOLLOW_ the corresponding nonterminal.
37
+ - FOLLOW(A) set: In parsing, it defines a set of terminals that can _follow_ the nonterminal _A_ anywhere in the grammar.
38
+ - LALR(1): A part of the LR family of parsers, it upgrades SLR by using a more precise _FOLLOW_ set, called _LA_.
39
+ - LA set: LA(q, A -> y) = { t | S =>* _aAtw_ and _ay_ reaches _q_ }
40
+ - Panic mode: In parsing, this is the mode that a parser can go in for recovery, if it encounters a terminal that it was not expecting. In panic mode, the parser pops terminals off of the input until it reaches a valid _synchronization token_. In order to utilize panic mode, at least one production must have the special _error_ terminal in it. If the parser encounters an error, it will attempt to find a production it can use to resynchronize; if it cannot resynchronize, it will error. It then attempts to resynchronize by continuously pop terminals off of the input and discarding them, attempting to find a synchronization token. A synchronization token is a token that follows an _error_ terminal.
41
+ - Shift/reduce conflict: This occurs when the parser is unable to decide if it should shift the next token over from the input to the stack, or to reduce the top token on the stack. If a shift/reduce conflict cannot be solved by changing the grammar, then precedence rules may be used (see `examples/example.ace`).
42
+ - Reduce/reduce conflict: This occurs when the parser is unable to decide which production to reduce. This cannot be solved by precedence.
43
+ - Precedence: In some grammars, the _Antelope_ runs into _Shift/reduce conflicts_ when attempting to construct a parser. To resolve these conflicts, _Antelope_ provides precedence declarations. Precedence is separated into levels, which each have a type; levels can be _left-associative_, _right-associative_, or _non-associative_. The higher the level, the higher the precedence. Think of the Order of Operations here; the operations multiply and divide are left associative, and on a higher level than add and subtract, which are still left-associative:
44
+
45
+ MULTIPLY, DIVIDE (left-associative)
46
+ ADD, SUBTRACT (left-associative)
47
+
48
+ Exponentiation, however, is right-associative, and is higher than MULTIPLY or DIVIDE; basically, `2**2**2` would be parsed as `2**(2**2)`, instead of the left-associative `(2**2)**2`. For an example of a grammar that uses precedence, see `examples/example.ace`.
49
+
50
+ ### Defining the Ace file
51
+
52
+ The Ace file format is very similar to _Bison_'s _y_ files; this was intentional, to make transitions between the two easy. The Ace file should be formatted like so:
53
+
54
+ ```
55
+ <directives>
56
+ %%
57
+ <rules>
58
+ %%
59
+ <code>
60
+ ```
61
+
62
+ Both `%%` (internally called _content boundaries_) are required; the minimum file that is _technically_ accepted by _Antelope_ is therefore two content boundaries separated by a newline.
20
63
 
21
- TODO: Write usage instructions here
64
+ In the `<directives>` section, there can be any number and combinations of _code blocks_ and _directives_. _Code blocks_ are blocks of code delimited by `%{` and `%}`, with the ending delimiter on its own line. These are copied into the output of the file directly. _Directives_ tell _Antelope_ information about the grammar. An example directive would be the `token` or `terminal` directive; this lets _Antelope_ know that a terminal by the given name exists. Directives take the form `%<name> [<value>]*`, with `<name>` being the directive name, and `<value>` being a string delimited by braces, angle brackets, quotes, or nothing at all. An example of a directive would be `%token ADD "+"`. The available directives are determined by the code generators available to _Antelope_ at the time that the Ace file is being compiled. Some directives, however, are always available:
65
+
66
+ - `require` (1 argument): This makes _Antelope_ check its version against the first argument to this. If the versions do _not_ match, _Antelope_ will raise an error and fail to parse the file. It is recommended to at least require the minor version of _Antelope_ (i.e. `%require "~> 0.1").
67
+ - `token`, `terminal` (1-2 arguments): Defines a terminal. The first argument defines its name; the second argument defines its value. Its value isn't used anywhere but the `.output` file, to make it easier to read.
68
+ - `left`, `right`, `nonassoc` (1+ arguments): Defines a precedence level, and sets the type of the level based on the directive name used.
69
+ - `type`: The code generator to use. Currently, the possible values for this can be `null`, `ruby`, and `output`.
70
+ - `define` (1+ arguments): Sets a key to a value. This would do the exact same thing that using the key as a directive would do, i.e. `%define something "value"` does the same thing as `%something "value"`. _(note: This is not entirely true. If the key were one of the above, it would most likely raise an error, complaining that there is no directive named that.)_
71
+ - `panic-mode` (0-1 arguments): Enables/disables panic mode being put in the output code. Not included by default, but should be.
72
+
73
+ In the `<rules>` section, there can be any number of rules (which are definitions for productions). Rules have this syntax:
74
+
75
+ ```
76
+ <head>: <body> ["|" <body>]* [";"]
77
+ ```
78
+
79
+ With `<head>` being the nonterminal that the production(s) reduce to, and `<body>` being one or more symbols followed by an optional block that is executed when is a reduction is made using that production. A semicolon terminating the rule is optional. Rules are what make up the grammar. `error`, `nothing`, and `ε` are all special symbols; the first one defines the special `error` terminal (used for panic mode, ignored otherwise), whereas the second two are used to literally mean nothing (i.e., the rule reduces to nothing). It is not always a good idea to use the `nothing` symbol, since most rules can be written without it.
80
+
81
+ In the `<code>` section, custom code used to wrap the generated parser can be placed. In order to embed the generated parser, you must place `%{write}` where you want the generated parser.
82
+
83
+ ### Compiling the Ace file
84
+
85
+ Compiling the Ace file is somewhat straightforward; `antelope compile /path/to/file.ace` will cover most use cases. If you want to override the type in the Ace file, you can use the `--type=` command option. If it is giving an error, and you're not sure what's causing it, you can use the `--verbose` command option to see a backtrace. If there are any conflicts in the
86
+
87
+ By default, _Antelope_ always includes the `Output` generator as a part of the output. This means that an `.output` file will always be generated along with any other files. The `.output` file contains information about the parser, like the productions that were used, precedence levels, states, and lookahead sets.
88
+
89
+ ### Language API
90
+
91
+ todo.
22
92
 
23
93
  ## Contributing
24
94
 
@@ -27,3 +97,8 @@ TODO: Write usage instructions here
27
97
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
98
  4. Push to the branch (`git push origin my-new-feature`)
29
99
  5. Create a new Pull Request
100
+
101
+ * Only if there's a generator for it.
102
+ [bison]: http://www.gnu.org/software/bison/
103
+ [ll-parser]: http://i.imgur.com/XhJKrDW.png
104
+ [tumblr-ll-parser]: http://redjazz96.tumblr.com/post/88336053195/what-antelope-does-and-what-i-hope-it-will-do-part
data/TODO.md ADDED
@@ -0,0 +1,58 @@
1
+ # Todo
2
+
3
+ - Documentation
4
+ - Language API files
5
+
6
+ ## Undocumented:
7
+
8
+ - `Antelope::Ace::Precedence#to_s`
9
+ - `Antelope::Ace::Scanner::Argument#method_missing`
10
+ - `Antelope::Ace::Scanner::Argument#==`
11
+ - `Antelope::Ace::Scanner::Argument`
12
+ - `Antelope::Ace::Scanner::First#scan_first_directive_arguments`
13
+ - `Antelope::Ace::Token#inspect`
14
+ - `Antelope::CLI`
15
+ - `Antelope::CLI#compile_file`
16
+ - `Antelope::CLI#compile`
17
+ - `Antelope::Generation::Recognizer::State#===`
18
+ - `Antelope::Generator#directives`
19
+ - `Antelope::Generator::Base.register_as`
20
+ - `Antelope::Generator::Base::Boolean`
21
+ - `Antelope::Generator::C`
22
+ - `Antelope::Generator::CHeader#guard_name`
23
+ - `Antelope::Generator::CHeader`
24
+ - `Antelope::Generator::CHeader#generate`
25
+ - `Antelope::Generator::CHeader#namespace`
26
+ - `Antelope::Generator::CSource`
27
+ - `Antelope::Generator::CSource#namespace`
28
+ - `Antelope::Generator::CSource#guard_name`
29
+ - `Antelope::Generator::CSource#generate`
30
+ - `Antelope::Generator::Output#unused_symbols`
31
+ - `Antelope::Generator::Ruby#error_class`
32
+ - `Antelope::Template#parse`
33
+ - `Antelope::Template::NO_SOURCE`
34
+ - `Antelope::Template`
35
+ - `Antelope::Template#determine_source`
36
+ - `Antelope::Template#normalize_input`
37
+ - `Antelope::Template#result`
38
+ - `Antelope::Template::Compiler#parse_comment_tag`
39
+ - `Antelope::Template::Compiler`
40
+ - `Antelope::Template::Compiler#parse_tag`
41
+ - `Antelope::Template::Compiler#parse_output_tag`
42
+ - `Antelope::Template::Compiler#compile`
43
+ - `Antelope::Template::Compiler#parse_text`
44
+ - `Antelope::Template::Compiler#merge_text_tokens`
45
+ - `Antelope::Template::Error`
46
+ - `Antelope::Template::NoTokenError`
47
+ - `Antelope::Template::SyntaxError`
48
+ - `Antelope::Template::Scanner#scan_ending`
49
+ - `Antelope::Template::Scanner#scan_until_brace`
50
+ - `Antelope::Template::Scanner#scan_text`
51
+ - `Antelope::Template::Scanner#scan_everything`
52
+ - `Antelope::Template::Scanner#scan_tag_type`
53
+ - `Antelope::Template::Scanner#scan_tag_contents`
54
+ - `Antelope::Template::Scanner#scan_tag`
55
+ - `Antelope::Template::Scanner#scan_escaped`
56
+ - `Antelope::Template::Scanner`
57
+ - `Antelope::Template::Scanner#scan`
58
+
@@ -1,20 +1,32 @@
1
1
  %require "~> 0.1"
2
- %type "ruby"
2
+ %generator "ruby"
3
3
 
4
- %terminal NUMBER
5
- %terminal SEMICOLON ";"
6
- %terminal ADD "+"
7
- %terminal LPAREN "("
8
- %terminal RPAREN ")"
4
+ %define api.push-pull pull
5
+ %define panic-mode true
6
+ %token <lex> NUMBER
7
+ %token <lex> SEMICOLON ";"
8
+ %token <lex> ADD "+"
9
+ %token <lex> LPAREN "("
10
+ %token <lex> RPAREN ")"
11
+
12
+ %type <node> s e t
13
+
14
+ %null.data api.prefix "antelope_"
15
+ %union {
16
+ struct slip_parser_node* node;
17
+ struct slip_lex_token* lex;
18
+ struct slip_parser_list* list;
19
+ }
9
20
 
10
21
  %%
11
22
 
12
23
  s: e
13
- e: t SEMICOLON
14
- | t ADD e
24
+ e: t[a] SEMICOLON[b] { $$ = $1 }
25
+ | t[a] ADD[b] e[c] { $$ = $1 + $2 }
26
+ | error[a]
15
27
 
16
28
  t: NUMBER
17
- | LPAREN e RPAREN
29
+ | LPAREN e RPAREN { $$ = $2 }
18
30
 
19
31
  %%
20
32
 
data/examples/example.ace CHANGED
@@ -1,27 +1,31 @@
1
1
  %require "~> 0.1"
2
- %type "ruby"
2
+ %generator "ruby"
3
3
 
4
+ %null.data ruby.error-class { SyntaxError }
5
+ %panic-mode true
4
6
  %terminal NUMBER
5
7
  %terminal MULTIPLY "*"
8
+ %terminal EXPONENTIATE "^"
6
9
  %terminal DIVIDE "/"
7
10
  %terminal ADD "+"
8
11
  %terminal SUBTRACT "-"
9
12
  %terminal LPAREN "("
10
13
  %terminal RPAREN ")"
11
14
 
12
- %nonassoc LPAREN RPAREN
15
+ %right EXPONENTIATE
13
16
  %left MULTIPLY DIVIDE
14
17
  %left ADD SUBTRACT
15
18
 
16
19
  %%
17
20
 
18
- expression: NUMBER { |a| a[1] }
19
- | expression ADD expression { |a, _, b| a + b }
20
- | expression SUBTRACT expression { |a, _, b| a - b }
21
- | expression MULTIPLY expression { |a, _, b| a * b }
22
- | expression DIVIDE expression { |a, _, b| a / b }
23
- | LPAREN expression RPAREN { |_, a, _| a }
24
- | LPAREN error RPAREN
21
+ expression: NUMBER { |a| a[1] }
22
+ | expression EXPONENTIATE expression { |a, _, b| a** b }
23
+ | expression ADD expression { |a, _, b| a + b }
24
+ | expression SUBTRACT expression { |a, _, b| a - b }
25
+ | expression MULTIPLY expression { |a, _, b| a * b }
26
+ | expression DIVIDE expression { |a, _, b| a / b }
27
+ | LPAREN expression RPAREN { |_, a, _| a }
28
+ | LPAREN error RPAREN { |_, e, _| e[1] }
25
29
 
26
30
  %%
27
31
 
@@ -34,9 +38,11 @@ class ExampleParser
34
38
  end
35
39
 
36
40
  input = [
41
+ [:LPAREN],
37
42
  [:NUMBER, 2],
38
43
  [:ADD],
39
- [:NUMBER, 2],
44
+ [:ADD, 2],
45
+ [:RPAREN],
40
46
  [:MULTIPLY],
41
47
  [:NUMBER, 3]
42
48
  ]