Skip to content

Instantly share code, notes, and snippets.

@JoshClose
Last active August 29, 2015 14:08
Show Gist options
  • Save JoshClose/b1635db1ba55129e0a29 to your computer and use it in GitHub Desktop.
Save JoshClose/b1635db1ba55129e0a29 to your computer and use it in GitHub Desktop.
using Irony.Parsing;
namespace Irony.Samples.SQLite
{
[Language( "SQLite", "3", "SQLite Grammar" )]
// ReSharper disable once InconsistentNaming
public class SQLiteGrammar : Grammar
{
public SQLiteGrammar() : base( false )
{
var lineComment = new CommentTerminal( "line_comment", "--", "\r\n", "\n" );
var comment = new CommentTerminal( "comment", "/*", "*/" );
NonGrammarTerminals.Add( comment );
NonGrammarTerminals.Add( lineComment );
var numericLiteral = new NumberLiteral( "number" );
var stringLiteral = new StringLiteral( "string", "'", StringOptions.AllowsDoubledQuote );
var blobLiteral = new NonTerminal( "blob" );
blobLiteral.Rule = "x" + stringLiteral;
// Covers normal identifiers (abc) and quoted id's ([abc d], "abc d")
var idSimple = TerminalFactory.CreateSqlExtIdentifier( this, "idSimple" );
var comma = ToTerm( "," );
var dot = ToTerm( "." );
var semi = ToTerm( ";" );
// ReSharper disable InconsistentNaming
var ABORT = ToTerm( "ABORT" );
var ACTION = ToTerm( "ACTION" );
var ADD = ToTerm( "ADD" );
var AFTER = ToTerm( "AFTER" );
var ALL = ToTerm( "ALL" );
var ALTER = ToTerm( "ALTER" );
var ANALYZE = ToTerm( "ANALYZE" );
var AND = ToTerm( "AND" );
var AS = ToTerm( "AS" );
var ASC = ToTerm( "ASC" );
var ATTACH = ToTerm( "ATTACH" );
var AUTOINCREMENT = ToTerm( "AUTOINCREMENT" );
var BEFORE = ToTerm( "BEFORE" );
var BEGIN = ToTerm( "BEGIN" );
var BETWEEN = ToTerm( "BETWEEN" );
var BY = ToTerm( "BY" );
var CASCADE = ToTerm( "CASCADE" );
var CASE = ToTerm( "CASE" );
var CAST = ToTerm( "CAST" );
var CHECK = ToTerm( "CHECK" );
var COLLATE = ToTerm( "COLLATE" );
var COLUMN = ToTerm( "COLUMN" );
var COMMIT = ToTerm( "COMMIT" );
var CONFLICT = ToTerm( "CONFLICT" );
var CONSTRAINT = ToTerm( "CONSTRAINT" );
var CREATE = ToTerm( "CREATE" );
var CROSS = ToTerm( "CROSS" );
var CURRENT_DATE = ToTerm( "CURRENT_DATE" );
var CURRENT_TIME = ToTerm( "CURRENT_TIME" );
var CURRENT_TIMESTAMP = ToTerm( "CURRENT_TIMESTAMP" );
var DATABASE = ToTerm( "DATABASE" );
var DEFAULT = ToTerm( "DEFAULT" );
var DEFERRABLE = ToTerm( "DEFERRABLE" );
var DEFERRED = ToTerm( "DEFERRED" );
var DELETE = ToTerm( "DELETE" );
var DESC = ToTerm( "DESC" );
var DETACH = ToTerm( "DETACH" );
var DISTINCT = ToTerm( "DISTINCT" );
var DROP = ToTerm( "DROP" );
var EACH = ToTerm( "EACH" );
var ELSE = ToTerm( "ELSE" );
var END = ToTerm( "END" );
var ESCAPE = ToTerm( "ESCAPE" );
var EXCEPT = ToTerm( "EXCEPT" );
var EXCLUSIVE = ToTerm( "EXCLUSIVE" );
var EXISTS = ToTerm( "EXISTS" );
var EXPLAIN = ToTerm( "EXPLAIN" );
var FAIL = ToTerm( "FAIL" );
var FOR = ToTerm( "FOR" );
var FOREIGN = ToTerm( "FOREIGN" );
var FROM = ToTerm( "FROM" );
var FULL = ToTerm( "FULL" );
var GLOB = ToTerm( "GLOB" );
var GROUP = ToTerm( "GROUP" );
var HAVING = ToTerm( "HAVING" );
var IF = ToTerm( "IF" );
var IGNORE = ToTerm( "IGNORE" );
var IMMEDIATE = ToTerm( "IMMEDIATE" );
var IN = ToTerm( "IN" );
var INDEX = ToTerm( "INDEX" );
var INDEXED = ToTerm( "INDEXED" );
var INITIALLY = ToTerm( "INTIALLY" );
var INNER = ToTerm( "INNER" );
var INSERT = ToTerm( "INSERT" );
var INSTEAD = ToTerm( "INSTEAD" );
var INTERSECT = ToTerm( "INTERSECT" );
var INTO = ToTerm( "INTO" );
var IS = ToTerm( "IS" );
var ISNULL = ToTerm( "ISNULL" );
var JOIN = ToTerm( "JOIN" );
var KEY = ToTerm( "KEY" );
var LEFT = ToTerm( "LEFT" );
var LIKE = ToTerm( "LIKE" );
var LIMIT = ToTerm( "LIMIT" );
var MATCH = ToTerm( "MATCH" );
var NATURAL = ToTerm( "NATURAL" );
var NO = ToTerm( "NO" );
var NOT = ToTerm( "NOT" );
var NOTNULL = ToTerm( "NOTNULL" );
var NULL = ToTerm( "NULL" );
var OF = ToTerm( "OF" );
var OFFSET = ToTerm( "OFFSET" );
var ON = ToTerm( "ON" );
var OR = ToTerm( "OR" );
var ORDER = ToTerm( "ORDER" );
var OUTER = ToTerm( "OUTER" );
var PLAN = ToTerm( "PLAN" );
var PRAGMA = ToTerm( "PRAGMA" );
var PRIMARY = ToTerm( "PRIMARY" );
var QUERY = ToTerm( "QUERY" );
var RAISE = ToTerm( "RAISE" );
var RECURSIVE = ToTerm( "RECURSIVE" );
var REFERENCES = ToTerm( "REFERENCES" );
var REGEXP = ToTerm( "REGEXP" );
var REINDEX = ToTerm( "REINDEX" );
var RELEASE = ToTerm( "RELEASE" );
var RENAME = ToTerm( "RENAME" );
var REPLACE = ToTerm( "REPLACE" );
var RESTRICT = ToTerm( "RESTRICT" );
var RIGHT = ToTerm( "RIGHT" );
var ROLLBACK = ToTerm( "ROLLBACK" );
var ROW = ToTerm( "ROW" );
var ROWID = ToTerm( "ROWID" );
var SAVEPOINT = ToTerm( "SAVEPOINT" );
var SELECT = ToTerm( "SELECT" );
var SET = ToTerm( "SET" );
var TABLE = ToTerm( "TABLE" );
var TEMP = ToTerm( "TEMP" );
var TEMPORARY = ToTerm( "TEMPORARY" );
var THEN = ToTerm( "THEN" );
var TO = ToTerm( "TO" );
var TRANSACTION = ToTerm( "TRANSACTION" );
var TRIGGER = ToTerm( "TRIGGER" );
var UNION = ToTerm( "UNION" );
var UNIQUE = ToTerm( "UNIQUE" );
var UPDATE = ToTerm( "UPADTE" );
var USING = ToTerm( "USING" );
var VACUUM = ToTerm( "VACUUM" );
var VALUES = ToTerm( "VALUES" );
var VIEW = ToTerm( "VIEW" );
var VIRTUAL = ToTerm( "VIRTUAL" );
var WHEN = ToTerm( "WHEN" );
var WHERE = ToTerm( "WHERE" );
var WITH = ToTerm( "WITH" );
var WITHOUT = ToTerm( "WITHOUT" );
// ReSharper restore InconsistentNaming
var sqlStmtList = new NonTerminal( "sql-stmt-list" );
var sqlStmt = new NonTerminal( "sql-stmt" );
var alterTableStmt = new NonTerminal( "alter-table-stmt" );
var analyzeStmt = new NonTerminal( "analyze-stmt" );
var attachStmt = new NonTerminal( "attach-stmt" );
var beginStmt = new NonTerminal( "begin-stmt" );
var commitStmt = new NonTerminal( "commit-stmt" );
var rollbackStmt = new NonTerminal( "rollback-stmt" );
var savepointStmt = new NonTerminal( "savepoint-stmt" );
var releaseStmt = new NonTerminal( "release-stmt" );
var createIndexStmt = new NonTerminal( "create-index-stmt" );
var indexedColumn = new NonTerminal( "indexed-column" );
var createTableStmt = new NonTerminal( "create-table-stmt" );
var columnDef = new NonTerminal( "column-def" );
var typeName = new NonTerminal( "type-name" );
var columnConstraint = new NonTerminal( "column-constraint" );
var signedNumber = new NonTerminal( "signed-number" );
var tableConstraint = new NonTerminal( "table-constraint" );
var foreignKeyClause = new NonTerminal( "foreign-key-clause" );
var conflictClause = new NonTerminal( "conflict-clause" );
var createTriggerStmt = new NonTerminal( "create-trigger-stmt" );
var createViewStmt = new NonTerminal( "create-view-stmt" );
var createVirtualTableStmt = new NonTerminal( "create-virtual-table-stmt" );
var withClause = new NonTerminal( "with-clause" );
var cteTableName = new NonTerminal( "cte-table-name" );
var recursiveCte = new NonTerminal( "recursive-cte" );
var commonTableExpression = new NonTerminal( "common-table-expression" );
var deleteStmt = new NonTerminal( "delete-stmt" );
var deleteStmtLimited = new NonTerminal( "delete-stmt-limited" );
var detachStmt = new NonTerminal( "detach-stmt" );
var dropIndexStmt = new NonTerminal( "drop-index-stmt" );
var dropTableStmt = new NonTerminal( "drop-table-stmt" );
var dropTriggerStmt = new NonTerminal( "drop-trigger-stmt" );
var dropViewStmt = new NonTerminal( "drop-view-stmt" );
var expr = new NonTerminal( "expr" );
var raiseFunction = new NonTerminal( "raise-function" );
var literalValue = new NonTerminal( "literal-value" );
// Handled already by 'number'.
//var numericLiteral = new NonTerminal( "numeric-literal" );
var insertStmt = new NonTerminal( "insert-stmt" );
var pragmaStmt = new NonTerminal( "pragma-stmt" );
var pragmaValue = new NonTerminal( "pragma-value" );
var reindexStmt = new NonTerminal( "reindex-stmt" );
var selectStmt = new NonTerminal( "select-stmt" );
var joinClause = new NonTerminal( "join-clause" );
var selectCore = new NonTerminal( "select-core" );
var factoredSelectStmt = new NonTerminal( "factoredSelectStmt" );
var simpleSelectStmt = new NonTerminal( "simple-select-stmt" );
var compoundSelectStmt = new NonTerminal( "compound-select-stmt" );
var tableOrSubquery = new NonTerminal( "table-or-subquery" );
var resultColumn = new NonTerminal( "result-column" );
var joinOperator = new NonTerminal( "join-operator" );
var joinConstraint = new NonTerminal( "join-constraint" );
var orderingTerm = new NonTerminal( "ordering-term" );
var compoundOperator = new NonTerminal( "compound-operator" );
var updateStmt = new NonTerminal( "update-stmt" );
var updateStmtLimited = new NonTerminal( "update-stmt-limited" );
var qualifiedTableName = new NonTerminal( "qualified-table-name" );
var vacuumStmt = new NonTerminal( "vacuum-stmt" );
// Handled already by CommentTerminal().
//var commentSyntax = new NonTerminal( "comment-syntax" );
var id = new NonTerminal( "id" );
var idSimpleListCommaPlus = new NonTerminal( "idSimpleListCommaPlus" );
var binaryOperator = new NonTerminal( "binaryOperator" );
var unaryOperator = new NonTerminal( "unaryOperator" );
var binaryExpr = new NonTerminal( "binaryExpr" );
var unaryExpr = new NonTerminal( "unaryExpr" );
var selectRestrictOpt = new NonTerminal( "selectRestrictOpt" );
var resultColumnListCommaPlus = new NonTerminal( "resultColumnListCommaPlus" );
var columnAliasOpt = new NonTerminal( "columnAliasOpt" );
var asOpt = new NonTerminal( "asOpt" );
var fromClause = new NonTerminal( "fromClause" );
var tableOrSubqueryListCommaPlus = new NonTerminal( "tableOrSubqueryListCommaPlus" );
var indexedClause = new NonTerminal( "indexedClause" );
var naturalOpt = new NonTerminal( "naturalOpt" );
var joinType = new NonTerminal( "joinType" );
var outerOpt = new NonTerminal( "outerOpt" );
var whereClause = new NonTerminal( "whereClause" );
var groupClause = new NonTerminal( "groupClause" );
var exprListCommaPlus = new NonTerminal( "exprListCommaPlus" );
var exprListCommaPlusParen = new NonTerminal( "exprListCommaPlusParen" );
var exprListCommaPlusParenListCommaPlus = new NonTerminal( "exprListCommaPlusParenListCommaPlus" );
Root = sqlStmtList;
// Identifiers
id.Rule = MakePlusRule( id, dot, idSimple );
idSimpleListCommaPlus.Rule = MakePlusRule( idSimpleListCommaPlus, comma, idSimple );
// Operators
binaryOperator.Rule = ToTerm( "||" ) | "*" | "/" | "%" | "+" | "-" | "<<" | ">>" | "&" | "|" | "<" | "<=" | ">" | ">=" | "=" | "==" | "!=" | "<>"
| IS | IS + PreferShiftHere() + NOT | IN | LIKE | GLOB | MATCH | REGEXP | AND | OR;
unaryOperator.Rule = ToTerm( "-" ) | "+" | "~" | NOT;
// Optional
asOpt.Rule = Empty | AS;
columnAliasOpt.Rule = Empty | asOpt + idSimple;
selectRestrictOpt.Rule = Empty | DISTINCT | ALL;
naturalOpt.Rule = Empty | NATURAL;
outerOpt.Rule = Empty | OUTER;
// SQLite BNF
// sql-stmt-list
sqlStmtList.Rule = MakeStarRule( sqlStmtList, semi, sqlStmt );
// sql-stmt
sqlStmt.Rule = selectStmt;
// expr
expr.Rule = literalValue
| id
| unaryExpr
| binaryExpr
;
unaryExpr.Rule = unaryOperator + expr;
binaryExpr.Rule = expr + binaryOperator + expr;
exprListCommaPlus.Rule = MakePlusRule( exprListCommaPlus, comma, expr );
exprListCommaPlusParen.Rule = "(" + exprListCommaPlus + ")";
exprListCommaPlusParenListCommaPlus.Rule = MakePlusRule( exprListCommaPlus, comma, exprListCommaPlusParen );
// literal-value
literalValue.Rule = numericLiteral
| stringLiteral
| blobLiteral
| NULL
| CURRENT_TIME
| CURRENT_DATE
| CURRENT_TIMESTAMP;
// select-stmt
selectStmt.Rule = selectCore;
// join-clause
joinClause.Rule = tableOrSubquery + joinOperator + tableOrSubquery + joinConstraint;
// select-core
selectCore.Rule = SELECT + selectRestrictOpt + resultColumnListCommaPlus + fromClause + whereClause + groupClause
| VALUES + exprListCommaPlusParenListCommaPlus;
fromClause.Rule = Empty
| FROM + tableOrSubqueryListCommaPlus
| FROM + joinClause;
whereClause.Rule = Empty | WHERE + expr;
groupClause.Rule = Empty
| GROUP + BY + exprListCommaPlus
| GROUP + BY + exprListCommaPlus + HAVING + expr;
// table-or-subquery
tableOrSubquery.Rule = id + columnAliasOpt + indexedClause
| "(" + ( tableOrSubqueryListCommaPlus | joinClause ) + ")"
| "(" + selectStmt + ")" + columnAliasOpt;
tableOrSubqueryListCommaPlus.Rule = MakePlusRule( tableOrSubqueryListCommaPlus, comma, tableOrSubquery );
indexedClause.Rule = Empty | INDEXED + BY + idSimple | NOT + INDEXED;
// result-column
resultColumn.Rule = "*"
| idSimple + PreferShiftHere() + dot + "*"
| expr + columnAliasOpt;
resultColumnListCommaPlus.Rule = MakePlusRule( resultColumnListCommaPlus, comma, resultColumn );
// join-operator
joinOperator.Rule = naturalOpt + joinType + JOIN;
joinType.Rule = Empty
| LEFT + outerOpt
| INNER
| CROSS;
// join-constraint
joinConstraint.Rule = Empty
| ON + expr
| USING + "(" + idSimpleListCommaPlus + ")";
RegisterOperators( 10, "||" );
RegisterOperators( 9, "*", "/", "%" );
RegisterOperators( 8, "+", "-" );
RegisterOperators( 7, "<<", ">>", "&", "|" );
RegisterOperators( 6, "<", "<=", ">", ">=" );
RegisterOperators( 5, "=", "==", "!=", "<>" );
RegisterOperators( 5, IS, /*IS + NOT,*/ IN, LIKE, GLOB, MATCH, REGEXP );
RegisterOperators( 4, AND );
RegisterOperators( 3, OR );
MarkPunctuation( ",", "(", ")" );
MarkPunctuation( asOpt );
MarkTransient( selectStmt, expr, asOpt, columnAliasOpt, unaryOperator, selectRestrictOpt );
binaryOperator.SetFlag( TermFlags.InheritPrecedence );
// TODO: Double check that all the parens are in code here.
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment