使用React js完成web前端

This commit is contained in:
LIm1tZz7 committed 2026-09-27 22:08:23 +08:00
1 parent 9e8c5f1ef0
commit 7600f0f9ed
130 files changed
+12708 -788

No files matched your search

+3 -16
View File
@@ -4,9 +4,6 @@ import ChuSQL.Model (Column (..))
-- 语法树:语句、数据来源、条件表达式、排序方向。
-- * 语句
-- | 一条语句:查 / 加 / 删 / 改 / 建表 / 删表 / 建索引 / 删索引
data Statement
= Select
{ selectCols :: [String]
@@ -15,26 +12,21 @@ data Statement
, selectOrderBy :: [(String, SortDir)]
, selectLimit :: Maybe Int
}
| -- \| 表、列、若干行(`VALUES (...), (...)` 可以一次给多行)
Insert String [String] [[Expr]]
| Insert String [String] [[Expr]]
| Delete String (Maybe Expr)
| Update String [(String, Expr)] (Maybe Expr)
| CreateTable String [(String, Column)]
| DropTable String
| -- \| 给某一列建索引(列名即索引名)
CreateIndex String String
| CreateIndex String String
| DropIndex String String
| DropColumn String String
deriving (Show, Eq)
-- | 数据来源:单表,或两表拼接
data FromClause
= FromTable (Maybe String) String
| FromJoin FromClause (Maybe String) String Expr
deriving (Show, Eq)
-- * 表达式
-- | 条件表达式
data Expr
= Col String
| LitInt Int
@@ -47,16 +39,11 @@ data Expr
| Or Expr Expr
deriving (Show, Eq)
-- * 排序
-- | 排序方向
data SortDir
= Asc
| Desc
deriving (Show, Eq)
-- * 构造
-- | 造一个最简单的 SELECT
makeSelect :: [String] -> String -> Maybe Expr -> Statement
makeSelect cols tbl w =
+22 -30
View File
@@ -15,11 +15,8 @@ import Text.Megaparsec.Char.Lexer qualified as Lxr
-- SQL 解析:词法 + 语法,把文本变成语句树。
-- * 词法
-- | 解析器类型
type Parser = Parsec Void String
-- | 跳过空白
sc :: Parser ()
sc = Lxr.space space1 empty empty
@@ -32,9 +29,6 @@ lexeme = Lxr.lexeme sc
symbol :: String -> Parser String
symbol = Lxr.symbol sc
{- | 大小写不敏感的关键字;其后不能紧跟标识符字符,避免把 @selection@ 读成 @select@。
整体用 'try' 包住:否则 @ORDER@ 会被 @keyword "or"@ 吃掉前缀 @OR@ 再报错,导致无法回溯。
-}
-- | 读关键字(不分大小写)
keyword :: String -> Parser ()
keyword k = lexeme $ try $ do
@@ -64,9 +58,6 @@ stringLit = lexeme $ do
_ <- char '\''
return s
{- | 字符串内的一个字符:@''@ 折叠成一个单引号,其余字符(含反斜杠)原样保留。
两个分支都不会在失败时消耗输入,因此可以安全地放进 'many'。
-}
-- | 字符串里的一个字符
stringChar :: Parser Char
stringChar =
@@ -75,7 +66,6 @@ stringChar =
, satisfy (/= '\'')
]
-- * 子句
-- | 升序或降序
sortDir :: Parser SortDir
sortDir = (Desc <$ keyword "desc") <|> (Asc <$ keyword "asc") <|> pure Asc
@@ -94,31 +84,29 @@ qualifiedName = do
return (intercalate "." (first : rest))
-- * 表达式
-- | 读一个表达式
expr :: Parser Expr
expr = makeExprParser atom operatorTable
{- | 运算符表。注意 'makeExprParser' 要求各层按优先级从高到低排列:
比较运算符绑定最紧,'AND' 次之,'OR' 最松。
-}
-- | 运算符优先级(从紧到松)
operatorTable :: [[Operator Parser Expr]]
operatorTable =
[
[ InfixN (Gt <$ symbol ">") -- 最高优先级
[ InfixN (Gt <$ symbol ">")
, InfixN (Lt <$ symbol "<")
, InfixN (Eq <$ symbol "=")
]
, [InfixL (And <$ keyword "AND")]
, [InfixL (Or <$ keyword "OR")] -- 最低优先级
, [InfixL (Or <$ keyword "OR")]
]
-- | 最小的表达式单位
atom :: Parser Expr
atom =
choice
[ LitInt <$> integer
[ LitBool True <$ keyword "TRUE"
, LitBool False <$ keyword "FALSE"
, LitInt <$> integer
, LitStr <$> stringLit
, Col <$> qualifiedName
, between (symbol "(") (symbol ")") expr
@@ -148,7 +136,6 @@ assignment = do
return (col, e)
-- | 保留字清单
reservedWords :: [String]
reservedWords =
[ "select"
@@ -173,12 +160,10 @@ reservedWords =
, "table"
, "index"
, "drop"
, "alter"
, "column"
]
{- | 表别名。别名不能是保留字:否则 @FROM users WHERE age > 18@ 会把 @WHERE@
当成 @users@ 的别名吃掉,后面真正的 WHERE 子句就再也解析不到。
用 'try' 包住,一旦命中保留字就整体回溯,让 'optional' 正常返回 'Nothing'。
-}
-- | 别名(不许用保留字)
aliasName :: Parser String
aliasName = try $ do
@@ -234,7 +219,7 @@ dropTableStatement = do
name <- identifier
return (DropTable name)
-- | 读 CREATE INDEX(列名即索引名:一列最多一个索引)
-- | 读 CREATE INDEX(列名即索引名)
createIndexStatement :: Parser Statement
createIndexStatement = do
keyword "create"
@@ -254,6 +239,17 @@ dropIndexStatement = do
col <- between (symbol "(") (symbol ")") identifier
return (DropIndex tbl col)
-- | 读 ALTER TABLE ... DROP COLUMN
alterDropColumnStatement :: Parser Statement
alterDropColumnStatement = do
keyword "alter"
keyword "table"
tbl <- identifier
keyword "drop"
keyword "column"
col <- identifier
return (DropColumn tbl col)
-- | 建表时的一列
columnDef :: Parser (String, Column)
columnDef = do
@@ -272,7 +268,6 @@ columnType =
<|> (keyword "boolean" >> pure TBool)
<|> (keyword "bool" >> pure TBool)
-- * 语句
-- | 读 SELECT
selectStatement :: Parser Statement
selectStatement = do
@@ -292,7 +287,7 @@ selectStatement = do
, selectLimit = mLimit
}
-- | 读 INSERT:`VALUES (...)` 后面可以跟多个括号,一次插多行
-- | 读 INSERT,可一次插多行
insertStatement :: Parser Statement
insertStatement = do
keyword "INSERT"
@@ -330,7 +325,6 @@ updateStatement = do
mWhere <- optional (keyword "where" *> expr)
return (Update tbl assigns mWhere)
-- * 入口
-- | 解析总入口
parseStatement :: String -> Either String Statement
parseStatement input =
@@ -338,10 +332,7 @@ parseStatement input =
Left err -> Left (errorBundlePretty err)
Right q -> Right q
where
-- \| 依次尝试各种语句。
-- `CREATE` / `DROP` 后面跟的词决定是哪条语句,而 `keyword` 的 `try` 只能回溯到
-- "这个词之前"——`CREATE` 一旦被吃掉就没得退了。所以带 `INDEX` 的那两个各自
-- 用 `try` 包住并排在前面:`CREATE INDEX ...` 先试,退回来再试 `CREATE TABLE ...`。
-- \| 依次尝试各种语句
statementP =
selectStatement
<|> insertStatement
@@ -350,4 +341,5 @@ parseStatement input =
<|> try createIndexStatement
<|> try createTableStatement
<|> try dropIndexStatement
<|> try alterDropColumnStatement
<|> dropTableStatement