Skip to content

Latest commit

History

52 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Syntax Parser

一个 C# 语法分析框架。

全局选项

  • Parser.DebugMode:是否开启调试输出。

使用示例

用下面的 SQL 语法分析器的例子,展示如何构建一个语法分析器。

基本配置

publicclassSqlParser{readonlyParserparser=new();publicSqlParser()=>parser.SetIgnoreCase(true)// Ignore case.SetSkipPattern(@"\s+")// Ignore whitespace.SetTokenizationType(TokenizationType.Static)// Static tokenization.SetSyntaxDef(newSqlSyntaxDef());publicIEnumerable<object?>Parse(stringstr)=>parser.Parse(str);}

语法定义

publicclassSqlSyntaxDef:ISyntaxDef{publicINodeRootNode=>root;// TokenspublicTokenNode<decimal>udecimal=new();publicTokenNode<uint>@uint=new();publicTokenNode<bool>@true=new();publicTokenNode<bool>@false=new();publicTokenNode<object?>@null=new();publicTokenNode<string>@select=new();publicTokenNode<string>@from=new();publicTokenNode<string>@where=new();publicTokenNode<string>@as=new();publicTokenNode<string>and=new();publicTokenNode<string>or=new();publicTokenNode<string>not=new();publicTokenNode<string>@in=new();publicTokenNode<string>notIn=new();publicTokenNode<string>exists=new();publicTokenNode<string>id=new();publicTokenNode<string>lParen=new();publicTokenNode<string>rParen=new();publicTokenNode<string>comma=new();publicTokenNode<string>dot=new();publicTokenNode<string>star=new();publicTokenNode<string>eq=new();publicTokenNode<string>ne=new();publicTokenNode<string>le=new();publicTokenNode<string>lt=new();publicTokenNode<string>ge=new();publicTokenNode<string>gt=new();publicTokenNode<string>plus=new();publicTokenNode<string>minus=new();publicTokenNode<string>multiply=new();publicTokenNode<string>divide=new();// Syntax treepublicEmptyNodeempty=new();publicMultiNode<Value>value=new();publicMultiNode<string?>asAlias=new();publicMultiNode<string>fieldName=new();publicMultiNode<Attr>attr=new();publicMultiNode<Operator.Comp>binaryCompOper=new();publicMultiNode<Operator.Comp>unaryCompOper=new();publicMultiNode<Operator.Arith>binaryArithOper=new();publicMultiNode<Operator.Arith>unaryArithOper=new();publicMultiNode<Operator.Logical>binaryLogicalOper=new();publicMultiNode<Operator.Logical>unaryLogicalOper=new();publicMultiNode<Expr>expr=new();publicMultiNode<Expr>expr0=new();publicMultiNode<Expr>expr1=new();publicMultiNode<Expr>expr2=new();publicMultiNode<Expr>expr3=new();publicMultiNode<Expr>expr4=new();publicMultiNode<Expr>selectColumn=new();publicMultiNode<IEnumerable<Expr>>selectColumns=new();publicMultiNode<Expr?>whereClause=new();publicMultiNode<Relation>relation=new();publicMultiNode<IEnumerable<Relation>>relations=new();publicMultiNode<IEnumerable<Relation>?>fromClause=new();publicMultiNode<SelectStmt>selectStmt=new();publicMultiNode<object>root=new();publicSqlSyntaxDef(){
#region Tokens
udecimal.SetRegex(@"\b\d+\.\d+\b").SetBuilder(t =>decimal.Parse(t.Value));@uint.SetRegex(@"\b\d+\b").SetBuilder(t =>uint.Parse(t.Value));@true.SetRegex(@"\bTRUE\b").SetBuilder(t =>true);@false.SetRegex(@"\bFALSE\b").SetBuilder(t =>false);@null.SetRegex(@"\bNULL\b").SetBuilder(t =>null);@select.SetRegex(@"\bSELECT\b");@from.SetRegex(@"\bFROM\b");@where.SetRegex(@"\bWHERE\b");@as.SetRegex(@"\bAS\b");and.SetRegex(@"\bAND\b");or.SetRegex(@"\bOR\b");not.SetRegex(@"\bNOT\b");exists.SetRegex(@"\bEXISTS\b");@in.SetRegex(@"\bIN\b");notIn.SetRegex(@"\bNOT IN\b");id.SetRegex(@"\b[A-Za-z_]+[A-Za-z0-9_]*\b").SetBuilder(t =>t.Value).SetCoverTypes(@true,@false,@null);lParen.SetRegex(@"\(");rParen.SetRegex(@"\)");comma.SetRegex(@",");dot.SetRegex(@"\.");star.SetRegex(@"\*");eq.SetRegex(@"=");ne.SetRegex(@"<>");le.SetRegex(@"<=");lt.SetRegex(@"<");ge.SetRegex(@">=");gt.SetRegex(@">");plus.SetRegex(@"\+");minus.SetRegex(@"-");multiply.SetTokenType(star.TokenType);divide.SetRegex(@"/");
#endregion
#region Syntax tree
// Rootroot.AddBranch(Syntax.Converter<object>(selectStmt));// StatementsselectStmt.NewSeqBranch(@select,selectColumns,fromClause,whereClause).SetBuilder(m =>newSelectStmt(){Columns=m.At(selectColumns),Tables=m.At(fromClause),Condition=m.At(whereClause),});// ComponentsfromClause.NewSeqBranch(empty).SetBuilder(m =>null);fromClause.NewSeqBranch(@from,relations).SetBuilder(m =>m.At(relations));whereClause.NewSeqBranch(empty).SetBuilder(m =>null);whereClause.NewSeqBranch(@where,expr).SetBuilder(m =>m.At(expr));selectColumns.AddBranch(Syntax.Sugar.List(selectColumn,comma));selectColumn.NewSeqBranch(expr,asAlias).SetBuilder(m =>{var_expr=m.At(expr);_expr.Alias=m.At(asAlias);return_expr;});relations.AddBranch(Syntax.Sugar.List(relation,comma));relation.NewSeqBranch(id,asAlias).SetBuilder(m =>newRelation(){Name=m.At(id),Alias=m.At(asAlias),});asAlias.NewSeqBranch(empty).SetBuilder(m =>null);asAlias.AddBranch(id!);asAlias.NewSeqBranch(@as,id).SetBuilder(m =>m.At(id));value.AddBranch(Syntax.Converter<Value>(udecimal,@uint,@true,@false,@null).SetBuilder(o =>newValue(o)));fieldName.AddBranch(star);fieldName.AddBranch(id);attr.NewSeqBranch(fieldName).SetBuilder(m =>newAttr(){FieldName=m.At(fieldName),});attr.NewSeqBranch(id,dot,fieldName).SetBuilder(m =>newAttr(){RelationName=m.At(id),FieldName=m.At(fieldName),});// Expressionsexpr.AddBranch(expr0);expr.NewSeqBranch(expr0,binaryLogicalOper,expr).SetBuilder(m =>m.At(expr)isOperatorExpr<Operator.Logical>other&&!other.IsUnary?OperatorExpr<Operator.Logical>.JoinRest(m.At(expr0),m.At(binaryLogicalOper),other):OperatorExpr<Operator.Logical>.Binary(m.At(expr0),m.At(binaryLogicalOper),m.At(expr)));expr0.AddBranch(expr1);expr0.NewSeqBranch(unaryLogicalOper,expr1).SetBuilder(m =>OperatorExpr<Operator.Logical>.Unary(m.At(unaryLogicalOper),m.At(expr1)));expr1.AddBranch(expr2);expr1.NewSeqBranch(unaryCompOper,expr2).SetBuilder(m =>OperatorExpr<Operator.Comp>.Unary(m.At(unaryCompOper),m.At(expr2)));expr1.NewSeqBranch(expr2,binaryCompOper,expr1).SetBuilder(m =>OperatorExpr<Operator.Comp>.Binary(m.At(expr2),m.At(binaryCompOper),m.At(expr1)));expr2.AddBranch(expr3);expr2.NewSeqBranch(expr3,binaryArithOper,expr2).SetBuilder(m =>m.At(expr2)isOperatorExpr<Operator.Arith>other&&!other.IsUnary?OperatorExpr<Operator.Arith>.JoinRest(m.At(expr3),m.At(binaryArithOper),other):OperatorExpr<Operator.Arith>.Binary(m.At(expr3),m.At(binaryArithOper),m.At(expr2)));expr3.AddBranch(expr4);expr3.NewSeqBranch(unaryArithOper,expr4).SetBuilder(m =>OperatorExpr<Operator.Arith>.Unary(m.At(unaryArithOper),m.At(expr4)));expr4.NewSeqBranch(value).SetBuilder(m =>newValueExpr(m.At(value)));expr4.NewSeqBranch(attr).SetBuilder(m =>newAttrExpr(m.At(attr)));expr4.NewSeqBranch(lParen,expr,rParen).SetBuilder(m =>newParensExpr(m.At(expr)));expr4.NewSeqBranch(lParen,selectStmt,rParen).SetBuilder(m =>newSubqueryExpr(m.At(selectStmt)));// OperatorsbinaryCompOper.NewSeqBranch(eq).SetBuilder(m =>Operator.Comp.Eq);binaryCompOper.NewSeqBranch(ne).SetBuilder(m =>Operator.Comp.Ne);binaryCompOper.NewSeqBranch(lt).SetBuilder(m =>Operator.Comp.Lt);binaryCompOper.NewSeqBranch(le).SetBuilder(m =>Operator.Comp.Le);binaryCompOper.NewSeqBranch(gt).SetBuilder(m =>Operator.Comp.Gt);binaryCompOper.NewSeqBranch(ge).SetBuilder(m =>Operator.Comp.Ge);binaryCompOper.NewSeqBranch(@in).SetBuilder(m =>Operator.Comp.In);binaryCompOper.NewSeqBranch(@notIn).SetBuilder(m =>Operator.Comp.NotIn);unaryCompOper.NewSeqBranch(@exists).SetBuilder(m =>Operator.Comp.Exists);binaryArithOper.NewSeqBranch(plus).SetBuilder(m =>Operator.Arith.Add);binaryArithOper.NewSeqBranch(minus).SetBuilder(m =>Operator.Arith.Subtract);binaryArithOper.NewSeqBranch(multiply).SetBuilder(m =>Operator.Arith.Multiply);binaryArithOper.NewSeqBranch(divide).SetBuilder(m =>Operator.Arith.Divide);unaryArithOper.NewSeqBranch(minus).SetBuilder(m =>Operator.Arith.Negative);binaryLogicalOper.NewSeqBranch(and).SetBuilder(m =>Operator.Logical.And);binaryLogicalOper.NewSeqBranch(or).SetBuilder(m =>Operator.Logical.Or);unaryLogicalOper.NewSeqBranch(not).SetBuilder(m =>Operator.Logical.Not);
#endregion
}}

About

A general-purpose parser framework for C#.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages