アンチパターン』読了。この本に載っているアンチパターンは、ソフトウェア開発、ソフトウェアのアーキテクチャ、プロジェクト管理の3種類に分けられています。最初のソフトウェア開発の部分は面白かったけれど、後の2つはあまり面白くありませんでした。理由として、自分の興味から離れている、(実際にプロジェクト管理なんてしないので)実感が湧かない、ソフトウェア工学そのものがつまらない、といった点が挙げられます。あと、CORBA、OMG、IDLといったキーワードが色々な物事の例として出てくることが多いのですが、そういったまともな(?)OOPに触れていない自分にとっては、どこか遠い知らない世界の物語に感じられます。アンチパターンというのは普遍的に思われる言葉だけど、この本に出てくる具体例は自分にとってはちっとも身近ではなく、要するに普遍的な内容ではなかったのです。しかし抽象的は話はそれはそれでさっぱりぴんとこない。

ソフトウェア工学の本は普遍的だから(例えば『入門VisualBasic』みたいな本よりは)いつ読んでも無駄にはならないだろうとは思っていたけど、思ったより普遍的でもなく、予想以上につまらないことが多そうです。もっと具体的な実装寄りなら良いのかなあ。具体的な設計や仕様なんかじゃなくて。

そういえば某同人ゲーム仕事はそんなに薄給ではなくなりました。

卒研…どこで左再帰してるかやっとわかったー!っていうか何で今頃こんなコンパイラの基礎というか構文解析の初歩を勉強しているのでしょうか。

なんというか、パーサーとかって、本を読んだだけでは全然理解できていませんね。まあ人にもよるのだろうけど、実際にいじってみて自分があまりに理解できていないことがよくわかりました。

Text.ParserCombinators.ParsecExprってどこにあるんだろうと悩む…なんとText.ParserCombinators.Parsec.Exprにありました

だいぶマシになったかな。しかしやっぱり抽象構文木を作らないとダメだろうか。コンパイラを作るわけではないので要らないかなあと思ったのだけど…

module Main where

import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr

main = do src <- getContents
          putStrLn $ makeSrc src

makeSrc :: String -> String
makeSrc src = case parse expression "" src of
    Right madeSrc -> madeSrc
    Left err -> show err

expression :: Parser String
expression = assignment_expression `chainl1` expression_op

expression_op = do string ","
                   return $ \x y -> x ++ "," ++ y

assignment_expression = try (do a <- unary_expression
                                b <- assignment_operator
                                c <- assignment_expression
                                return $ a ++ b ++ c)
                     <|> conditional_expression

assignment_operator = string "="
                  <|> string "*="
                  <|> string "/="
                  <|> string "%="
                  <|> string "+="
                  <|> string "-="
                  <|> string "<<="
                  <|> string ">>="
                  <|> string "&="
                  <|> string "^="
                  <|> string "|="

conditional_expression = do a <- buildExpressionParser conditional_op_table cast_expression --logical_OR_expression
                            bcde <- option "" (do b <- string "?"
                                                  c <- expression
                                                  d <- string ":"
                                                  e <- conditional_expression
                                                  return $ b ++ c ++ d ++ e)
                            return $ a ++ bcde

constant_expression = conditional_expression

conditional_op_table =  [ [op "*"  (\x y -> x ++ "*" ++ y) AssocLeft, op "/"  (\x y -> x ++ "/" ++ y) AssocLeft
                          ,op "%"  (\x y -> x ++ "%" ++ y) AssocLeft]
                         ,[op "+"  (\x y -> x ++ "+" ++ y) AssocLeft, op "-"  (\x y -> x ++ "-" ++ y) AssocLeft]
                         ,[op "<<"  (\x y -> x ++ "<<" ++ y) AssocLeft, op ">>"  (\x y -> x ++ ">>" ++ y) AssocLeft]
                         ,[op "<="  (\x y -> x ++ "<=" ++ y) AssocLeft, op ">="  (\x y -> x ++ ">=" ++ y) AssocLeft
                          ,op "<"  (\x y -> x ++ "<" ++ y) AssocLeft, op ">"  (\x y -> x ++ ">" ++ y) AssocLeft]
                         ,[op "=="  (\x y -> x ++ "==" ++ y) AssocLeft, op "!="  (\x y -> x ++ "!=" ++ y) AssocLeft]
                         ,[op "&"  (\x y -> x ++ "&" ++ y) AssocLeft]
                         ,[op "^"  (\x y -> x ++ "^" ++ y) AssocLeft]
                         ,[op "|"  (\x y -> x ++ "|" ++ y) AssocLeft]
                         ,[op "&&"  (\x y -> x ++ "&&" ++ y) AssocLeft]
                         ,[op "||"  (\x y -> x ++ "||" ++ y) AssocLeft]
                         ]
 where
     op s f assoc = Infix (try (do{string s; return f})) assoc

cast_expression = unary_expression -- also cast

unary_expression = try (do a <- string "++"
                           b <- unary_expression
                           return $ a ++ b)
               <|> try (do a <- string "--"
                           b <- unary_expression
                           return $ a ++ b)
               <|> do a <- unary_operator
                      b <- cast_expression
                      return $ a ++ b
               <|> postfix_expression -- also something

unary_operator = string "&"
             <|> string "*"
             <|> string "+"
             <|> string "-"
             <|> string "~"
             <|> string "!"

postfix_expression = do a <- primary_expression -- also something
                        b <- many (do b <- string "["
                                      c <- expression
                                      d <- string "]"
                                      return $ b ++ c ++ d
                               <|> do b <- string "."
                                      c <- identifier
                                      return $ b ++ c
                               <|> try (do b <- string "->"
                                           c <- identifier
                                           return $ b ++ c)
                               <|> do b <- string "++"
                                      return b
                               <|> do b <- string "--"
                                      return b)
                        return $ a ++ concat b -- also something
                                               -- fix chain left

primary_expression = try constant
                 <|> identifier
                 <|> do a <- string "("
                        b <- expression
                        c <- string ")"
                        return $ a ++ b ++ c -- also something

identifier = do a <- many space
                b <- many1 $ alphaNum <|> char '_'
                c <- many space
                return $ a ++ b ++ c

constant = integer_constant -- also something

integer_constant = do a <- many space
                      b <- many1 digit
                      c <- many space
                      return $ a ++ b ++ c