现代希腊语的拉丁转写

参考希腊语标准化组织 ELOT 743 (Type 2 - transcription) (1982; 2001)使用处理编程语言的手段词法分析 + 语法分析将现代希腊语转写为拉丁字母

该标准的英文版可见维基百科

https://en.wikipedia.org/wiki/Romanization_of_Greek#Modern_Greek

词法分析

ELOT 743 Type 2 中的合法 token 有

α, αι, αυ, β, γ, γγ, γκ, γξ, γχ, 
δ, ε, ει, ευ, ζ, η, ηυ, θ, ι, κ, 
λ, μ, μπ, ν, ντ, ξ, ο, οι, ου, π, 
ρ, σ , ς, τ, υ, υι, φ, χ, ψ, ω, ωυ

最长优先匹配 token在程序中之所以选取这些 token 而非直接选取希腊字母作为 token 是为了方便语法分析的实现

处理重音符分音符和两者的混合在词法分析器中穷举有限种在上述基本 token 中的排列组合
在此处需要注意上表中的 αυευηυωυ 并非单元音
在处理重音符分音符时需要与占据两个字母长度的单元音例如 αι 等区别
重音似乎不应该落在单独出来的 αυευηυωυυυι 的情况比较复杂因为单独拿出来的 υι 都应该是 /i/同样只存在 υί 一种可能存疑

处理大写字母词法分析阶段只额外需要添加上述所有 token 首字母大写的形式使用 python 的 str.capitalize() 方法可以自动生成

语法分析

主要是处理 αυευηυωυ 的转写规则

测试

现代希腊语版圣经 https://www.bible.com/languages/ell

源代码

词法分析

import ply.lex as lex
# lexical analysis
# =================
# basic tokens
ellinika_tokens = [ "α", "αι", "αυ", 
                    "β", 
                    "γ", "γγ", "γκ", "γξ", "γχ", 
                    "δ", 
                    "ε", "ει", "ευ", 
                    "ζ", 
                    "η", "ηυ", 
                    "θ", 
                    "ι", 
                    "κ", 
                    "λ", 
                    "μ", "μπ", 
                    "ν", "ντ", 
                    "ξ", 
                    "ο", "οι", "ου", 
                    "π", 
                    "ρ", 
                    "σ", "ς", 
                    "τ", 
                    "υ", "υι", 
                    "φ", 
                    "χ", 
                    "ψ", 
                    "ω", "ωυ"]
# acute accent and diaeresis
ellinika_tokens += ["ά",
                    "έ", "αί", "αϊ", "αΐ",
                    "ή", "ί", "ύ", "εί", "οί", "εϊ", "οϊ", "εΐ", "οΐ",
                    "ό", "ώ",
                    "ού", "οϋ", "οΰ"]
# acute accent and diaeresis about αυ, ευ, ηυ, ωυ, υι
ellinika_tokens += ["αύ", "εύ", "ηύ", "ωύ", "υί"]
# capital letters
ellinika_tokens += [token[0].upper() + token[1:] for token in ellinika_tokens]
# longest tokens first
ellinika_tokens_sorted = sorted(ellinika_tokens, key=len, reverse=True)
tokens = ('ELLINIKA_CHAR',)
t_ELLINIKA_CHAR = r'|'.join(ellinika_tokens_sorted)
t_ignore  = ' \t'

# lexical analysis error handling
def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

lexer = lex.lex()

# test
data = "ΕΠΕΙΔΗ, πολλοί επιχείρησαν να συντάξουν διήγηση για τα πράγματα που σε μας είναι πλήρως βεβαιωμένα,\
        καθώς μας τα παρέδωσαν αυτοί που εξαρχής έγιναν αυτόπτες μάρτυρες και υπηρέτες τού λόγου, \
        φάνηκε εύλογο και σε μένα, που παρακολούθησα ακριβώς τα πάντα από την αρχή, να σου γράψω γι’ αυτά με τη σειρά, εξοχότατε Θεόφιλε. \
        για να γνωρίσεις τη βεβαιότητα των πραγμάτων, για τα οποία κατηχήθηκες."

lexer.input(data)
print("Lexer output:")
for token in lexer:
    print(token)

语法分析

import ply.yacc as yacc

# TODO