mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
709dc33c92
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8112 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
381 lines
8.5 KiB
Text
381 lines
8.5 KiB
Text
#
|
|
# parser.y
|
|
#
|
|
# Copyright (c) 1998-2007 Minero Aoki
|
|
#
|
|
# This program is free software.
|
|
# You can distribute/modify this program under the terms of
|
|
# the GNU Lesser General Public License version 2.1.
|
|
#
|
|
|
|
class TMail::Parser
|
|
|
|
options no_result_var
|
|
|
|
rule
|
|
|
|
content : DATETIME datetime { val[1] }
|
|
| RECEIVED received { val[1] }
|
|
| MADDRESS addrs_TOP { val[1] }
|
|
| RETPATH retpath { val[1] }
|
|
| KEYWORDS keys { val[1] }
|
|
| ENCRYPTED enc { val[1] }
|
|
| MIMEVERSION version { val[1] }
|
|
| CTYPE ctype { val[1] }
|
|
| CENCODING cencode { val[1] }
|
|
| CDISPOSITION cdisp { val[1] }
|
|
| ADDRESS addr_TOP { val[1] }
|
|
| MAILBOX mbox { val[1] }
|
|
|
|
datetime : day DIGIT ATOM DIGIT hour zone
|
|
# 0 1 2 3 4 5
|
|
# date month year
|
|
{
|
|
t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0)
|
|
(t + val[4] - val[5]).localtime
|
|
}
|
|
|
|
day : /* none */
|
|
| ATOM ','
|
|
|
|
hour : DIGIT ':' DIGIT
|
|
{
|
|
(val[0].to_i * 60 * 60) +
|
|
(val[2].to_i * 60)
|
|
}
|
|
| DIGIT ':' DIGIT ':' DIGIT
|
|
{
|
|
(val[0].to_i * 60 * 60) +
|
|
(val[2].to_i * 60) +
|
|
(val[4].to_i)
|
|
}
|
|
|
|
zone : ATOM
|
|
{
|
|
timezone_string_to_unixtime(val[0])
|
|
}
|
|
|
|
received : from by via with id for received_datetime
|
|
{
|
|
val
|
|
}
|
|
|
|
from : /* none */
|
|
| FROM received_domain
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
by : /* none */
|
|
| BY received_domain
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
received_domain
|
|
: domain
|
|
{
|
|
join_domain(val[0])
|
|
}
|
|
| domain '@' domain
|
|
{
|
|
join_domain(val[2])
|
|
}
|
|
| domain DOMLIT
|
|
{
|
|
join_domain(val[0])
|
|
}
|
|
|
|
via : /* none */
|
|
| VIA ATOM
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
with : /* none */
|
|
{
|
|
[]
|
|
}
|
|
| with WITH ATOM
|
|
{
|
|
val[0].push val[2]
|
|
val[0]
|
|
}
|
|
|
|
id : /* none */
|
|
| ID msgid
|
|
{
|
|
val[1]
|
|
}
|
|
| ID ATOM
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
for : /* none */
|
|
| FOR received_addrspec
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
received_addrspec
|
|
: routeaddr
|
|
{
|
|
val[0].spec
|
|
}
|
|
| spec
|
|
{
|
|
val[0].spec
|
|
}
|
|
|
|
received_datetime
|
|
: /* none */
|
|
| ';' datetime
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
addrs_TOP : addrs
|
|
| group_bare
|
|
| addrs commas group_bare
|
|
|
|
addr_TOP : mbox
|
|
| group
|
|
| group_bare
|
|
|
|
retpath : addrs_TOP
|
|
| '<' '>' { [ Address.new(nil, nil) ] }
|
|
|
|
addrs : addr
|
|
{
|
|
val
|
|
}
|
|
| addrs commas addr
|
|
{
|
|
val[0].push val[2]
|
|
val[0]
|
|
}
|
|
|
|
addr : mbox
|
|
| group
|
|
|
|
mboxes : mbox
|
|
{
|
|
val
|
|
}
|
|
| mboxes commas mbox
|
|
{
|
|
val[0].push val[2]
|
|
val[0]
|
|
}
|
|
|
|
mbox : spec
|
|
| routeaddr
|
|
| addr_phrase routeaddr
|
|
{
|
|
val[1].phrase = Decoder.decode(val[0])
|
|
val[1]
|
|
}
|
|
|
|
group : group_bare ';'
|
|
|
|
group_bare: addr_phrase ':' mboxes
|
|
{
|
|
AddressGroup.new(val[0], val[2])
|
|
}
|
|
| addr_phrase ':' { AddressGroup.new(val[0], []) }
|
|
|
|
addr_phrase
|
|
: local_head { val[0].join('.') }
|
|
| addr_phrase local_head { val[0] << ' ' << val[1].join('.') }
|
|
|
|
routeaddr : '<' routes spec '>'
|
|
{
|
|
val[2].routes.replace val[1]
|
|
val[2]
|
|
}
|
|
| '<' spec '>'
|
|
{
|
|
val[1]
|
|
}
|
|
|
|
routes : at_domains ':'
|
|
|
|
at_domains: '@' domain { [ val[1].join('.') ] }
|
|
| at_domains ',' '@' domain { val[0].push val[3].join('.'); val[0] }
|
|
|
|
spec : local '@' domain { Address.new( val[0], val[2] ) }
|
|
| local { Address.new( val[0], nil ) }
|
|
|
|
local: local_head
|
|
| local_head '.' { val[0].push ''; val[0] }
|
|
|
|
local_head: word
|
|
{ val }
|
|
| local_head dots word
|
|
{
|
|
val[1].times do
|
|
val[0].push ''
|
|
end
|
|
val[0].push val[2]
|
|
val[0]
|
|
}
|
|
|
|
domain : domword
|
|
{ val }
|
|
| domain dots domword
|
|
{
|
|
val[1].times do
|
|
val[0].push ''
|
|
end
|
|
val[0].push val[2]
|
|
val[0]
|
|
}
|
|
|
|
dots : '.' { 0 }
|
|
| '.' '.' { 1 }
|
|
|
|
word : atom
|
|
| QUOTED
|
|
| DIGIT
|
|
|
|
domword : atom
|
|
| DOMLIT
|
|
| DIGIT
|
|
|
|
commas : ','
|
|
| commas ','
|
|
|
|
msgid : '<' spec '>'
|
|
{
|
|
val[1] = val[1].spec
|
|
val.join('')
|
|
}
|
|
|
|
keys : phrase { val }
|
|
| keys ',' phrase { val[0].push val[2]; val[0] }
|
|
|
|
phrase : word
|
|
| phrase word { val[0] << ' ' << val[1] }
|
|
|
|
enc : word
|
|
{
|
|
val.push nil
|
|
val
|
|
}
|
|
| word word
|
|
{
|
|
val
|
|
}
|
|
|
|
version : DIGIT '.' DIGIT
|
|
{
|
|
[ val[0].to_i, val[2].to_i ]
|
|
}
|
|
|
|
ctype : TOKEN '/' TOKEN params opt_semicolon
|
|
{
|
|
[ val[0].downcase, val[2].downcase, decode_params(val[3]) ]
|
|
}
|
|
| TOKEN params opt_semicolon
|
|
{
|
|
[ val[0].downcase, nil, decode_params(val[1]) ]
|
|
}
|
|
|
|
params : /* none */
|
|
{
|
|
{}
|
|
}
|
|
| params ';' TOKEN '=' QUOTED
|
|
{
|
|
val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"')
|
|
val[0]
|
|
}
|
|
| params ';' TOKEN '=' TOKEN
|
|
{
|
|
val[0][ val[2].downcase ] = val[4]
|
|
val[0]
|
|
}
|
|
|
|
cencode : TOKEN
|
|
{
|
|
val[0].downcase
|
|
}
|
|
|
|
cdisp : TOKEN params opt_semicolon
|
|
{
|
|
[ val[0].downcase, decode_params(val[1]) ]
|
|
}
|
|
|
|
opt_semicolon
|
|
:
|
|
| ';'
|
|
|
|
atom : ATOM
|
|
| FROM
|
|
| BY
|
|
| VIA
|
|
| WITH
|
|
| ID
|
|
| FOR
|
|
|
|
end
|
|
|
|
|
|
---- header
|
|
#
|
|
# parser.rb
|
|
#
|
|
# Copyright (c) 1998-2007 Minero Aoki
|
|
#
|
|
# This program is free software.
|
|
# You can distribute/modify this program under the terms of
|
|
# the GNU Lesser General Public License version 2.1.
|
|
#
|
|
|
|
require 'tmail/scanner'
|
|
require 'tmail/utils'
|
|
|
|
---- inner
|
|
|
|
include TextUtils
|
|
|
|
def self.parse( ident, str, cmt = nil )
|
|
new.parse(ident, str, cmt)
|
|
end
|
|
|
|
MAILP_DEBUG = false
|
|
|
|
def initialize
|
|
self.debug = MAILP_DEBUG
|
|
end
|
|
|
|
def debug=( flag )
|
|
@yydebug = flag && Racc_debug_parser
|
|
@scanner_debug = flag
|
|
end
|
|
|
|
def debug
|
|
@yydebug
|
|
end
|
|
|
|
def parse( ident, str, comments = nil )
|
|
@scanner = Scanner.new(str, ident, comments)
|
|
@scanner.debug = @scanner_debug
|
|
@first = [ident, ident]
|
|
result = yyparse(self, :parse_in)
|
|
comments.map! {|c| to_kcode(c) } if comments
|
|
result
|
|
end
|
|
|
|
private
|
|
|
|
def parse_in( &block )
|
|
yield @first
|
|
@scanner.scan(&block)
|
|
end
|
|
|
|
def on_error( t, val, vstack )
|
|
raise SyntaxError, "parse error on token #{racc_token2str t}"
|
|
end
|
|
|