// SPARQL/Update // Author: Andy Seaborne andy.seaborne@hp.com // (c) Copyright 2007 Hewlett-Packard Development Company, LP // All rights reserved. // See end of file for details. options { JAVA_UNICODE_ESCAPE = true ; UNICODE_INPUT = false ; STATIC = false ; // DEBUG_PARSER = true ; // DEBUG_TOKEN_MANAGER = true ; } PARSER_BEGIN(SPARULParser) /* * (c) Copyright 2007 Hewlett-Packard Development Company, LP * All rights reserved. */ package com.hp.hpl.jena.sparql.modify.lang.parser ; import com.hp.hpl.jena.graph.* ; //import com.hp.hpl.jena.query.* ; import com.hp.hpl.jena.sparql.syntax.* ; import com.hp.hpl.jena.sparql.expr.* ; import com.hp.hpl.jena.sparql.modify.op.* ; public class SPARULParser extends SPARULParserBase { } PARSER_END(SPARULParser) // SPARQUL parts. TOKEN [IGNORE_CASE] : { | | | | | | | | | | | } void SPARUL() : {} { Prologue() ( //( Update() | Manage() | Transaction() ) ( Update() | Manage() ) ) * } void Update() : { } { ( { UpdatePattern upPat = null ; Element el ; } ( upPat = Modify() | upPat = Insert() | upPat = Delete() ) ( el = WhereClause() { upPat.setPattern(el) ; } )? { getRequest().addUpdate(upPat) ; } ) | ( { Update up = null ; } ( up = Load() | up = Clear() ) { getRequest().addUpdate(up) ; } ) } UpdateModify Modify() : { UpdateModify up = new UpdateModify() ; Node iri ; Template template ; } { ( iri = GraphIRI() { up.addGraphName(iri.getURI()) ; } )* template = ConstructTemplate() { up.setDeleteTemplate(template) ; } template = ConstructTemplate() { up.setInsertTemplate(template) ; } { return new UpdateModify() ; } } UpdatePattern Delete() : { UpdateDelete up = new UpdateDelete() ; Node iri ; Template template ; } { (()? iri = IRIref() { up.addGraphName(iri.getURI()) ; } )* template = ConstructTemplate() { up.setDeleteTemplate(template) ; } { return up ; } } UpdatePattern Insert() : { UpdateInsert up = new UpdateInsert() ; Node iri ; Template template ; } { (()? iri = IRIref() { up.addGraphName(iri.getURI()) ; } )* template = ConstructTemplate() { up.setInsertTemplate(template) ; } { return up ; } } Node GraphIRI() : { Node iri ; } { iri = IRIref() { return iri ; } } UpdateLoad Load() : { UpdateLoad up = new UpdateLoad() ; Node iri ;} { ( iri = IRIref() { up.addLoadIRI(iri.getURI()) ; } )+ ( iri = IRIref() { up.setGraphName(iri.getURI()) ; } )? { return up ; } } UpdateClear Clear() : { UpdateClear up = new UpdateClear(); Node iri ; } { ( iri = GraphIRI() { up.setGraphName(iri.getURI()) ; } )? { return up ; } } void Manage() : { GraphMgt mgt ; } { ( mgt = Create() | mgt = Drop() ) { getRequest().addUpdate(mgt) ; } } UpdateCreate Create() : { boolean silent = false ; Node iri ; } { ( { silent = true ; } )? iri = GraphIRI() { return new UpdateCreate( iri, silent); } } UpdateDrop Drop() : { boolean silent = false ; Node iri ; } { ({ silent = true ; } )? iri = GraphIRI() { return new UpdateDrop(iri, silent) ; } } // void Transaction() : {} // { // TransBegin() | TransCommit() | TransAbort() // } // // void TransBegin() : {} // { // (IRIref())? // { System.out.println("++ Begin") ; } // } // // void TransCommit() : {} // { // (IRIref())? // { System.out.println("++ Commit") ; } // } // // void TransAbort() : {} // { // (IRIref())? // { System.out.println("++ Abort") ; } // } void Prologue() : {} { ( BaseDecl() ) ? ( PrefixDecl() )* } void BaseDecl() : { Node n ; } { n = Q_IRI_REF() { getPrologue().setBaseURI(n.getURI()) ; } } void PrefixDecl() : { Token t ; Node n ; } { t = n = Q_IRI_REF() { String s = fixupPrefix(t.image, t.beginLine, t.beginColumn) ; getPrologue().setPrefix(s, n.getURI()) ; } } Element WhereClause() : { Element el ; } { ()? el = GroupGraphPattern() { return el ; } } // ---- General Graph Pattern Element GroupGraphPattern() : { Element el = null ; } { { ElementGroup elg = new ElementGroup() ; } { startGroup(elg) ; } ( { startTriplesBlock() ; } el = TriplesBlock(null) { endTriplesBlock() ; elg.addElement(el) ; } )? ( ( el = GraphPatternNotTriples() | el = Filter() ) { elg.addElement(el) ; } ()? ( { startTriplesBlock() ; } el = TriplesBlock(null) { endTriplesBlock() ; elg.addElement(el) ; } )? )* { endGroup(elg) ; } { return elg ; } } Element TriplesBlock(ElementTriplesBlock acc) : { } { { if ( acc == null ) acc = new ElementTriplesBlock() ; } TriplesSameSubject(acc) ( (TriplesBlock(acc))? )? { return acc ; } } // ----- Element GraphPatternNotTriples() : { Element el = null ; } { ( el = OptionalGraphPattern() | // "GroupPattern" or "GroupPattern" union "GroupPattern" el = GroupOrUnionGraphPattern() | el = GraphGraphPattern() ) { return el ; } } // ---- Definitions of each pattern element Element OptionalGraphPattern() : { Element el ; } { el = GroupGraphPattern() { return new ElementOptional(null, el) ; } } Element GraphGraphPattern() : { Element el ; Node n ;} { n = VarOrIRIref() el = GroupGraphPattern() { return new ElementNamedGraph(n, el) ; } } // G (union G)* can be a single group pattern // or a group pattern as part of an union. Element GroupOrUnionGraphPattern() : { Element el = null ; ElementUnion el2 = null ; } { el = GroupGraphPattern() ( { if ( el2 == null ) { el2 = new ElementUnion() ; el2.addElement(el) ; } } el = GroupGraphPattern() { el2.addElement(el) ; } )* { return (el2==null)? el : el2 ; } } Element Filter() : { Expr c ; } { c = Constraint() { return new ElementFilter(c) ; } } Expr Constraint() : { Expr c ; } { ( c = BrackettedExpression() | c = BuiltInCall() | c = FunctionCall() ) { return c ; } } Expr FunctionCall() : { Node fname ; ExprList a ; } { fname = IRIref() a = ArgList() { return new E_Function(fname.getURI(), a) ; } } ExprList ArgList() : { Expr expr ; ExprList args = new ExprList() ; } { ( | // Was ( Expression() ( Expression() )* )? expr = Expression() { args.add(expr) ; } ( expr = Expression() { args.add(expr) ; } )* ) { return args ; } } // -------- Construct patterns Template ConstructTemplate() : { } { { TemplateGroup g = new TemplateGroup() ; } (ConstructTriples(g))? { return g ; } } void ConstructTriples(TemplateGroup acc) : { } { TriplesSameSubject(acc) ( (ConstructTriples(acc))? )? } // -------- Triple lists with property and object lists void TriplesSameSubject(TripleCollector acc) : { Node s ; } { s = VarOrTerm() PropertyListNotEmpty(s, acc) | // Any of the triple generating syntax elements s = TriplesNode(acc) PropertyList(s, acc) } void PropertyListNotEmpty(Node s, TripleCollector acc) : { Node p ; } { p = Verb() ObjectList(s, p, acc) ( (p = Verb() ObjectList(s, p, acc))? )* } void PropertyList(Node s, TripleCollector acc) : { } { ( PropertyListNotEmpty(s, acc) ) ? } // // Recursive // void PropertyListNotEmpty(Node s, TripleCollector acc) : { Node p ; } // { // p = Verb() // ObjectList(s, p, acc) // ( PropertyList(s, acc) ) ? // #ifdef ARQ // | // Reification(s, acc) // #endif // } // // Recursive // void ObjectList(Node s, Node p, TripleCollector acc): { Node o ; } // { // { int mark = acc.mark() ; } // o = GraphNode(acc) // { insert(acc, mark, s, p, o) ; } // ( ObjectList(s, p , acc) )? // } void ObjectList(Node s, Node p, TripleCollector acc): { Node o ; } { Object(s, p, acc) ( Object(s, p, acc) )* } void Object(Node s, Node p, TripleCollector acc): { Node o ; } { { int mark = acc.mark() ; } o = GraphNode(acc) { insert(acc, mark, s, p, o) ; } } Node Verb() : {Node p ;} { // ( p = VarOrBlankNodeOrIRIref() | { p = nRDFtype ; } ) ( p = VarOrIRIref() | { p = nRDFtype ; } ) { return p ; } } // -------- Triple expansions // Anything that can stand in a node slot and which is // a number of triples Node TriplesNode(TripleCollector acc) : { Node n ; } { n = Collection(acc) { return n ; } | n = BlankNodePropertyList(acc) { return n ; } } Node BlankNodePropertyList(TripleCollector acc) : { } { { Node n = createBNode() ; } PropertyListNotEmpty(n, acc) { return n ; } } // ------- RDF collections Node Collection(TripleCollector acc) : { Node listHead = nRDFnil ; Node lastCell = null ; int mark ; Node n ; } { ( { Node cell = createListNode() ; if ( listHead == nRDFnil ) listHead = cell ; if ( lastCell != null ) insert(acc, lastCell, nRDFrest, cell) ; mark = acc.mark() ; } n = GraphNode(acc) { insert(acc, mark, cell, nRDFfirst, n) ; lastCell = cell ; } ) + // Not * here - "()" is handled separately. { if ( lastCell != null ) insert(acc, lastCell, nRDFrest, nRDFnil) ; return listHead ; } } // -------- Nodes in a graph pattern or template Node GraphNode(TripleCollector acc) : { Node n ; } { n = VarOrTerm() { return n ; } | n = TriplesNode(acc) { return n ; } } Node VarOrTerm() : {Node n = null ; } { ( n = Var() | n = GraphTerm() ) { return n ; } } // Property (if no bNodes) + DESCRIBE Node VarOrIRIref() : {Node n = null ; } { ( n = Var() | n = IRIref() ) { return n ; } } // // GRAPH and property if including blank nodes are properties. // Node VarOrBlankNodeOrIRIref() : {Node n = null ; } // { // ( n = Var() | n = BlankNode() | n = IRIref() ) // { return n ; } // } Node Var() : { Token t ;} { ( t = | t = ) { return createVariable(t.image, t.beginLine, t.beginColumn) ; } } Node GraphTerm() : { Node n ; } { n = IRIref() { return n ; } | n = RDFLiteral() { return n ; } | n = NumericLiteral() { return n ; } | n = BooleanLiteral() { return n ; } | n = BlankNode() { return n ; } // { return nRDFnil ; } | { return nRDFnil ; } } // -------- Constraint syntax Expr Expression() : { Expr expr ; } { expr = ConditionalOrExpression() { return expr ; } } Expr ConditionalOrExpression() : { Expr expr1, expr2 ; } { expr1 = ConditionalAndExpression() ( expr2 = ConditionalAndExpression() { expr1 = new E_LogicalOr(expr1, expr2) ; } )* { return expr1 ; } } Expr ConditionalAndExpression() : { Expr expr1, expr2 ;} { expr1 = ValueLogical() ( expr2 = ValueLogical() { expr1 = new E_LogicalAnd(expr1, expr2) ; } )* { return expr1 ; } } Expr ValueLogical() : { Expr expr ; } { expr = RelationalExpression() { return expr ; } } Expr RelationalExpression() : { Expr expr1, expr2 ; } { expr1 = NumericExpression() ( expr2 = NumericExpression() { expr1 = new E_Equals(expr1, expr2) ; } | expr2 = NumericExpression() { expr1 = new E_NotEquals(expr1, expr2) ; } | expr2 = NumericExpression() { expr1 = new E_LessThan(expr1, expr2) ; } | expr2 = NumericExpression() { expr1 = new E_GreaterThan(expr1, expr2) ; } | expr2 = NumericExpression() { expr1 = new E_LessThanOrEqual(expr1, expr2) ; } | expr2 = NumericExpression() { expr1 = new E_GreaterThanOrEqual(expr1, expr2) ; } )? { return expr1 ; } } Expr NumericExpression () : { Expr expr ; } { expr = AdditiveExpression() { return expr ; } } Expr AdditiveExpression() : { Expr expr1, expr2 ; Node n ; } { expr1 = MultiplicativeExpression() ( expr2 = MultiplicativeExpression() { expr1 = new E_Add(expr1, expr2) ; } | expr2 = MultiplicativeExpression() { expr1 = new E_Subtract(expr1, expr2) ; } | n = NumericLiteralPositive() { n = stripSign(n) ; expr2 = asExpr(n) ; expr1 = new E_Add(expr1, expr2) ; } | n = NumericLiteralNegative() { n = stripSign(n) ; expr2 = asExpr(n) ; expr1 = new E_Subtract(expr1, expr2) ; } )* { return expr1 ; } } Expr MultiplicativeExpression() : { Expr expr1, expr2 ; } { expr1 = UnaryExpression() ( expr2 = UnaryExpression() { expr1 = new E_Multiply(expr1, expr2) ; } | expr2 = UnaryExpression() { expr1 = new E_Divide(expr1, expr2) ; } // | expr2 = UnaryExpression() // { expr1 = new E_Modulus(expr1, expr2) ; } )* { return expr1 ; } } Expr UnaryExpression() : { Expr expr ; } { expr = PrimaryExpression() { return new E_LogicalNot(expr) ; } | expr = PrimaryExpression() { return new E_UnaryPlus(expr) ; } | expr = PrimaryExpression() { return new E_UnaryMinus(expr) ; } | expr = PrimaryExpression() { return expr ; } } Expr PrimaryExpression() : { Expr expr ; Node gn ; } { ( expr = BrackettedExpression() { return expr ; } | expr = BuiltInCall() { return expr ; } | expr = IRIrefOrFunction() { return expr ; } // NOT | gn = VarOrTerm() { return asExpr(gn) ; } // Because of IRIrefOrFunction vs and blank nodes | gn = RDFLiteral() { return asExpr(gn) ; } | gn = NumericLiteral() { return asExpr(gn) ; } | gn = BooleanLiteral() { return asExpr(gn) ; } | gn = Var() { return asExpr(gn) ; } ) } Expr BrackettedExpression() : { Expr expr ; } { expr = Expression() { return expr ; } } Expr BuiltInCall() : { Expr expr ; Expr expr1, expr2 ; Node gn ; Token t ;} { // STR expr = Expression() { return new E_Str(expr) ; } | // Lang expr = Expression() { return new E_Lang(expr) ; } |// Langmatches expr1 = Expression() expr2 = Expression() { return new E_LangMatches(expr1, expr2) ; } | // Datatype expr = Expression() { return new E_Datatype(expr) ; } | gn = Var() { return new E_Bound(new NodeVar(gn)) ; } | expr1 = Expression() expr2 = Expression() { return new E_SameTerm(expr1, expr2) ; } | t = expr = Expression() { return new E_IsIRI(expr) ; } | t = expr = Expression() { return new E_IsURI(expr) ; } | expr = Expression() { return new E_IsBlank(expr) ; } | expr = Expression() { return new E_IsLiteral(expr) ; } | // Regular expression matcher expr = RegexExpression() { return expr ; } } Expr RegexExpression() : { Expr expr ; Expr patExpr = null ; Expr flagsExpr = null ; } { expr = Expression() patExpr = Expression() ( flagsExpr = Expression() ) ? { return new E_Regex(expr, patExpr, flagsExpr) ; } } // The case of "q:name()" or just "q:name" // by expanding out FunctionCall() Expr IRIrefOrFunction() : {Node gn ; ExprList a = null ; } { gn = IRIref() ( a = ArgList() )? { if ( a == null ) return asExpr(gn) ; return new E_Function(gn.getURI(), a) ; } } Node RDFLiteral() : { Token t ; String lex = null ; } { lex = String() // Optional lang tag and datatype. { String lang = null ; Node uri = null ; } ( ( t = { lang = stripChars(t.image, 1) ; } ) | ( uri = IRIref() ) )? { return makeNode(lex, lang, uri) ; } } Node NumericLiteral() : { Node n ; } { ( n = NumericLiteralUnsigned() | n = NumericLiteralPositive() | n = NumericLiteralNegative() ) { return n ; } } Node NumericLiteralUnsigned() : { Token t ; } { t = { return makeNodeInteger(t.image) ; } | t = { return makeNodeDecimal(t.image) ; } | t = { return makeNodeDouble(t.image) ; } } Node NumericLiteralPositive() : { Token t ; } { t = { return makeNodeInteger(t.image) ; } | t = { return makeNodeDecimal(t.image) ; } | t = { return makeNodeDouble(t.image) ; } } Node NumericLiteralNegative() : { Token t ; } { t = { return makeNodeInteger(t.image) ; } | t = { return makeNodeDecimal(t.image) ; } | t = { return makeNodeDouble(t.image) ; } } Node BooleanLiteral() : {} { { return XSD_TRUE ; } | { return XSD_FALSE ; } } String String() : { Token t ; String lex ; } { ( t = { lex = stripQuotes(t.image) ; } | t = { lex = stripQuotes(t.image) ; } | t = { lex = stripQuotes3(t.image) ; } | t = { lex = stripQuotes3(t.image) ; } ) { lex = unescapeStr(lex, t.beginLine, t.beginColumn) ; return lex ; } } Node IRIref() : { Node n ; } { n = Q_IRI_REF() { return n ; } | n = QName() { return n ; } } Node QName() : { Token t ; } { ( t = { return createNodeFromPrefixedName(t.image, t.beginLine, t.beginColumn) ; } | t = { return createNodeFromPrefixedName(t.image, t.beginLine, t.beginColumn) ; } ) } Node BlankNode() : { Token t = null ; } { t = { return createBNode(t.image, t.beginLine, t.beginColumn) ; } | // { return createBNode() ; } { return createBNode() ; } } Node Q_IRI_REF() : { Token t ; } { t = { return createNodeFromURI(t.image, t.beginLine, t.beginColumn) ; } } // ------------------------------------------ // Tokens // Comments and whitespace SKIP : { " " | "\t" | "\n" | "\r" | "\f" } TOKEN: { <#WS: " " | "\t" | "\n" | "\r" | "\f"> } SPECIAL_TOKEN : { } // Main tokens */ TOKEN: { // Includes # for relative URIs ","<","\u0000"-"\u0020"])* ">" > | )? ":" > | > | > //| > | > | > | ()+("-" ()+)* > | <#A2Z: ["a"-"z","A"-"Z"]> | <#A2ZN: ["a"-"z","A"-"Z","0"-"9"]> } // ------------------------------------------------- // Keyworks : includes operators that are words and should be // before general things like IDENTIFIER which swallow almost // anything TOKEN : { } // Before HEX rule! TOKEN [IGNORE_CASE] : { // Prologue < BASE: "base" > | < PREFIX: "prefix" > // Result forms | < SELECT: "select" > | < DISTINCT: "distinct" > | < DESCRIBE: "describe" > | < CONSTRUCT: "construct" > | < ASK: "ask" > | < LIMIT: "limit" > | < OFFSET: "offset" > | < ORDER: "order" > | < BY: "by" > | < ASC: "asc" > | < DESC: "desc" > // Dataset | < NAMED: "named" > | < FROM: "from" > // Graph pattern operators | < WHERE: "where" > | < AND: "and" > | < GRAPH: "graph" > | < OPTIONAL: "optional" > | < UNION: "union" > | < FILTER: "filter" > // Expression operators | < BOUND: "bound" > | < STR: "str" > // | < URI: "uri" > | < DTYPE: "datatype" > | < LANG: "lang" > | < LANGMATCHES: "langmatches" > //| < IS_IRI: ("isIRI"|"isURI") > | < IS_URI: "isURI" > | < IS_IRI: "isIRI" > | < IS_BLANK: "isBlank" > | < IS_LITERAL: "isLiteral" > | < REGEX: "regex" > | < SAME_TERM: "sameTerm" > | | } // ------------------------------------------------- TOKEN : { < INTEGER: > | // Be careful to bracket the digits part if +/- added < DECIMAL: ( "." ()* | "." ) > // Required exponent. | < DOUBLE: ( (["0"-"9"])+ "." (["0"-"9"])* | "." (["0"-"9"])+ () | (["0"-"9"])+ ) > | < INTEGER_POSITIVE: > | < DECIMAL_POSITIVE: > | < DOUBLE_POSITIVE: > | < INTEGER_NEGATIVE: > | < DECIMAL_NEGATIVE: > | < DOUBLE_NEGATIVE: > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < #QUOTE_3D: "\"\"\""> | < #QUOTE_3S: "'''"> | | < STRING_LITERAL1: // Single quoted string "'" ( (~["'","\\","\n","\r"]) | )* "'" > | < STRING_LITERAL2: // Double quoted string "\"" ( (~["\"","\\","\n","\r"]) | )* "\"" > | < STRING_LITERAL_LONG1: ( ("'" | "''")? (~["'","\\"] | ))* > | < STRING_LITERAL_LONG2: ( ("\"" | "\"\"")? (~["\"","\\"] | ))* > | < DIGITS: (["0"-"9"])+> //| } TOKEN : { < LPAREN: "(" > | < RPAREN: ")" > // I don't know why white space is needed to be included here but not ANON | (|)* > | < LBRACE: "{" > | < RBRACE: "}" > | < LBRACKET: "[" > | < RBRACKET: "]" > // ()* is not needed but is in NIL | < ANON: (|)* > | < SEMICOLON: ";" > | < COMMA: "," > | < DOT: "." > } // Operator TOKEN : { < EQ: "=" > | < NE: "!=" > | < GT: ">" > | < LT: "<" > | < LE: "<=" > // Maybe: | "=>" > | < GE: ">=" > // Maybe: | "=<" > | < BANG: "!" > | < TILDE: "~" > | < COLON: ":" > | < SC_OR: "||" > | < SC_AND: "&&" > | < PLUS: "+" > | < MINUS: "-" > | < STAR: "*" > | < SLASH: "/" > //| < AMP: "&" > //| < REM: "%" > | < DATATYPE: "^^"> | < AT: "@"> } // See XML chars.txt for notes TOKEN: { // XML 1.1 NCNameStartChar without "_" <#NCCHAR1P: ["A"-"Z"] | ["a"-"z"] | ["\u00C0"-"\u00D6"] | ["\u00D8"-"\u00F6"] | ["\u00F8"-"\u02FF"] | ["\u0370"-"\u037D"] | ["\u037F"-"\u1FFF"] | ["\u200C"-"\u200D"] | ["\u2070"-"\u218F"] | ["\u2C00"-"\u2FEF"] | ["\u3001"-"\uD7FF"] | ["\uF900"-"\uFFFD"] > // [#x10000-#xEFFFF] | <#NCCHAR1: | "_" > // No trailing DOTs in qnames. | // #NCCHAR without "." <#NCCHAR: ( | "-" | ["0"-"9"] | "\u00B7" | ["\u0300"-"\u036F"] | ["\u203F"-"\u2040"] ) > | // NCNAME but no leading "_", no trailing ".", can have dot inside prefix name. <#NCNAME_PREFIX: ((|".")* )? > | // With a leading "_", no dot at end of local name. <#NCNAME: ((|".")* )? > | // NCNAME without "-" and ".", allowing leading digits. <#VARNAME: ( | ["0"-"9"] ) ( | ["0"-"9"] | "\u00B7" | ["\u0300"-"\u036F"] | ["\u203F"-"\u2040"] )* > } // Catch-all tokens. Must be last. // Any non-whitespace. Causes a parser exception, rather than a // token manager error (with hidden line numbers). // Only bad IRIs (e.g. spaces) now give unhelpful parse errors. TOKEN: { <#UNKNOWN: (~[" ","\t","\n","\r","\f" ])+ > } /* * (c) Copyright 2007 Hewlett-Packard Development Company, LP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* # Local Variables: # tab-width: 4 # indent-tabs-mode: nil # comment-default-style: "//" # End: */