93 lines
1.7 KiB
Plaintext
93 lines
1.7 KiB
Plaintext
|
|
grammar BasicTypes
|
|
|
|
# space really is just space. ruby is newline sensitive, so there is more whitespace footwork
|
|
# rule of thumb is that anything eats space behind it, but only space, no newlines
|
|
rule space [ \t]* end
|
|
|
|
rule linebreak "\n" end
|
|
|
|
rule comment
|
|
"#" (/.*/ !linebreak) linebreak
|
|
end
|
|
|
|
rule dot '.' end
|
|
|
|
## Lexical syntax
|
|
|
|
rule number
|
|
float | integer
|
|
end
|
|
|
|
rule float
|
|
(digits '.' digits space*) { to_str.to_f }
|
|
end
|
|
|
|
rule integer
|
|
(digits space*) { to_str.to_i }
|
|
end
|
|
|
|
rule digits
|
|
[0-9]+ ('_' [0-9]+)* # Numbers may contain underscores.
|
|
end
|
|
|
|
rule lparen '(' space* end
|
|
rule rparen ')' space* end
|
|
|
|
|
|
# Hierarchical syntax
|
|
|
|
rule term
|
|
additive | factor
|
|
end
|
|
|
|
rule additive
|
|
(factor operator:('+' | '-') space* term) {
|
|
capture(:factor).value.send(capture(:operator).to_s, capture(:term).value)
|
|
}
|
|
end
|
|
|
|
rule factor
|
|
multiplicative | prefix
|
|
end
|
|
|
|
rule multiplicative
|
|
(prefix operator:('*' | '/' | '%') space* factor) {
|
|
capture(:prefix).value.send(capture(:operator).to_s, capture(:factor).value)
|
|
}
|
|
end
|
|
|
|
rule prefix
|
|
prefixed | exponent
|
|
end
|
|
|
|
rule prefixed
|
|
(operator:('-' | '+' | '~') space* prefix) {
|
|
s = capture(:operator).to_s
|
|
s += '@' unless s == '~' # Unary + and - require an @.
|
|
capture(:prefix).value.send(s)
|
|
}
|
|
end
|
|
|
|
rule exponent
|
|
exponential | primary
|
|
end
|
|
|
|
rule exponential
|
|
(primary operator:'**' space* prefix) {
|
|
capture(:primary).value.send(capture(:operator).to_s, capture(:prefix).value)
|
|
}
|
|
end
|
|
|
|
rule primary
|
|
group | number
|
|
end
|
|
|
|
rule group
|
|
(lparen term rparen) {
|
|
capture(:term).value
|
|
}
|
|
end
|
|
|
|
end
|