Last active
January 3, 2016 10:39
-
-
Save takahashim/8451126 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% name = ReVIEW::Compiler::Literals | |
%% header { | |
## | |
# Provides Literals appropriate for your ruby version. | |
#-- | |
# This set of literals is for Ruby 1.8 regular expressions. | |
} | |
Alphanumeric = /[0-9A-Za-z\200-\377]/n | |
AlphanumericAscii = /[A-Za-z0-9]/ | |
LowerAlphabetAscii = /[a-z]/ | |
Digit = /[0-9]/ | |
BOM = "\357\273\277" | |
Newline = /\n|\r\n?/ | |
NonAlphanumeric = /[\000-\057\072-\100\133-\140\173-\177]/n | |
Spacechar = / |\t/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% name = ReVIEW::Compiler::Literals | |
%% header { | |
# coding: UTF-8 | |
## | |
#-- | |
# This set of literals is for Ruby 1.9 regular expressions and gives full | |
# unicode support. | |
# | |
# Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric | |
# characters, newlines and spaces. | |
} | |
Alphanumeric = /\p{Word}/ | |
AlphanumericAscii = /[A-Za-z0-9]/ | |
LowerAlphabetAscii = /[a-z]/ | |
Digit = /[0-9]/ | |
BOM = "\uFEFF" | |
Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ | |
NonAlphanumeric = /\p{^Word}/ | |
Spacechar = /\t|\p{Zs}/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% name = ReVIEW::Compiler | |
%% { | |
if RUBY_VERSION > '1.9' then | |
require_relative 'literals_1_9.kpeg' | |
else | |
require_relative 'literals_1_8.kpeg' | |
end | |
## | |
# Creates extension methods for the `name` extension to enable and disable | |
# the extension and to query if they are active. | |
attr_reader :strategy | |
class SyntaxElement | |
def initialize(name, type, argc, &block) | |
@name = name | |
@type = type | |
@argc_spec = argc | |
@checker = block | |
end | |
attr_reader :name | |
def check_args(args) | |
unless @argc_spec === args.size | |
raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})" | |
end | |
@checker.call(*args) if @checker | |
end | |
def min_argc | |
case @argc_spec | |
when Range then @argc_spec.begin | |
when Integer then @argc_spec | |
else | |
raise TypeError, "argc_spec is not Range/Integer: #{inspect()}" | |
end | |
end | |
def block_required? | |
@type == :block | |
end | |
def block_allowed? | |
@type == :block or @type == :optional | |
end | |
end | |
SYNTAX = {} | |
def self.defblock(name, argc, optional = false, &block) | |
defsyntax name, (optional ? :optional : :block), argc, &block | |
end | |
def self.defsingle(name, argc, &block) | |
defsyntax name, :line, argc, &block | |
end | |
def self.defsyntax(name, type, argc, &block) | |
SYNTAX[name] = SyntaxElement.new(name, type, argc, &block) | |
end | |
def syntax_defined?(name) | |
SYNTAX.key?(name.to_sym) | |
end | |
def syntax_descriptor(name) | |
SYNTAX[name.to_sym] | |
end | |
class InlineSyntaxElement | |
def initialize(name) | |
@name = name | |
end | |
attr_reader :name | |
end | |
INLINE = {} | |
def self.definline(name) | |
INLINE[name] = InlineSyntaxElement.new(name) | |
end | |
def inline_defined?(name) | |
INLINE.key?(name.to_sym) | |
end | |
defblock :read, 0 | |
defblock :lead, 0 | |
defblock :list, 2 | |
defblock :emlist, 0..1 | |
defblock :cmd, 0..1 | |
defblock :table, 0..2 | |
defblock :quote, 0 | |
defblock :image, 2..3, true | |
defblock :source, 0..1 | |
defblock :listnum, 2 | |
defblock :emlistnum, 0..1 | |
defblock :bibpaper, 2..3, true | |
defblock :doorquote, 1 | |
defblock :talk, 0 | |
defblock :texequation, 0 | |
defblock :graph, 1..3 | |
defblock :address, 0 | |
defblock :blockquote, 0 | |
defblock :bpo, 0 | |
defblock :flushright, 0 | |
defblock :centering, 0 | |
defblock :note, 0..1 | |
defblock :box, 0..1 | |
defblock :comment, 0..1, true | |
defsingle :footnote, 2 | |
defsingle :noindent, 0 | |
defsingle :linebreak, 0 | |
defsingle :pagebreak, 0 | |
defsingle :indepimage, 1..3 | |
defsingle :numberlessimage, 1..3 | |
defsingle :hr, 0 | |
defsingle :parasep, 0 | |
defsingle :label, 1 | |
defsingle :raw, 1 | |
defsingle :tsize, 1 | |
defsingle :include, 1 | |
defsingle :olnum, 1 | |
definline :chapref | |
definline :chap | |
definline :title | |
definline :img | |
definline :icon | |
definline :list | |
definline :table | |
definline :fn | |
definline :kw | |
definline :ruby | |
definline :bou | |
definline :ami | |
definline :b | |
definline :dtp | |
definline :code | |
definline :bib | |
definline :hd | |
definline :href | |
definline :recipe | |
definline :abbr | |
definline :acronym | |
definline :cite | |
definline :dfn | |
definline :em | |
definline :kbd | |
definline :q | |
definline :samp | |
definline :strong | |
definline :var | |
definline :big | |
definline :small | |
definline :del | |
definline :ins | |
definline :sup | |
definline :sub | |
definline :tt | |
definline :i | |
definline :tti | |
definline :ttb | |
definline :u | |
definline :raw | |
definline :br | |
definline :m | |
definline :uchar | |
definline :idx | |
definline :hidx | |
definline :comment | |
definline :include | |
def tagged_section_init | |
@tagged_section = [] | |
end | |
def open_tagged_section(tag, args, contents) | |
mid = "#{tag}_begin" | |
unless @strategy.respond_to?(mid) | |
error "strategy does not support tagged section: #{tag}" | |
return | |
end | |
@tagged_section.push [tag, level] | |
## @strategy.__send__ mid, level, label, caption | |
puts "@strategy.__send__ #{mid}, #{level}, #{label}, #{caption}" | |
end | |
def close_tagged_section(tag, level) | |
mid = "#{tag}_end" | |
if @strategy.respond_to?(mid) | |
@strategy.__send__ mid, level | |
else | |
error "strategy does not support block op: #{mid}" | |
end | |
end | |
def compile_command(name, args, lines) | |
p :compile_command, name,args,lines | |
# syntax = syntax_descriptor(name) | |
return "" | |
unless @strategy.respond_to?(syntax.name) | |
error "strategy does not support command: //#{syntax.name}" | |
compile_unknown_command args, lines | |
return | |
end | |
begin | |
syntax.check_args args | |
rescue CompileError => err | |
error err.message | |
args = ['(NoArgument)'] * syntax.min_argc | |
end | |
if syntax.block_allowed? | |
compile_block syntax, args, lines | |
else | |
if lines | |
error "block is not allowed for command //#{syntax.name}; ignore" | |
end | |
compile_single syntax, args | |
end | |
end | |
} | |
root = Start | |
Start = &. { tagged_section_init } Block* | |
## TODO InlineElement の後に Ulist / Olist / Dlist が来ると先頭行じゃなくてマッチできてしまうかも | |
## using &. to detect EOF | |
Block = BlankLine* | |
( SinglelineComment:c | |
| Headline:headline | |
| BlockElement:c | |
| Ulist:c | |
| Olist:c | |
| Dlist:c | |
| Paragraph:c | |
) | |
BlankLine = SP Newline | |
Headline = ( HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent:caption Newline* ) | |
{ puts "@strategy.headline #{level}, #{cmd}, #{label}, #{caption}" } | |
HeadlinePrefix = < /={1,5}/ > { text.length } | |
Paragraph = !"=" ParagraphSub+ SP | |
ParagraphSub = ( InlineElement:c | |
| < ContentText > { text } | |
)+:d { d } | |
ContentText = !Newline !Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist NonInlineElement+:c Newline? { c } | |
NonInlineElement = !InlineElement < /[^\r\n]/ > { text } | |
BlockElement = ( "//" ElementName:symbol BracketArg*:args "{" Newline BlockElementContents?:contents "//}" SP | |
{ compile_command(symbol, args, contents) } | |
| "//" ElementName:symbol BracketArg*:args SP | |
) | |
InlineElement = "@<" < /[^>\r\n]+/ > {symbol = text} ">" "{" < InlineElementContents? > { contents = text} "}" | |
{ puts "@<> #{symbol} #{contents}" } | |
BracketArg = "[" < /([^\r\n\]\\]|\\[^\r\n])*/ > "]" { text } | |
BraceArg = "{" < /([^\r\n}\\]|\\[^\r\n])*/ > "}" { text } | |
## contents との差は paragraph を切るか切らないか | |
BlockElementContents = BlockElementContent+:c SP { c } | |
## 各要素は Newline で終わらなければならない | |
BlockElementContent = ( SinglelineComment:c | |
| BlockElement:c | |
| Ulist:c | |
| Olist:c | |
| Dlist:c | |
| BlockElementParagraph:c | |
) | |
BlockElementParagraph = &. { @blockElem = [] } BlockElementParagraphSub+:c SP { @blockElem } | |
BlockElementParagraphSub = ( InlineElement:c | |
| BlockElementContentText:c { @blockElem << c } | |
)+ | |
BlockElementContentText = ( &. !"//}" !SinglelineComment !BlockElement !Ulist !Olist !Dlist < NonInlineElement+ Newline? > ):c { text } | |
InlineElementContents = !"}" InlineElementContent+:c | |
InlineElementContent = ( InlineElement:c | |
| InlineElementContentText:c | |
) | |
InlineElementContentText = ( !InlineElement /[^\r\n}]/ )+ | |
SinglelineContent = ContentInlines:c (Newline | EOF) { c } | |
ContentInlines = < ContentInline+:c > { text } | |
ContentInline = ( InlineElement:c | |
| ContentInlineText+:c | |
) | |
ContentInlineText = !InlineElement !Newline . | |
## * 箇条書き | |
## 行頭から… の指定がない | |
Ulist = (UlistElement | SinglelineComment):c Ulist?:cc | |
UlistElement = " "+ "*"+:level Space* SinglelineContent:text | |
## 1. 番号付き箇条書き | |
## 行頭から… の指定がない | |
Olist = (OlistElement | SinglelineComment):c Olist?:cc | |
OlistElement = " "+ Digits:n "." Space* SinglelineContent:text | |
## : 用語リスト | |
## 行頭から… の指定がない | |
Dlist = (DlistElement | SinglelineComment):c Dlist?:cc | |
DlistElement = " "* ":" " " Space* SinglelineContent:text DlistElementContent:content SP | |
DlistElementContent = /[ \t]+/ SinglelineContent:c | |
SinglelineComment = "#@" /[^\r\n]+/ Newline? SP { "(skip comment" } | |
Digits = Digit+ | |
SP = /[ \t\r\n]*/ | |
## Space = /[ \t]/ | |
Space = /[ \t]/ | |
EOF = !. | |
ElementName = < LowerAlphabetAscii+ > { text } | |
%literals = ReVIEW::Compiler::Literals | |
Alphanumeric = %literals.Alphanumeric | |
AlphanumericAscii = %literals.AlphanumericAscii | |
LowerAlphabetAscii = %literals.LowerAlphabetAscii | |
Digit = %literals.Digit | |
BOM = %literals.BOM | |
Newline = %literals.Newline | |
NonAlphanumeric = %literals.NonAlphanumeric | |
Spacechar = %literals.Spacechar |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment